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.c127
1 files changed, 87 insertions, 40 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a99a8d948721..1e50326d00dd 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3215,11 +3215,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
3215 dentry->d_parent->d_name.name, 3215 dentry->d_parent->d_name.name,
3216 dentry->d_name.name, 3216 dentry->d_name.name,
3217 (unsigned long long)cookie); 3217 (unsigned long long)cookie);
3218 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); 3218 nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args);
3219 res.pgbase = args.pgbase; 3219 res.pgbase = args.pgbase;
3220 status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); 3220 status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
3221 if (status >= 0) { 3221 if (status >= 0) {
3222 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); 3222 memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE);
3223 status += args.pgbase; 3223 status += args.pgbase;
3224 } 3224 }
3225 3225
@@ -3653,11 +3653,11 @@ static inline int nfs4_server_supports_acls(struct nfs_server *server)
3653 && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL); 3653 && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
3654} 3654}
3655 3655
3656/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that 3656/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that
3657 * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on 3657 * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_SIZE) bytes on
3658 * the stack. 3658 * the stack.
3659 */ 3659 */
3660#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT) 3660#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE)
3661 3661
3662static int buf_to_pages_noslab(const void *buf, size_t buflen, 3662static int buf_to_pages_noslab(const void *buf, size_t buflen,
3663 struct page **pages, unsigned int *pgbase) 3663 struct page **pages, unsigned int *pgbase)
@@ -3668,7 +3668,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen,
3668 spages = pages; 3668 spages = pages;
3669 3669
3670 do { 3670 do {
3671 len = min_t(size_t, PAGE_CACHE_SIZE, buflen); 3671 len = min_t(size_t, PAGE_SIZE, buflen);
3672 newpage = alloc_page(GFP_KERNEL); 3672 newpage = alloc_page(GFP_KERNEL);
3673 3673
3674 if (newpage == NULL) 3674 if (newpage == NULL)
@@ -3737,9 +3737,10 @@ out:
3737static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) 3737static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)
3738{ 3738{
3739 struct nfs4_cached_acl *acl; 3739 struct nfs4_cached_acl *acl;
3740 size_t buflen = sizeof(*acl) + acl_len;
3740 3741
3741 if (pages && acl_len <= PAGE_SIZE) { 3742 if (buflen <= PAGE_SIZE) {
3742 acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); 3743 acl = kmalloc(buflen, GFP_KERNEL);
3743 if (acl == NULL) 3744 if (acl == NULL)
3744 goto out; 3745 goto out;
3745 acl->cached = 1; 3746 acl->cached = 1;
@@ -3781,17 +3782,15 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
3781 .rpc_argp = &args, 3782 .rpc_argp = &args,
3782 .rpc_resp = &res, 3783 .rpc_resp = &res,
3783 }; 3784 };
3784 int ret = -ENOMEM, npages, i; 3785 unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
3785 size_t acl_len = 0; 3786 int ret = -ENOMEM, i;
3786 3787
3787 npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
3788 /* As long as we're doing a round trip to the server anyway, 3788 /* As long as we're doing a round trip to the server anyway,
3789 * let's be prepared for a page of acl data. */ 3789 * let's be prepared for a page of acl data. */
3790 if (npages == 0) 3790 if (npages == 0)
3791 npages = 1; 3791 npages = 1;
3792 3792 if (npages > ARRAY_SIZE(pages))
3793 /* Add an extra page to handle the bitmap returned */ 3793 return -ERANGE;
3794 npages++;
3795 3794
3796 for (i = 0; i < npages; i++) { 3795 for (i = 0; i < npages; i++) {
3797 pages[i] = alloc_page(GFP_KERNEL); 3796 pages[i] = alloc_page(GFP_KERNEL);
@@ -3807,11 +3806,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
3807 args.acl_len = npages * PAGE_SIZE; 3806 args.acl_len = npages * PAGE_SIZE;
3808 args.acl_pgbase = 0; 3807 args.acl_pgbase = 0;
3809 3808
3810 /* Let decode_getfacl know not to fail if the ACL data is larger than
3811 * the page we send as a guess */
3812 if (buf == NULL)
3813 res.acl_flags |= NFS4_ACL_LEN_REQUEST;
3814
3815 dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", 3809 dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n",
3816 __func__, buf, buflen, npages, args.acl_len); 3810 __func__, buf, buflen, npages, args.acl_len);
3817 ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), 3811 ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode),
@@ -3819,20 +3813,19 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
3819 if (ret) 3813 if (ret)
3820 goto out_free; 3814 goto out_free;
3821 3815
3822 acl_len = res.acl_len - res.acl_data_offset; 3816 /* Handle the case where the passed-in buffer is too short */
3823 if (acl_len > args.acl_len) 3817 if (res.acl_flags & NFS4_ACL_TRUNC) {
3824 nfs4_write_cached_acl(inode, NULL, 0, acl_len); 3818 /* Did the user only issue a request for the acl length? */
3825 else 3819 if (buf == NULL)
3826 nfs4_write_cached_acl(inode, pages, res.acl_data_offset, 3820 goto out_ok;
3827 acl_len);
3828 if (buf) {
3829 ret = -ERANGE; 3821 ret = -ERANGE;
3830 if (acl_len > buflen) 3822 goto out_free;
3831 goto out_free;
3832 _copy_from_pages(buf, pages, res.acl_data_offset,
3833 acl_len);
3834 } 3823 }
3835 ret = acl_len; 3824 nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len);
3825 if (buf)
3826 _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len);
3827out_ok:
3828 ret = res.acl_len;
3836out_free: 3829out_free:
3837 for (i = 0; i < npages; i++) 3830 for (i = 0; i < npages; i++)
3838 if (pages[i]) 3831 if (pages[i])
@@ -3890,10 +3883,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
3890 .rpc_argp = &arg, 3883 .rpc_argp = &arg,
3891 .rpc_resp = &res, 3884 .rpc_resp = &res,
3892 }; 3885 };
3886 unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
3893 int ret, i; 3887 int ret, i;
3894 3888
3895 if (!nfs4_server_supports_acls(server)) 3889 if (!nfs4_server_supports_acls(server))
3896 return -EOPNOTSUPP; 3890 return -EOPNOTSUPP;
3891 if (npages > ARRAY_SIZE(pages))
3892 return -ERANGE;
3897 i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); 3893 i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
3898 if (i < 0) 3894 if (i < 0)
3899 return i; 3895 return i;
@@ -6223,11 +6219,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
6223 dprintk("<-- %s\n", __func__); 6219 dprintk("<-- %s\n", __func__);
6224} 6220}
6225 6221
6222static size_t max_response_pages(struct nfs_server *server)
6223{
6224 u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
6225 return nfs_page_array_len(0, max_resp_sz);
6226}
6227
6228static void nfs4_free_pages(struct page **pages, size_t size)
6229{
6230 int i;
6231
6232 if (!pages)
6233 return;
6234
6235 for (i = 0; i < size; i++) {
6236 if (!pages[i])
6237 break;
6238 __free_page(pages[i]);
6239 }
6240 kfree(pages);
6241}
6242
6243static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
6244{
6245 struct page **pages;
6246 int i;
6247
6248 pages = kcalloc(size, sizeof(struct page *), gfp_flags);
6249 if (!pages) {
6250 dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
6251 return NULL;
6252 }
6253
6254 for (i = 0; i < size; i++) {
6255 pages[i] = alloc_page(gfp_flags);
6256 if (!pages[i]) {
6257 dprintk("%s: failed to allocate page\n", __func__);
6258 nfs4_free_pages(pages, size);
6259 return NULL;
6260 }
6261 }
6262
6263 return pages;
6264}
6265
6226static void nfs4_layoutget_release(void *calldata) 6266static void nfs4_layoutget_release(void *calldata)
6227{ 6267{
6228 struct nfs4_layoutget *lgp = calldata; 6268 struct nfs4_layoutget *lgp = calldata;
6269 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
6270 size_t max_pages = max_response_pages(server);
6229 6271
6230 dprintk("--> %s\n", __func__); 6272 dprintk("--> %s\n", __func__);
6273 nfs4_free_pages(lgp->args.layout.pages, max_pages);
6231 put_nfs_open_context(lgp->args.ctx); 6274 put_nfs_open_context(lgp->args.ctx);
6232 kfree(calldata); 6275 kfree(calldata);
6233 dprintk("<-- %s\n", __func__); 6276 dprintk("<-- %s\n", __func__);
@@ -6239,9 +6282,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
6239 .rpc_release = nfs4_layoutget_release, 6282 .rpc_release = nfs4_layoutget_release,
6240}; 6283};
6241 6284
6242int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) 6285void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
6243{ 6286{
6244 struct nfs_server *server = NFS_SERVER(lgp->args.inode); 6287 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
6288 size_t max_pages = max_response_pages(server);
6245 struct rpc_task *task; 6289 struct rpc_task *task;
6246 struct rpc_message msg = { 6290 struct rpc_message msg = {
6247 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], 6291 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
@@ -6259,12 +6303,19 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
6259 6303
6260 dprintk("--> %s\n", __func__); 6304 dprintk("--> %s\n", __func__);
6261 6305
6306 lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
6307 if (!lgp->args.layout.pages) {
6308 nfs4_layoutget_release(lgp);
6309 return;
6310 }
6311 lgp->args.layout.pglen = max_pages * PAGE_SIZE;
6312
6262 lgp->res.layoutp = &lgp->args.layout; 6313 lgp->res.layoutp = &lgp->args.layout;
6263 lgp->res.seq_res.sr_slot = NULL; 6314 lgp->res.seq_res.sr_slot = NULL;
6264 nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); 6315 nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
6265 task = rpc_run_task(&task_setup_data); 6316 task = rpc_run_task(&task_setup_data);
6266 if (IS_ERR(task)) 6317 if (IS_ERR(task))
6267 return PTR_ERR(task); 6318 return;
6268 status = nfs4_wait_for_completion_rpc_task(task); 6319 status = nfs4_wait_for_completion_rpc_task(task);
6269 if (status == 0) 6320 if (status == 0)
6270 status = task->tk_status; 6321 status = task->tk_status;
@@ -6272,7 +6323,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
6272 status = pnfs_layout_process(lgp); 6323 status = pnfs_layout_process(lgp);
6273 rpc_put_task(task); 6324 rpc_put_task(task);
6274 dprintk("<-- %s status=%d\n", __func__, status); 6325 dprintk("<-- %s status=%d\n", __func__, status);
6275 return status; 6326 return;
6276} 6327}
6277 6328
6278static void 6329static void
@@ -6304,12 +6355,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
6304 return; 6355 return;
6305 } 6356 }
6306 spin_lock(&lo->plh_inode->i_lock); 6357 spin_lock(&lo->plh_inode->i_lock);
6307 if (task->tk_status == 0) { 6358 if (task->tk_status == 0 && lrp->res.lrs_present)
6308 if (lrp->res.lrs_present) { 6359 pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
6309 pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
6310 } else
6311 BUG_ON(!list_empty(&lo->plh_segs));
6312 }
6313 lo->plh_block_lgets--; 6360 lo->plh_block_lgets--;
6314 spin_unlock(&lo->plh_inode->i_lock); 6361 spin_unlock(&lo->plh_inode->i_lock);
6315 dprintk("<-- %s\n", __func__); 6362 dprintk("<-- %s\n", __func__);