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.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a99a8d948721..6a78d49da5c1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6223,11 +6223,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
6223 dprintk("<-- %s\n", __func__); 6223 dprintk("<-- %s\n", __func__);
6224} 6224}
6225 6225
6226static size_t max_response_pages(struct nfs_server *server)
6227{
6228 u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
6229 return nfs_page_array_len(0, max_resp_sz);
6230}
6231
6232static void nfs4_free_pages(struct page **pages, size_t size)
6233{
6234 int i;
6235
6236 if (!pages)
6237 return;
6238
6239 for (i = 0; i < size; i++) {
6240 if (!pages[i])
6241 break;
6242 __free_page(pages[i]);
6243 }
6244 kfree(pages);
6245}
6246
6247static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
6248{
6249 struct page **pages;
6250 int i;
6251
6252 pages = kcalloc(size, sizeof(struct page *), gfp_flags);
6253 if (!pages) {
6254 dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
6255 return NULL;
6256 }
6257
6258 for (i = 0; i < size; i++) {
6259 pages[i] = alloc_page(gfp_flags);
6260 if (!pages[i]) {
6261 dprintk("%s: failed to allocate page\n", __func__);
6262 nfs4_free_pages(pages, size);
6263 return NULL;
6264 }
6265 }
6266
6267 return pages;
6268}
6269
6226static void nfs4_layoutget_release(void *calldata) 6270static void nfs4_layoutget_release(void *calldata)
6227{ 6271{
6228 struct nfs4_layoutget *lgp = calldata; 6272 struct nfs4_layoutget *lgp = calldata;
6273 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
6274 size_t max_pages = max_response_pages(server);
6229 6275
6230 dprintk("--> %s\n", __func__); 6276 dprintk("--> %s\n", __func__);
6277 nfs4_free_pages(lgp->args.layout.pages, max_pages);
6231 put_nfs_open_context(lgp->args.ctx); 6278 put_nfs_open_context(lgp->args.ctx);
6232 kfree(calldata); 6279 kfree(calldata);
6233 dprintk("<-- %s\n", __func__); 6280 dprintk("<-- %s\n", __func__);
@@ -6239,9 +6286,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
6239 .rpc_release = nfs4_layoutget_release, 6286 .rpc_release = nfs4_layoutget_release,
6240}; 6287};
6241 6288
6242int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) 6289int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
6243{ 6290{
6244 struct nfs_server *server = NFS_SERVER(lgp->args.inode); 6291 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
6292 size_t max_pages = max_response_pages(server);
6245 struct rpc_task *task; 6293 struct rpc_task *task;
6246 struct rpc_message msg = { 6294 struct rpc_message msg = {
6247 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], 6295 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
@@ -6259,6 +6307,13 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
6259 6307
6260 dprintk("--> %s\n", __func__); 6308 dprintk("--> %s\n", __func__);
6261 6309
6310 lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
6311 if (!lgp->args.layout.pages) {
6312 nfs4_layoutget_release(lgp);
6313 return -ENOMEM;
6314 }
6315 lgp->args.layout.pglen = max_pages * PAGE_SIZE;
6316
6262 lgp->res.layoutp = &lgp->args.layout; 6317 lgp->res.layoutp = &lgp->args.layout;
6263 lgp->res.seq_res.sr_slot = NULL; 6318 lgp->res.seq_res.sr_slot = NULL;
6264 nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); 6319 nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);