diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 57 |
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 | ||
6226 | static 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 | |||
6232 | static 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 | |||
6247 | static 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 | |||
6226 | static void nfs4_layoutget_release(void *calldata) | 6270 | static 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 | ||
6242 | int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | 6289 | int 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); |