aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index a0a2484c3aed..f568a1de5ec5 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -931,6 +931,44 @@ pnfs_find_server(struct inode *inode, struct nfs_open_context *ctx)
return server;
}
+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 struct nfs4_layoutget *
pnfs_alloc_init_layoutget_args(struct inode *ino,
struct nfs_open_context *ctx,
@@ -982,6 +1020,18 @@ pnfs_alloc_init_layoutget_args(struct inode *ino,
return lgp;
}
+void pnfs_layoutget_free(struct nfs4_layoutget *lgp)
+{
+ size_t max_pages = lgp->args.layout.pglen / PAGE_SIZE;
+
+ nfs4_free_pages(lgp->args.layout.pages, max_pages);
+ if (lgp->args.inode)
+ pnfs_put_layout_hdr(NFS_I(lgp->args.inode)->layout);
+ put_rpccred(lgp->cred);
+ put_nfs_open_context(lgp->args.ctx);
+ kfree(lgp);
+}
+
static void pnfs_clear_layoutcommit(struct inode *inode,
struct list_head *head)
{