NFS: Create a common rw_header_alloc and rw_header_free function
authorAnna Schumaker <Anna.Schumaker@netapp.com>
Tue, 6 May 2014 13:12:30 +0000 (09:12 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Wed, 28 May 2014 22:40:04 +0000 (18:40 -0400)
I create a new struct nfs_rw_ops to decide the differences between reads
and writes.  This struct will be set when initializing a new
nfs_pgio_descriptor, and then passed on to the nfs_rw_header when a new
header is allocated.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/internal.h
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/read.c
fs/nfs/write.c
include/linux/nfs_page.h
include/linux/nfs_xdr.h

index 5ddc142c5062229aee5804b42b7be686e6835ae0..9d6a40eae11c1ea260e98505f0176f18d4bba6e5 100644 (file)
@@ -237,6 +237,8 @@ extern void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
 void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos);
 int nfs_iocounter_wait(struct nfs_io_counter *c);
 
+struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
+void nfs_rw_header_free(struct nfs_pgio_header *);
 struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
 void nfs_pgio_data_release(struct nfs_pgio_data *);
 
@@ -397,8 +399,6 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool
 
 struct nfs_pgio_completion_ops;
 /* read.c */
-extern struct nfs_rw_header *nfs_readhdr_alloc(void);
-extern void nfs_readhdr_free(struct nfs_pgio_header *hdr);
 extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
                        struct inode *inode, bool force_mds,
                        const struct nfs_pgio_completion_ops *compl_ops);
@@ -425,8 +425,6 @@ int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
 extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
                        struct inode *inode, int ioflags, bool force_mds,
                        const struct nfs_pgio_completion_ops *compl_ops);
-extern struct nfs_rw_header *nfs_writehdr_alloc(void);
-extern void nfs_writehdr_free(struct nfs_pgio_header *hdr);
 extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
                             struct nfs_pgio_header *hdr);
 extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
index a98ccf722d7b5b4e8643ee6a3f3bdcd77b258fc5..ca356fe0836bdc93f792af892e4e5bacdf602084 100644 (file)
@@ -300,6 +300,37 @@ static inline struct nfs_rw_header *NFS_RW_HEADER(struct nfs_pgio_header *hdr)
        return container_of(hdr, struct nfs_rw_header, header);
 }
 
