diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 74 |
1 files changed, 52 insertions, 22 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9d992b0346e3..1ff76acc7e98 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -50,6 +50,8 @@ | |||
50 | #include <linux/module.h> | 50 | #include <linux/module.h> |
51 | #include <linux/sunrpc/bc_xprt.h> | 51 | #include <linux/sunrpc/bc_xprt.h> |
52 | #include <linux/xattr.h> | 52 | #include <linux/xattr.h> |
53 | #include <linux/utsname.h> | ||
54 | #include <linux/mm.h> | ||
53 | 55 | ||
54 | #include "nfs4_fs.h" | 56 | #include "nfs4_fs.h" |
55 | #include "delegation.h" | 57 | #include "delegation.h" |
@@ -3251,6 +3253,35 @@ static void buf_to_pages(const void *buf, size_t buflen, | |||
3251 | } | 3253 | } |
3252 | } | 3254 | } |
3253 | 3255 | ||
3256 | static int buf_to_pages_noslab(const void *buf, size_t buflen, | ||
3257 | struct page **pages, unsigned int *pgbase) | ||
3258 | { | ||
3259 | struct page *newpage, **spages; | ||
3260 | int rc = 0; | ||
3261 | size_t len; | ||
3262 | spages = pages; | ||
3263 | |||
3264 | do { | ||
3265 | len = min(PAGE_CACHE_SIZE, buflen); | ||
3266 | newpage = alloc_page(GFP_KERNEL); | ||
3267 | |||
3268 | if (newpage == NULL) | ||
3269 | goto unwind; | ||
3270 | memcpy(page_address(newpage), buf, len); | ||
3271 | buf += len; | ||
3272 | buflen -= len; | ||
3273 | *pages++ = newpage; | ||
3274 | rc++; | ||
3275 | } while (buflen != 0); | ||
3276 | |||
3277 | return rc; | ||
3278 | |||
3279 | unwind: | ||
3280 | for(; rc > 0; rc--) | ||
3281 | __free_page(spages[rc-1]); | ||
3282 | return -ENOMEM; | ||
3283 | } | ||
3284 | |||
3254 | struct nfs4_cached_acl { | 3285 | struct nfs4_cached_acl { |
3255 | int cached; | 3286 | int cached; |
3256 | size_t len; | 3287 | size_t len; |
@@ -3419,13 +3450,23 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
3419 | .rpc_argp = &arg, | 3450 | .rpc_argp = &arg, |
3420 | .rpc_resp = &res, | 3451 | .rpc_resp = &res, |
3421 | }; | 3452 | }; |
3422 | int ret; | 3453 | int ret, i; |
3423 | 3454 | ||
3424 | if (!nfs4_server_supports_acls(server)) | 3455 | if (!nfs4_server_supports_acls(server)) |
3425 | return -EOPNOTSUPP; | 3456 | return -EOPNOTSUPP; |
3457 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | ||
3458 | if (i < 0) | ||
3459 | return i; | ||
3426 | nfs_inode_return_delegation(inode); | 3460 | nfs_inode_return_delegation(inode); |
3427 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | ||
3428 | ret = nfs4_call_sync(server, &msg, &arg, &res, 1); | 3461 | ret = nfs4_call_sync(server, &msg, &arg, &res, 1); |
3462 | |||
3463 | /* | ||
3464 | * Free each page after tx, so the only ref left is | ||
3465 | * held by the network stack | ||
3466 | */ | ||
3467 | for (; i > 0; i--) | ||
3468 | put_page(pages[i-1]); | ||
3469 | |||
3429 | /* | 3470 | /* |
3430 | * Acl update can result in inode attribute update. | 3471 | * Acl update can result in inode attribute update. |
3431 | * so mark the attribute cache invalid. | 3472 | * so mark the attribute cache invalid. |
@@ -4572,27 +4613,16 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4572 | *p = htonl((u32)clp->cl_boot_time.tv_nsec); | 4613 | *p = htonl((u32)clp->cl_boot_time.tv_nsec); |
4573 | args.verifier = &verifier; | 4614 | args.verifier = &verifier; |
4574 | 4615 | ||
4575 | while (1) { | 4616 | args.id_len = scnprintf(args.id, sizeof(args.id), |
4576 | args.id_len = scnprintf(args.id, sizeof(args.id), | 4617 | "%s/%s.%s/%u", |
4577 | "%s/%s %u", | 4618 | clp->cl_ipaddr, |
4578 | clp->cl_ipaddr, | 4619 | init_utsname()->nodename, |
4579 | rpc_peeraddr2str(clp->cl_rpcclient, | 4620 | init_utsname()->domainname, |
4580 | RPC_DISPLAY_ADDR), | 4621 | clp->cl_rpcclient->cl_auth->au_flavor); |
4581 | clp->cl_id_uniquifier); | ||
4582 | |||
4583 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | ||
4584 | |||
4585 | if (status != -NFS4ERR_CLID_INUSE) | ||
4586 | break; | ||
4587 | |||
4588 | if (signalled()) | ||
4589 | break; | ||
4590 | |||
4591 | if (++clp->cl_id_uniquifier == 0) | ||
4592 | break; | ||
4593 | } | ||
4594 | 4622 | ||
4595 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); | 4623 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); |
4624 | if (!status) | ||
4625 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); | ||
4596 | dprintk("<-- %s status= %d\n", __func__, status); | 4626 | dprintk("<-- %s status= %d\n", __func__, status); |
4597 | return status; | 4627 | return status; |
4598 | } | 4628 | } |