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.c76
1 files changed, 64 insertions, 12 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a99a8d948721..635274140b18 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -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 (pages && 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;
@@ -3819,7 +3820,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
3819 if (ret) 3820 if (ret)
3820 goto out_free; 3821 goto out_free;
3821 3822
3822 acl_len = res.acl_len - res.acl_data_offset; 3823 acl_len = res.acl_len;
3823 if (acl_len > args.acl_len) 3824 if (acl_len > args.acl_len)
3824 nfs4_write_cached_acl(inode, NULL, 0, acl_len); 3825 nfs4_write_cached_acl(inode, NULL, 0, acl_len);
3825 else 3826 else
@@ -6223,11 +6224,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
6223 dprintk("<-- %s\n", __func__); 6224 dprintk("<-- %s\n", __func__);
6224} 6225}
6225 6226
6227static size_t max_response_pages(struct nfs_server *server)
6228{
6229 u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
6230 return nfs_page_array_len(0, max_resp_sz);
6231}
6232
6233static void nfs4_free_pages(struct page **pages, size_t size)
6234{
6235 int i;
6236
6237 if (!pages)
6238 return;
6239
6240 for (i = 0; i < size; i++) {
6241 if (!pages[i])
6242 break;
6243 __free_page(pages[i]);
6244 }
6245 kfree(pages);
6246}
6247
6248static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
6249{
6250 struct page **pages;
6251 int i;
6252
6253 pages = kcalloc(size, sizeof(struct page *), gfp_flags);
6254 if (!pages) {
6255 dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
6256 return NULL;
6257 }
6258
6259 for (i = 0; i < size; i++) {
6260 pages[i] = alloc_page(gfp_flags);
6261 if (!pages[i]) {
6262 dprintk("%s: failed to allocate page\n", __func__);
6263 nfs4_free_pages(pages, size);
6264 return NULL;
6265 }
6266 }
6267
6268 return pages;
6269}
6270
6226static void nfs4_layoutget_release(void *calldata) 6271static void nfs4_layoutget_release(void *calldata)
6227{ 6272{
6228 struct nfs4_layoutget *lgp = calldata; 6273 struct nfs4_layoutget *lgp = calldata;
6274 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
6275 size_t max_pages = max_response_pages(server);
6229 6276
6230 dprintk("--> %s\n", __func__); 6277 dprintk("--> %s\n", __func__);
6278 nfs4_free_pages(lgp->args.layout.pages, max_pages);
6231 put_nfs_open_context(lgp->args.ctx); 6279 put_nfs_open_context(lgp->args.ctx);
6232 kfree(calldata); 6280 kfree(calldata);
6233 dprintk("<-- %s\n", __func__); 6281 dprintk("<-- %s\n", __func__);
@@ -6239,9 +6287,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
6239 .rpc_release = nfs4_layoutget_release, 6287 .rpc_release = nfs4_layoutget_release,
6240}; 6288};
6241 6289
6242int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) 6290void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
6243{ 6291{
6244 struct nfs_server *server = NFS_SERVER(lgp->args.inode); 6292 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
6293 size_t max_pages = max_response_pages(server);
6245 struct rpc_task *task; 6294 struct rpc_task *task;
6246 struct rpc_message msg = { 6295 struct rpc_message msg = {
6247 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], 6296 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
@@ -6259,12 +6308,19 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
6259 6308
6260 dprintk("--> %s\n", __func__); 6309 dprintk("--> %s\n", __func__);
6261 6310
6311 lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
6312 if (!lgp->args.layout.pages) {
6313 nfs4_layoutget_release(lgp);
6314 return;
6315 }
6316 lgp->args.layout.pglen = max_pages * PAGE_SIZE;
6317
6262 lgp->res.layoutp = &lgp->args.layout; 6318 lgp->res.layoutp = &lgp->args.layout;
6263 lgp->res.seq_res.sr_slot = NULL; 6319 lgp->res.seq_res.sr_slot = NULL;
6264 nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); 6320 nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
6265 task = rpc_run_task(&task_setup_data); 6321 task = rpc_run_task(&task_setup_data);
6266 if (IS_ERR(task)) 6322 if (IS_ERR(task))
6267 return PTR_ERR(task); 6323 return;
6268 status = nfs4_wait_for_completion_rpc_task(task); 6324 status = nfs4_wait_for_completion_rpc_task(task);
6269 if (status == 0) 6325 if (status == 0)
6270 status = task->tk_status; 6326 status = task->tk_status;
@@ -6272,7 +6328,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
6272 status = pnfs_layout_process(lgp); 6328 status = pnfs_layout_process(lgp);
6273 rpc_put_task(task); 6329 rpc_put_task(task);
6274 dprintk("<-- %s status=%d\n", __func__, status); 6330 dprintk("<-- %s status=%d\n", __func__, status);
6275 return status; 6331 return;
6276} 6332}
6277 6333
6278static void 6334static void
@@ -6304,12 +6360,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
6304 return; 6360 return;
6305 } 6361 }
6306 spin_lock(&lo->plh_inode->i_lock); 6362 spin_lock(&lo->plh_inode->i_lock);
6307 if (task->tk_status == 0) { 6363 if (task->tk_status == 0 && lrp->res.lrs_present)
6308 if (lrp->res.lrs_present) { 6364 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--; 6365 lo->plh_block_lgets--;
6314 spin_unlock(&lo->plh_inode->i_lock); 6366 spin_unlock(&lo->plh_inode->i_lock);
6315 dprintk("<-- %s\n", __func__); 6367 dprintk("<-- %s\n", __func__);