aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnna Schumaker <Anna.Schumaker@netapp.com>2014-05-06 09:12:30 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-05-28 18:40:04 -0400
commit4a0de55c565a36cac8422b76a948c4634a90781e (patch)
tree749ab695ab23756f1f7c791a17a2125eac993d9c
parent00bfa30abe86982ce1929e9cabd703e5546106bd (diff)
NFS: Create a common rw_header_alloc and rw_header_free function
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>
-rw-r--r--fs/nfs/internal.h6
-rw-r--r--fs/nfs/pagelist.c33
-rw-r--r--fs/nfs/pnfs.c8
-rw-r--r--fs/nfs/read.c34
-rw-r--r--fs/nfs/write.c28
-rw-r--r--include/linux/nfs_page.h7
-rw-r--r--include/linux/nfs_xdr.h1
7 files changed, 72 insertions, 45 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 5ddc142c5062..9d6a40eae11c 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -237,6 +237,8 @@ extern void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
237void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos); 237void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos);
238int nfs_iocounter_wait(struct nfs_io_counter *c); 238int nfs_iocounter_wait(struct nfs_io_counter *c);
239 239
240struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *);
241void nfs_rw_header_free(struct nfs_pgio_header *);
240struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int); 242struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int);
241void nfs_pgio_data_release(struct nfs_pgio_data *); 243void nfs_pgio_data_release(struct nfs_pgio_data *);
242 244
@@ -397,8 +399,6 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool
397 399
398struct nfs_pgio_completion_ops; 400struct nfs_pgio_completion_ops;
399/* read.c */ 401/* read.c */
400extern struct nfs_rw_header *nfs_readhdr_alloc(void);
401extern void nfs_readhdr_free(struct nfs_pgio_header *hdr);
402extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, 402extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
403 struct inode *inode, bool force_mds, 403 struct inode *inode, bool force_mds,
404 const struct nfs_pgio_completion_ops *compl_ops); 404 const struct nfs_pgio_completion_ops *compl_ops);
@@ -425,8 +425,6 @@ int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
425extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, 425extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
426 struct inode *inode, int ioflags, bool force_mds, 426 struct inode *inode, int ioflags, bool force_mds,
427 const struct nfs_pgio_completion_ops *compl_ops); 427 const struct nfs_pgio_completion_ops *compl_ops);
428extern struct nfs_rw_header *nfs_writehdr_alloc(void);
429extern void nfs_writehdr_free(struct nfs_pgio_header *hdr);
430extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, 428extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
431 struct nfs_pgio_header *hdr); 429 struct nfs_pgio_header *hdr);
432extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); 430extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index a98ccf722d7b..ca356fe0836b 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -301,6 +301,37 @@ static inline struct nfs_rw_header *NFS_RW_HEADER(struct nfs_pgio_header *hdr)
301} 301}
302 302
303/** 303/**
304 * nfs_rw_header_alloc - Allocate a header for a read or write
305 * @ops: Read or write function vector
306 */
307struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *ops)
308{
309 struct nfs_rw_header *header = ops->rw_alloc_header();
310
311 if (header) {
312 struct nfs_pgio_header *hdr = &header->header;
313
314 INIT_LIST_HEAD(&hdr->pages);
315 INIT_LIST_HEAD(&hdr->rpc_list);
316 spin_lock_init(&hdr->lock);
317 atomic_set(&hdr->refcnt, 0);
318 hdr->rw_ops = ops;
319 }
320 return header;
321}
322EXPORT_SYMBOL_GPL(nfs_rw_header_alloc);
323
324/*
325 * nfs_rw_header_free - Free a read or write header
326 * @hdr: The header to free
327 */
328void nfs_rw_header_free(struct nfs_pgio_header *hdr)
329{
330 hdr->rw_ops->rw_free_header(NFS_RW_HEADER(hdr));
331}
332EXPORT_SYMBOL_GPL(nfs_rw_header_free);
333
334/**
304 * nfs_pgio_data_alloc - Allocate pageio data 335 * nfs_pgio_data_alloc - Allocate pageio data
305 * @hdr: The header making a request 336 * @hdr: The header making a request
306 * @pagecount: Number of pages to create 337 * @pagecount: Number of pages to create
@@ -367,6 +398,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
367 struct inode *inode, 398 struct inode *inode,
368 const struct nfs_pageio_ops *pg_ops, 399 const struct nfs_pageio_ops *pg_ops,
369 const struct nfs_pgio_completion_ops *compl_ops, 400 const struct nfs_pgio_completion_ops *compl_ops,
401 const struct nfs_rw_ops *rw_ops,
370 size_t bsize, 402 size_t bsize,
371 int io_flags) 403 int io_flags)
372{ 404{
@@ -380,6 +412,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
380 desc->pg_inode = inode; 412 desc->pg_inode = inode;
381 desc->pg_ops = pg_ops; 413 desc->pg_ops = pg_ops;
382 desc->pg_completion_ops = compl_ops; 414 desc->pg_completion_ops = compl_ops;
415 desc->pg_rw_ops = rw_ops;
383 desc->pg_ioflags = io_flags; 416 desc->pg_ioflags = io_flags;
384 desc->pg_error = 0; 417 desc->pg_error = 0;
385 desc->pg_lseg = NULL; 418 desc->pg_lseg = NULL;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index e192ba69a7d4..54c84c128b2b 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1585,7 +1585,7 @@ pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *he
1585static void pnfs_writehdr_free(struct nfs_pgio_header *hdr) 1585static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)
1586{ 1586{
1587 pnfs_put_lseg(hdr->lseg); 1587 pnfs_put_lseg(hdr->lseg);
1588 nfs_writehdr_free(hdr); 1588 nfs_rw_header_free(hdr);
1589} 1589}
1590EXPORT_SYMBOL_GPL(pnfs_writehdr_free); 1590EXPORT_SYMBOL_GPL(pnfs_writehdr_free);
1591 1591
@@ -1596,7 +1596,7 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1596 struct nfs_pgio_header *hdr; 1596 struct nfs_pgio_header *hdr;
1597 int ret; 1597 int ret;
1598 1598
1599 whdr = nfs_writehdr_alloc(); 1599 whdr = nfs_rw_header_alloc(desc->pg_rw_ops);
1600 if (!whdr) { 1600 if (!whdr) {
1601 desc->pg_completion_ops->error_cleanup(&desc->pg_list); 1601 desc->pg_completion_ops->error_cleanup(&desc->pg_list);
1602 pnfs_put_lseg(desc->pg_lseg); 1602 pnfs_put_lseg(desc->pg_lseg);
@@ -1743,7 +1743,7 @@ pnfs_do_multiple_reads(struct nfs_pageio_descriptor *desc, struct list_head *hea
1743static void pnfs_readhdr_free(struct nfs_pgio_header *hdr) 1743static void pnfs_readhdr_free(struct nfs_pgio_header *hdr)
1744{ 1744{
1745 pnfs_put_lseg(hdr->lseg); 1745 pnfs_put_lseg(hdr->lseg);
1746 nfs_readhdr_free(hdr); 1746 nfs_rw_header_free(hdr);
1747} 1747}
1748EXPORT_SYMBOL_GPL(pnfs_readhdr_free); 1748EXPORT_SYMBOL_GPL(pnfs_readhdr_free);
1749 1749
@@ -1754,7 +1754,7 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
1754 struct nfs_pgio_header *hdr; 1754 struct nfs_pgio_header *hdr;
1755 int ret; 1755 int ret;
1756 1756
1757 rhdr = nfs_readhdr_alloc(); 1757 rhdr = nfs_rw_header_alloc(desc->pg_rw_ops);
1758 if (!rhdr) { 1758 if (!rhdr) {
1759 desc->pg_completion_ops->error_cleanup(&desc->pg_list); 1759 desc->pg_completion_ops->error_cleanup(&desc->pg_list);
1760 ret = -ENOMEM; 1760 ret = -ENOMEM;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index ab4c1a5b5fbd..4cf3577bd54e 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -31,33 +31,19 @@
31static const struct nfs_pageio_ops nfs_pageio_read_ops; 31static const struct nfs_pageio_ops nfs_pageio_read_ops;
32static const struct rpc_call_ops nfs_read_common_ops; 32static const struct rpc_call_ops nfs_read_common_ops;
33static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops; 33static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops;
34static const struct nfs_rw_ops nfs_rw_read_ops;
34 35
35static struct kmem_cache *nfs_rdata_cachep; 36static struct kmem_cache *nfs_rdata_cachep;
36 37
37struct nfs_rw_header *nfs_readhdr_alloc(void) 38static struct nfs_rw_header *nfs_readhdr_alloc(void)
38{ 39{
39 struct nfs_rw_header *rhdr; 40 return kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
40
41 rhdr = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
42 if (rhdr) {
43 struct nfs_pgio_header *hdr = &rhdr->header;
44
45 INIT_LIST_HEAD(&hdr->pages);
46 INIT_LIST_HEAD(&hdr->rpc_list);
47 spin_lock_init(&hdr->lock);
48 atomic_set(&hdr->refcnt, 0);
49 }
50 return rhdr;
51} 41}
52EXPORT_SYMBOL_GPL(nfs_readhdr_alloc);
53 42
54void nfs_readhdr_free(struct nfs_pgio_header *hdr) 43static void nfs_readhdr_free(struct nfs_rw_header *rhdr)
55{ 44{
56 struct nfs_rw_header *rhdr = container_of(hdr, struct nfs_rw_header, header);
57
58 kmem_cache_free(nfs_rdata_cachep, rhdr); 45 kmem_cache_free(nfs_rdata_cachep, rhdr);
59} 46}
60EXPORT_SYMBOL_GPL(nfs_readhdr_free);
61 47
62static 48static
63int nfs_return_empty_page(struct page *page) 49int nfs_return_empty_page(struct page *page)
@@ -79,7 +65,8 @@ void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
79 if (server->pnfs_curr_ld && !force_mds) 65 if (server->pnfs_curr_ld && !force_mds)
80 pg_ops = server->pnfs_curr_ld->pg_read_ops; 66 pg_ops = server->pnfs_curr_ld->pg_read_ops;
81#endif 67#endif
82 nfs_pageio_init(pgio, inode, pg_ops, compl_ops, server->rsize, 0); 68 nfs_pageio_init(pgio, inode, pg_ops, compl_ops, &nfs_rw_read_ops,
69 server->rsize, 0);
83} 70}
84EXPORT_SYMBOL_GPL(nfs_pageio_init_read); 71EXPORT_SYMBOL_GPL(nfs_pageio_init_read);
85 72
@@ -375,13 +362,13 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
375 struct nfs_pgio_header *hdr; 362 struct nfs_pgio_header *hdr;
376 int ret; 363 int ret;
377 364
378 rhdr = nfs_readhdr_alloc(); 365 rhdr = nfs_rw_header_alloc(desc->pg_rw_ops);
379 if (!rhdr) { 366 if (!rhdr) {
380 desc->pg_completion_ops->error_cleanup(&desc->pg_list); 367 desc->pg_completion_ops->error_cleanup(&desc->pg_list);
381 return -ENOMEM; 368 return -ENOMEM;
382 } 369 }
383 hdr = &rhdr->header; 370 hdr = &rhdr->header;
384 nfs_pgheader_init(desc, hdr, nfs_readhdr_free); 371 nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
385 atomic_inc(&hdr->refcnt); 372 atomic_inc(&hdr->refcnt);
386 ret = nfs_generic_pagein(desc, hdr); 373 ret = nfs_generic_pagein(desc, hdr);
387 if (ret == 0) 374 if (ret == 0)
@@ -647,3 +634,8 @@ void nfs_destroy_readpagecache(void)
647{ 634{
648 kmem_cache_destroy(nfs_rdata_cachep); 635 kmem_cache_destroy(nfs_rdata_cachep);
649} 636}
637
638static const struct nfs_rw_ops nfs_rw_read_ops = {
639 .rw_alloc_header = nfs_readhdr_alloc,
640 .rw_free_header = nfs_readhdr_free,
641};
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 0dc4d6a28bd0..9c5cde38da45 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -46,6 +46,7 @@ static const struct rpc_call_ops nfs_write_common_ops;
46static const struct rpc_call_ops nfs_commit_ops; 46static const struct rpc_call_ops nfs_commit_ops;
47static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops; 47static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
48static const struct nfs_commit_completion_ops nfs_commit_completion_ops; 48static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
49static const struct nfs_rw_ops nfs_rw_write_ops;
49 50
50static struct kmem_cache *nfs_wdata_cachep; 51static struct kmem_cache *nfs_wdata_cachep;
51static mempool_t *nfs_wdata_mempool; 52static mempool_t *nfs_wdata_mempool;
@@ -70,29 +71,19 @@ void nfs_commit_free(struct nfs_commit_data *p)
70} 71}
71EXPORT_SYMBOL_GPL(nfs_commit_free); 72EXPORT_SYMBOL_GPL(nfs_commit_free);
72 73
73struct nfs_rw_header *nfs_writehdr_alloc(void) 74static struct nfs_rw_header *nfs_writehdr_alloc(void)
74{ 75{
75 struct nfs_rw_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOIO); 76 struct nfs_rw_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOIO);
76 77
77 if (p) { 78 if (p)
78 struct nfs_pgio_header *hdr = &p->header;
79
80 memset(p, 0, sizeof(*p)); 79 memset(p, 0, sizeof(*p));
81 INIT_LIST_HEAD(&hdr->pages);
82 INIT_LIST_HEAD(&hdr->rpc_list);
83 spin_lock_init(&hdr->lock);
84 atomic_set(&hdr->refcnt, 0);
85 }
86 return p; 80 return p;
87} 81}
88EXPORT_SYMBOL_GPL(nfs_writehdr_alloc);
89 82
90void nfs_writehdr_free(struct nfs_pgio_header *hdr) 83static void nfs_writehdr_free(struct nfs_rw_header *whdr)
91{ 84{
92 struct nfs_rw_header *whdr = container_of(hdr, struct nfs_rw_header, header);
93 mempool_free(whdr, nfs_wdata_mempool); 85 mempool_free(whdr, nfs_wdata_mempool);
94} 86}
95EXPORT_SYMBOL_GPL(nfs_writehdr_free);
96 87
97static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) 88static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
98{ 89{
@@ -1210,13 +1201,13 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1210 struct nfs_pgio_header *hdr; 1201 struct nfs_pgio_header *hdr;
1211 int ret; 1202 int ret;
1212 1203
1213 whdr = nfs_writehdr_alloc(); 1204 whdr = nfs_rw_header_alloc(desc->pg_rw_ops);
1214 if (!whdr) { 1205 if (!whdr) {
1215 desc->pg_completion_ops->error_cleanup(&desc->pg_list); 1206 desc->pg_completion_ops->error_cleanup(&desc->pg_list);
1216 return -ENOMEM; 1207 return -ENOMEM;
1217 } 1208 }
1218 hdr = &whdr->header; 1209 hdr = &whdr->header;
1219 nfs_pgheader_init(desc, hdr, nfs_writehdr_free); 1210 nfs_pgheader_init(desc, hdr, nfs_rw_header_free);
1220 atomic_inc(&hdr->refcnt); 1211 atomic_inc(&hdr->refcnt);
1221 ret = nfs_generic_flush(desc, hdr); 1212 ret = nfs_generic_flush(desc, hdr);
1222 if (ret == 0) 1213 if (ret == 0)
@@ -1244,7 +1235,8 @@ void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
1244 if (server->pnfs_curr_ld && !force_mds) 1235 if (server->pnfs_curr_ld && !force_mds)
1245 pg_ops = server->pnfs_curr_ld->pg_write_ops; 1236 pg_ops = server->pnfs_curr_ld->pg_write_ops;
1246#endif 1237#endif
1247 nfs_pageio_init(pgio, inode, pg_ops, compl_ops, server->wsize, ioflags); 1238 nfs_pageio_init(pgio, inode, pg_ops, compl_ops, &nfs_rw_write_ops,
1239 server->wsize, ioflags);
1248} 1240}
1249EXPORT_SYMBOL_GPL(nfs_pageio_init_write); 1241EXPORT_SYMBOL_GPL(nfs_pageio_init_write);
1250 1242
@@ -1925,3 +1917,7 @@ void nfs_destroy_writepagecache(void)
1925 kmem_cache_destroy(nfs_wdata_cachep); 1917 kmem_cache_destroy(nfs_wdata_cachep);
1926} 1918}
1927 1919
1920static const struct nfs_rw_ops nfs_rw_write_ops = {
1921 .rw_alloc_header = nfs_writehdr_alloc,
1922 .rw_free_header = nfs_writehdr_free,
1923};
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 92ce5783b707..594812546c25 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -52,6 +52,11 @@ struct nfs_pageio_ops {
52 int (*pg_doio)(struct nfs_pageio_descriptor *); 52 int (*pg_doio)(struct nfs_pageio_descriptor *);
53}; 53};
54 54
55struct nfs_rw_ops {
56 struct nfs_rw_header *(*rw_alloc_header)(void);
57 void (*rw_free_header)(struct nfs_rw_header *);
58};
59
55struct nfs_pageio_descriptor { 60struct nfs_pageio_descriptor {
56 struct list_head pg_list; 61 struct list_head pg_list;
57 unsigned long pg_bytes_written; 62 unsigned long pg_bytes_written;
@@ -63,6 +68,7 @@ struct nfs_pageio_descriptor {
63 68
64 struct inode *pg_inode; 69 struct inode *pg_inode;
65 const struct nfs_pageio_ops *pg_ops; 70 const struct nfs_pageio_ops *pg_ops;
71 const struct nfs_rw_ops *pg_rw_ops;
66 int pg_ioflags; 72 int pg_ioflags;
67 int pg_error; 73 int pg_error;
68 const struct rpc_call_ops *pg_rpc_callops; 74 const struct rpc_call_ops *pg_rpc_callops;
@@ -86,6 +92,7 @@ extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
86 struct inode *inode, 92 struct inode *inode,
87 const struct nfs_pageio_ops *pg_ops, 93 const struct nfs_pageio_ops *pg_ops,
88 const struct nfs_pgio_completion_ops *compl_ops, 94 const struct nfs_pgio_completion_ops *compl_ops,
95 const struct nfs_rw_ops *rw_ops,
89 size_t bsize, 96 size_t bsize,
90 int how); 97 int how);
91extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *, 98extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 965c2aa6b33f..a1b91b67145e 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1269,6 +1269,7 @@ struct nfs_pgio_header {
1269 const struct rpc_call_ops *mds_ops; 1269 const struct rpc_call_ops *mds_ops;
1270 void (*release) (struct nfs_pgio_header *hdr); 1270 void (*release) (struct nfs_pgio_header *hdr);
1271 const struct nfs_pgio_completion_ops *completion_ops; 1271 const struct nfs_pgio_completion_ops *completion_ops;
1272 const struct nfs_rw_ops *rw_ops;
1272 struct nfs_direct_req *dreq; 1273 struct nfs_direct_req *dreq;
1273 void *layout_private; 1274 void *layout_private;
1274 spinlock_t lock; 1275 spinlock_t lock;