aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c74
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
3256static 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
3279unwind:
3280 for(; rc > 0; rc--)
3281 __free_page(spages[rc-1]);
3282 return -ENOMEM;
3283}
3284
3254struct nfs4_cached_acl { 3285struct 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}