|
@@ -6223,11 +6223,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
|
|
|
dprintk("<-- %s\n", __func__);
|
|
|
}
|
|
|
|
|
|
+static size_t max_response_pages(struct nfs_server *server)
|
|
|
+{
|
|
|
+ u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
|
|
|
+ return nfs_page_array_len(0, max_resp_sz);
|
|
|
+}
|
|
|
+
|
|
|
+static void nfs4_free_pages(struct page **pages, size_t size)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (!pages)
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (i = 0; i < size; i++) {
|
|
|
+ if (!pages[i])
|
|
|
+ break;
|
|
|
+ __free_page(pages[i]);
|
|
|
+ }
|
|
|
+ kfree(pages);
|
|
|
+}
|
|
|
+
|
|
|
+static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
|
|
|
+{
|
|
|
+ struct page **pages;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ pages = kcalloc(size, sizeof(struct page *), gfp_flags);
|
|
|
+ if (!pages) {
|
|
|
+ dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < size; i++) {
|
|
|
+ pages[i] = alloc_page(gfp_flags);
|
|
|
+ if (!pages[i]) {
|
|
|
+ dprintk("%s: failed to allocate page\n", __func__);
|
|
|
+ nfs4_free_pages(pages, size);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return pages;
|
|
|
+}
|
|
|
+
|
|
|
static void nfs4_layoutget_release(void *calldata)
|
|
|
{
|
|
|
struct nfs4_layoutget *lgp = calldata;
|
|
|
+ struct nfs_server *server = NFS_SERVER(lgp->args.inode);
|
|
|
+ size_t max_pages = max_response_pages(server);
|
|
|
|
|
|
dprintk("--> %s\n", __func__);
|
|
|
+ nfs4_free_pages(lgp->args.layout.pages, max_pages);
|
|
|
put_nfs_open_context(lgp->args.ctx);
|
|
|
kfree(calldata);
|
|
|
dprintk("<-- %s\n", __func__);
|
|
@@ -6239,9 +6286,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
|
|
|
.rpc_release = nfs4_layoutget_release,
|
|
|
};
|
|
|
|
|
|
-int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
|
|
|
+int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
|
|
|
{
|
|
|
struct nfs_server *server = NFS_SERVER(lgp->args.inode);
|
|
|
+ size_t max_pages = max_response_pages(server);
|
|
|
struct rpc_task *task;
|
|
|
struct rpc_message msg = {
|
|
|
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
|
|
@@ -6259,6 +6307,13 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
|
|
|
|
|
|
dprintk("--> %s\n", __func__);
|
|
|
|
|
|
+ lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
|
|
|
+ if (!lgp->args.layout.pages) {
|
|
|
+ nfs4_layoutget_release(lgp);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ lgp->args.layout.pglen = max_pages * PAGE_SIZE;
|
|
|
+
|
|
|
lgp->res.layoutp = &lgp->args.layout;
|
|
|
lgp->res.seq_res.sr_slot = NULL;
|
|
|
nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
|