+/**
+ * nfs_rw_header_alloc - Allocate a header for a read or write
+ * @ops: Read or write function vector
+ */
+struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *ops)
+{
+       struct nfs_rw_header *header = ops->rw_alloc_header();
+
+       if (header) {
+               struct nfs_pgio_header *hdr = &header->header;
+
+               INIT_LIST_HEAD(&hdr->pages);
+               INIT_LIST_HEAD(&hdr->rpc_list);
+               spin_lock_init(&hdr->lock);
+               atomic_set(&hdr->refcnt, 0);
+               hdr->rw_ops = ops;
+       }
+       return header;
+}
+EXPORT_SYMBOL_GPL(nfs_rw_header_alloc);
+
+/*
+ * nfs_rw_header_free - Free a read or write header
+ * @hdr: The header to free
+ */
+void nfs_rw_header_free(struct nfs_pgio_header *hdr)
+{
+       hdr->rw_ops->rw_free_header(NFS_RW_HEADER(hdr));
+}
+EXPORT_SYMBOL_GPL(nfs_rw_header_free);
+
 /**
  * nfs_pgio_data_alloc - Allocate pageio data
  * @hdr: The header making a request
@@ -367,6 +398,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
                     struct inode *inode,
                     const struct nfs_pageio_ops *pg_ops,
                     const struct nfs_pgio_completion_ops *compl_ops,
+                    const struct nfs_rw_ops *rw_ops,
                     size_t bsize,
                     int io_flags)
 {
@@ -380,6 +412,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
        desc->pg_inode = inode;
        desc->pg_ops = pg_ops;
        desc->pg_completion_ops = compl_ops;
+       desc->pg_rw_ops = rw_ops;
        desc->pg_ioflags = io_flags;
        desc->pg_error = 0;
        desc->pg_lseg = NULL;
index e192ba69a7d47ee0d9d33903bc45a0f225d0b692..54c84c128b2b57811da2446f383938934d3ff3a0 100644 (file)
@@ -1585,7 +1585,7 @@ pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *he
 static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)
 {
        pnfs_put_lseg(hdr->lseg);
-       nfs_writehdr_free(hdr);
+       nfs_rw_header_free(hdr);
 }
 EXPORT_SYMBOL_GPL(pnfs_writehdr_free);
 
@@ -1596,7 +1596,7 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
        struct nfs_pgio_header *hdr;
        int ret;
 
-       whdr = nfs_writehdr_alloc();
+       whdr = nfs_rw_header_alloc(desc->pg_rw_ops);
        if (!whdr) {
                desc->pg_completion_ops->error_cleanup(&desc->pg_list);
                pnfs_put_lseg(desc->pg_lseg);
@@ -1743,7 +1743,7 @@ pnfs_do_multiple_reads(struct nfs_pageio_descriptor *desc, struct list_head *hea
 static void pnfs_readhdr_free(struct nfs_pgio_header *hdr)
 {
        pnfs_put_lseg(hdr->lseg);
-       nfs_readhdr_free(hdr);
+       nfs_rw_header_free(hdr);
 }
 EXPORT_SYMBOL_GPL(pnfs_readhdr_free);
 
@@ -1754,7 +1754,7 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
        struct nfs_pgio_header *hdr;
        int ret;
 
-       rhdr = nfs_readhdr_alloc();
+       rhdr = nfs_rw_header_alloc(desc->pg_rw_ops);
        if (!rhdr) {
                desc->pg_completion_ops->error_cleanup(&desc->pg_list);
                ret = -ENOMEM;
index ab4c1a5b5fbd238dc0b3715605d88e639e88ca28..4cf3577bd54eb36ff3d190ebc4a67c0203e1c6cd 100644 (file)
 static const struct nfs_pageio_ops nfs_pageio_read_ops;
 static const struct rpc_call_ops nfs_read_common_ops;
 static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops;
+static const struct nfs_rw_ops nfs_rw_read_ops;
 
 static struct kmem_cache *nfs_rdata_cachep;
 
-struct nfs_rw_header *nfs_readhdr_alloc(void)
+static struct nfs_rw_header *nfs_readhdr_alloc(void)
 {
-       struct nfs_rw_header *rhdr;
-
-       rhdr = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
-       if (rhdr) {
-               struct nfs_pgio_header *hdr = &rhdr->header;
-
-               INIT_LIST_HEAD(&hdr->pages);
-               INIT_LIST_HEAD(&hdr->rpc_list);
-               spin_lock_init(&hdr->lock);
-               atomic_set(&hdr->refcnt, 0);
-       }
-       return rhdr;
+       return kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
 }
-EXPORT_SYMBOL_GPL(nfs_readhdr_alloc);
 
-void nfs_readhdr_free(struct nfs_pgio_header *hdr)
+static void nfs_readhdr_free(struct nfs_rw_header *rhdr)
 {
-       struct nfs_rw_header *rhdr = container_of(hdr, struct nfs_rw_header, header);
-
        kmem_cache_free(nfs_rdata_cachep, rhdr);
 }
-EXPORT_SYMBOL_GPL(nfs_readhdr_free);
 
 static
 int nfs_return_empty_page(struct page *page)
@@ -79,7 +65,8 @@ void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
        if (server->pnfs_curr_ld && !force_mds)
                pg_ops = server->pnfs_curr_ld->pg_read_ops;
 #endif
-       nfs_pageio_init(pgio, inode, pg_ops, compl_ops, server->rsize, 0);
+       nfs_pageio_init(pgio, inode, pg_ops, compl_ops, &nfs_rw_read_ops,
+                       server->rsize, 0);
 }
 EXPORT_SYMBOL_GPL(nfs_pageio_init_read);
 
@@ -375,13 +362,13 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
        struct nfs_pgio_header *hdr;
        int ret;
 
-       rhdr = nfs_readhdr_alloc();
+       rhdr = nfs_rw_header_alloc(desc->pg_rw_ops);
        if (!rhdr) {
                desc->pg_completion_ops->error_cleanup(&desc->pg_list);
                return -ENOMEM;
        }
        hdr = &rhdr->header;
-       nfs_pgheader_init(desc, hdr, nfs_readhdr_free);
+       nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
        atomic_inc(&hdr->refcnt);
        ret = nfs_generic_pagein(desc, hdr);
        if (ret == 0)
@@ -647,3 +634,8 @@ void nfs_destroy_readpagecache(void)
 {
        kmem_cache_destroy(nfs_rdata_cachep);
 }
+
+static const struct nfs_rw_ops nfs_rw_read_ops = {
+       .rw_alloc_header        = nfs_readhdr_alloc,
+       .rw_free_header         = nfs_readhdr_free,
+};
index 0dc4d6a28bd0d7f25f3bc6b937224a3c62ef34c3..9c5cde38da45e52f3be85c183363616bfaf65e78 100644 (file)
@@ -46,6 +46,7 @@ static const struct rpc_call_ops nfs_write_common_ops;
 static const struct rpc_call_ops nfs_commit_ops;
 static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
 static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
+static const struct nfs_rw_ops nfs_rw_write_ops;
 
 static struct kmem_cache *nfs_wdata_cachep;
 static mempool_t *nfs_wdata_mempool;
@@ -70,29 +71,19 @@ void nfs_commit_free(struct nfs_commit_data *p)
 }
 EXPORT_SYMBOL_GPL(nfs_commit_free);
 
-struct nfs_rw_header *nfs_writehdr_alloc(void)
+static struct nfs_rw_header *nfs_writehdr_alloc(void)
 {
        struct nfs_rw_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOIO);
 
-       if (p) {
-               struct nfs_pgio_header *hdr = &p->header;
-
+       if (p)
                memset(p, 0, sizeof(*p));
-               INIT_LIST_HEAD(&hdr->pages);
-               INIT_LIST_HEAD(&hdr->rpc_list);
-               spin_lock_init(&hdr->lock);
-               atomic_set(&hdr->refcnt, 0);
-       }
        return p;
 }
-EXPORT_SYMBOL_GPL(nfs_writehdr_alloc);
 
-void nfs_writehdr_free(struct nfs_pgio_header *hdr)
+static void nfs_writehdr_free(struct nfs_rw_header *whdr)
 {
-       struct nfs_rw_header *whdr = container_of(hdr, struct nfs_rw_header, header);
        mempool_free(whdr, nfs_wdata_mempool);
 }
-EXPORT_SYMBOL_GPL(nfs_writehdr_free);
 
 static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
 {
@@ -1210,13 +1201,13 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
        struct nfs_pgio_header *hdr;
        int ret;
 
-       whdr = nfs_writehdr_alloc();
+       whdr = nfs_rw_header_alloc(desc->pg_rw_ops);
        if (!whdr) {
                desc->pg_completion_ops->error_cleanup(&desc->pg_list);
                return -ENOMEM;
        }
        hdr = &whdr->header;
-       nfs_pgheader_init(desc, hdr, nfs_writehdr_free);
+       nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
        atomic_inc(&hdr->refcnt);
        ret = nfs_generic_flush(desc, hdr);
        if (ret == 0)
@@ -1244,7 +1235,8 @@ void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
        if (server->pnfs_curr_ld && !force_mds)
                pg_ops = server->pnfs_curr_ld->pg_write_ops;
 #endif
-       nfs_pageio_init(pgio, inode, pg_ops, compl_ops, server->wsize, ioflags);
+       nfs_pageio_init(pgio, inode, pg_ops, compl_ops, &nfs_rw_write_ops,
+                       server->wsize, ioflags);
 }
 EXPORT_SYMBOL_GPL(nfs_pageio_init_write);
 
@@ -1925,3 +1917,7 @@ void nfs_destroy_writepagecache(void)
        kmem_cache_destroy(nfs_wdata_cachep);
 }
 
+static const struct nfs_rw_ops nfs_rw_write_ops = {
+       .rw_alloc_header        = nfs_writehdr_alloc,
+       .rw_free_header         = nfs_writehdr_free,
+};
index 92ce5783b707df8ea90306aaf145f1fbba3d02a2..594812546c254401907bd474bbdcac5a7fe08704 100644 (file)
@@ -52,6 +52,11 @@ struct nfs_pageio_ops {
        int     (*pg_doio)(struct nfs_pageio_descriptor *);
 };
 
+struct nfs_rw_ops {
+       struct nfs_rw_header *(*rw_alloc_header)(void);
+       void (*rw_free_header)(struct nfs_rw_header *);
+};
+
 struct nfs_pageio_descriptor {
        struct list_head        pg_list;
        unsigned long           pg_bytes_written;
@@ -63,6 +68,7 @@ struct nfs_pageio_descriptor {
 
        struct inode            *pg_inode;
        const struct nfs_pageio_ops *pg_ops;
+       const struct nfs_rw_ops *pg_rw_ops;
        int                     pg_ioflags;
        int                     pg_error;
        const struct rpc_call_ops *pg_rpc_callops;
@@ -86,6 +92,7 @@ extern        void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
                             struct inode *inode,
                             const struct nfs_pageio_ops *pg_ops,
                             const struct nfs_pgio_completion_ops *compl_ops,
+                            const struct nfs_rw_ops *rw_ops,
                             size_t bsize,
                             int how);
 extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
index 965c2aa6b33f9ff71a132e447c1a1c896c5f6805..a1b91b67145e91bcbd633dd8ceb73e7cfa156f5d 100644 (file)
@@ -1269,6 +1269,7 @@ struct nfs_pgio_header {
        const struct rpc_call_ops *mds_ops;
        void (*release) (struct nfs_pgio_header *hdr);
        const struct nfs_pgio_completion_ops *completion_ops;
+       const struct nfs_rw_ops *rw_ops;
        struct nfs_direct_req   *dreq;
        void                    *layout_private;
        spinlock_t              lock;