aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4filelayout.c15
-rw-r--r--fs/nfs/objlayout/objio_osd.c13
-rw-r--r--fs/nfs/pagelist.c10
-rw-r--r--fs/nfs/pnfs.c24
-rw-r--r--fs/nfs/pnfs.h25
-rw-r--r--fs/nfs/read.c43
-rw-r--r--fs/nfs/write.c28
-rw-r--r--include/linux/nfs_page.h14
8 files changed, 131 insertions, 41 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index b690bb5ee58..46bb31b7968 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -658,7 +658,7 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
658 * return true : coalesce page 658 * return true : coalesce page
659 * return false : don't coalesce page 659 * return false : don't coalesce page
660 */ 660 */
661bool 661static bool
662filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, 662filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
663 struct nfs_page *req) 663 struct nfs_page *req)
664{ 664{
@@ -681,6 +681,16 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
681 return (p_stripe == r_stripe); 681 return (p_stripe == r_stripe);
682} 682}
683 683
684static const struct nfs_pageio_ops filelayout_pg_read_ops = {
685 .pg_test = filelayout_pg_test,
686 .pg_doio = nfs_generic_pg_readpages,
687};
688
689static const struct nfs_pageio_ops filelayout_pg_write_ops = {
690 .pg_test = filelayout_pg_test,
691 .pg_doio = nfs_generic_pg_writepages,
692};
693
684static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg) 694static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg)
685{ 695{
686 return !FILELAYOUT_LSEG(lseg)->commit_through_mds; 696 return !FILELAYOUT_LSEG(lseg)->commit_through_mds;
@@ -878,7 +888,8 @@ static struct pnfs_layoutdriver_type filelayout_type = {
878 .owner = THIS_MODULE, 888 .owner = THIS_MODULE,
879 .alloc_lseg = filelayout_alloc_lseg, 889 .alloc_lseg = filelayout_alloc_lseg,
880 .free_lseg = filelayout_free_lseg, 890 .free_lseg = filelayout_free_lseg,
881 .pg_test = filelayout_pg_test, 891 .pg_read_ops = &filelayout_pg_read_ops,
892 .pg_write_ops = &filelayout_pg_write_ops,
882 .mark_pnfs_commit = filelayout_mark_pnfs_commit, 893 .mark_pnfs_commit = filelayout_mark_pnfs_commit,
883 .choose_commit_list = filelayout_choose_commit_list, 894 .choose_commit_list = filelayout_choose_commit_list,
884 .commit_pagelist = filelayout_commit_pagelist, 895 .commit_pagelist = filelayout_commit_pagelist,
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
index 8ff2ea3f10e..c203fab694a 100644
--- a/fs/nfs/objlayout/objio_osd.c
+++ b/fs/nfs/objlayout/objio_osd.c
@@ -1007,6 +1007,16 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
1007 OBJIO_LSEG(pgio->pg_lseg)->max_io_size; 1007 OBJIO_LSEG(pgio->pg_lseg)->max_io_size;
1008} 1008}
1009 1009
1010static const struct nfs_pageio_ops objio_pg_read_ops = {
1011 .pg_test = objio_pg_test,
1012 .pg_doio = nfs_generic_pg_readpages,
1013};
1014
1015static const struct nfs_pageio_ops objio_pg_write_ops = {
1016 .pg_test = objio_pg_test,
1017 .pg_doio = nfs_generic_pg_writepages,
1018};
1019
1010static struct pnfs_layoutdriver_type objlayout_type = { 1020static struct pnfs_layoutdriver_type objlayout_type = {
1011 .id = LAYOUT_OSD2_OBJECTS, 1021 .id = LAYOUT_OSD2_OBJECTS,
1012 .name = "LAYOUT_OSD2_OBJECTS", 1022 .name = "LAYOUT_OSD2_OBJECTS",
@@ -1020,7 +1030,8 @@ static struct pnfs_layoutdriver_type objlayout_type = {
1020 1030
1021 .read_pagelist = objlayout_read_pagelist, 1031 .read_pagelist = objlayout_read_pagelist,
1022 .write_pagelist = objlayout_write_pagelist, 1032 .write_pagelist = objlayout_write_pagelist,
1023 .pg_test = objio_pg_test, 1033 .pg_read_ops = &objio_pg_read_ops,
1034 .pg_write_ops = &objio_pg_write_ops,
1024 1035
1025 .free_deviceid_node = objio_free_deviceid_node, 1036 .free_deviceid_node = objio_free_deviceid_node,
1026 1037
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 00985571628..9b8a4730f0b 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -230,7 +230,7 @@ EXPORT_SYMBOL_GPL(nfs_generic_pg_test);
230 */ 230 */
231void nfs_pageio_init(struct nfs_pageio_descriptor *desc, 231void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
232 struct inode *inode, 232 struct inode *inode,
233 int (*doio)(struct nfs_pageio_descriptor *), 233 const struct nfs_pageio_ops *pg_ops,
234 size_t bsize, 234 size_t bsize,
235 int io_flags) 235 int io_flags)
236{ 236{
@@ -241,12 +241,10 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
241 desc->pg_base = 0; 241 desc->pg_base = 0;
242 desc->pg_moreio = 0; 242 desc->pg_moreio = 0;
243 desc->pg_inode = inode; 243 desc->pg_inode = inode;
244 desc->pg_doio = doio; 244 desc->pg_ops = pg_ops;
245 desc->pg_ioflags = io_flags; 245 desc->pg_ioflags = io_flags;
246 desc->pg_error = 0; 246 desc->pg_error = 0;
247 desc->pg_lseg = NULL; 247 desc->pg_lseg = NULL;
248 desc->pg_test = nfs_generic_pg_test;
249 pnfs_pageio_init(desc, inode);
250} 248}
251 249
252/** 250/**
@@ -276,7 +274,7 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
276 return false; 274 return false;
277 if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE) 275 if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
278 return false; 276 return false;
279 return pgio->pg_test(pgio, prev, req); 277 return pgio->pg_ops->pg_test(pgio, prev, req);
280} 278}
281 279
282/** 280/**
@@ -311,7 +309,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
311static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc) 309static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
312{ 310{
313 if (!list_empty(&desc->pg_list)) { 311 if (!list_empty(&desc->pg_list)) {
314 int error = desc->pg_doio(desc); 312 int error = desc->pg_ops->pg_doio(desc);
315 if (error < 0) 313 if (error < 0)
316 desc->pg_error = error; 314 desc->pg_error = error;
317 else 315 else
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index ff820077237..7ec46d5f05a 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1056,6 +1056,30 @@ out_forget_reply:
1056} 1056}
1057 1057
1058bool 1058bool
1059pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
1060{
1061 struct nfs_server *server = NFS_SERVER(inode);
1062 struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
1063
1064 if (ld == NULL)
1065 return false;
1066 nfs_pageio_init(pgio, inode, ld->pg_read_ops, server->rsize, 0);
1067 return true;
1068}
1069
1070bool
1071pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags)
1072{
1073 struct nfs_server *server = NFS_SERVER(inode);
1074 struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
1075
1076 if (ld == NULL)
1077 return false;
1078 nfs_pageio_init(pgio, inode, ld->pg_write_ops, server->wsize, ioflags);
1079 return true;
1080}
1081
1082bool
1059pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, 1083pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
1060 struct nfs_page *req) 1084 struct nfs_page *req)
1061{ 1085{
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 96bf4e6f45b..137a2bd5c8c 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -87,7 +87,8 @@ struct pnfs_layoutdriver_type {
87 void (*free_lseg) (struct pnfs_layout_segment *lseg); 87 void (*free_lseg) (struct pnfs_layout_segment *lseg);
88 88
89 /* test for nfs page cache coalescing */ 89 /* test for nfs page cache coalescing */
90 bool (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *); 90 const struct nfs_pageio_ops *pg_read_ops;
91 const struct nfs_pageio_ops *pg_write_ops;
91 92
92 /* Returns true if layoutdriver wants to divert this request to 93 /* Returns true if layoutdriver wants to divert this request to
93 * driver's commit routine. 94 * driver's commit routine.
@@ -152,6 +153,10 @@ struct pnfs_layout_segment *
152pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, 153pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
153 loff_t pos, u64 count, enum pnfs_iomode access_type, 154 loff_t pos, u64 count, enum pnfs_iomode access_type,
154 gfp_t gfp_flags); 155 gfp_t gfp_flags);
156
157bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
158bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int);
159
155void set_pnfs_layoutdriver(struct nfs_server *, u32 id); 160void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
156void unset_pnfs_layoutdriver(struct nfs_server *); 161void unset_pnfs_layoutdriver(struct nfs_server *);
157enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, 162enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
@@ -293,15 +298,6 @@ static inline int pnfs_return_layout(struct inode *ino)
293 return 0; 298 return 0;
294} 299}
295 300
296static inline void pnfs_pageio_init(struct nfs_pageio_descriptor *pgio,
297 struct inode *inode)
298{
299 struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
300
301 if (ld)
302 pgio->pg_test = ld->pg_test;
303}
304
305#else /* CONFIG_NFS_V4_1 */ 301#else /* CONFIG_NFS_V4_1 */
306 302
307static inline void pnfs_destroy_all_layouts(struct nfs_client *clp) 303static inline void pnfs_destroy_all_layouts(struct nfs_client *clp)
@@ -385,9 +381,14 @@ static inline void unset_pnfs_layoutdriver(struct nfs_server *s)
385{ 381{
386} 382}
387 383
388static inline void pnfs_pageio_init(struct nfs_pageio_descriptor *pgio, 384static inline bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
389 struct inode *inode)
390{ 385{
386 return false;
387}
388
389static inline bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags)
390{
391 return false;
391} 392}
392 393
393static inline void 394static inline void
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 20a7f952e24..b6d9ec9a208 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -32,6 +32,7 @@
32 32
33static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc); 33static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc);
34static int nfs_pagein_one(struct nfs_pageio_descriptor *desc); 34static int nfs_pagein_one(struct nfs_pageio_descriptor *desc);
35static const struct nfs_pageio_ops nfs_pageio_read_ops;
35static const struct rpc_call_ops nfs_read_partial_ops; 36static const struct rpc_call_ops nfs_read_partial_ops;
36static const struct rpc_call_ops nfs_read_full_ops; 37static const struct rpc_call_ops nfs_read_full_ops;
37 38
@@ -113,6 +114,20 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)
113 } 114 }
114} 115}
115 116
117static void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
118 struct inode *inode)
119{
120 nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops,
121 NFS_SERVER(inode)->rsize, 0);
122}
123
124static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
125 struct inode *inode)
126{
127 if (!pnfs_pageio_init_read(pgio, inode))
128 nfs_pageio_init_read_mds(pgio, inode);
129}
130
116int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, 131int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
117 struct page *page) 132 struct page *page)
118{ 133{
@@ -131,14 +146,11 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
131 if (len < PAGE_CACHE_SIZE) 146 if (len < PAGE_CACHE_SIZE)
132 zero_user_segment(page, len, PAGE_CACHE_SIZE); 147 zero_user_segment(page, len, PAGE_CACHE_SIZE);
133 148
134 nfs_pageio_init(&pgio, inode, NULL, 0, 0); 149 nfs_pageio_init_read(&pgio, inode);
135 nfs_list_add_request(new, &pgio.pg_list); 150 nfs_list_add_request(new, &pgio.pg_list);
136 pgio.pg_count = len; 151 pgio.pg_count = len;
137 152
138 if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) 153 nfs_pageio_complete(&pgio);
139 nfs_pagein_multi(&pgio);
140 else
141 nfs_pagein_one(&pgio);
142 return 0; 154 return 0;
143} 155}
144 156
@@ -365,6 +377,20 @@ out:
365 return ret; 377 return ret;
366} 378}
367 379
380int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
381{
382 if (desc->pg_bsize < PAGE_CACHE_SIZE)
383 return nfs_pagein_multi(desc);
384 return nfs_pagein_one(desc);
385}
386EXPORT_SYMBOL_GPL(nfs_generic_pg_readpages);
387
388
389static const struct nfs_pageio_ops nfs_pageio_read_ops = {
390 .pg_test = nfs_generic_pg_test,
391 .pg_doio = nfs_generic_pg_readpages,
392};
393
368/* 394/*
369 * This is the callback from RPC telling us whether a reply was 395 * This is the callback from RPC telling us whether a reply was
370 * received or some error occurred (timeout or socket shutdown). 396 * received or some error occurred (timeout or socket shutdown).
@@ -635,8 +661,6 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
635 .pgio = &pgio, 661 .pgio = &pgio,
636 }; 662 };
637 struct inode *inode = mapping->host; 663 struct inode *inode = mapping->host;
638 struct nfs_server *server = NFS_SERVER(inode);
639 size_t rsize = server->rsize;
640 unsigned long npages; 664 unsigned long npages;
641 int ret = -ESTALE; 665 int ret = -ESTALE;
642 666
@@ -664,10 +688,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
664 if (ret == 0) 688 if (ret == 0)
665 goto read_complete; /* all pages were read */ 689 goto read_complete; /* all pages were read */
666 690
667 if (rsize < PAGE_CACHE_SIZE) 691 nfs_pageio_init_read(&pgio, inode);
668 nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
669 else
670 nfs_pageio_init(&pgio, inode, nfs_pagein_one, rsize, 0);
671 692
672 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); 693 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
673 694
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 72716805968..b144b547454 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1033,15 +1033,31 @@ out:
1033 return ret; 1033 return ret;
1034} 1034}
1035 1035
1036static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, 1036int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1037{
1038 if (desc->pg_bsize < PAGE_CACHE_SIZE)
1039 return nfs_flush_multi(desc);
1040 return nfs_flush_one(desc);
1041}
1042EXPORT_SYMBOL_GPL(nfs_generic_pg_writepages);
1043
1044static const struct nfs_pageio_ops nfs_pageio_write_ops = {
1045 .pg_test = nfs_generic_pg_test,
1046 .pg_doio = nfs_generic_pg_writepages,
1047};
1048
1049static void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
1037 struct inode *inode, int ioflags) 1050 struct inode *inode, int ioflags)
1038{ 1051{
1039 size_t wsize = NFS_SERVER(inode)->wsize; 1052 nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops,
1053 NFS_SERVER(inode)->wsize, ioflags);
1054}
1040 1055
1041 if (wsize < PAGE_CACHE_SIZE) 1056static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
1042 nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags); 1057 struct inode *inode, int ioflags)
1043 else 1058{
1044 nfs_pageio_init(pgio, inode, nfs_flush_one, wsize, ioflags); 1059 if (!pnfs_pageio_init_write(pgio, inode, ioflags))
1060 nfs_pageio_init_write_mds(pgio, inode, ioflags);
1045} 1061}
1046 1062
1047/* 1063/*
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 25311b3bedf..d378f08b905 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -55,6 +55,12 @@ struct nfs_page {
55 struct nfs_writeverf wb_verf; /* Commit cookie */ 55 struct nfs_writeverf wb_verf; /* Commit cookie */
56}; 56};
57 57
58struct nfs_pageio_descriptor;
59struct nfs_pageio_ops {
60 bool (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);
61 int (*pg_doio)(struct nfs_pageio_descriptor *);
62};
63
58struct nfs_pageio_descriptor { 64struct nfs_pageio_descriptor {
59 struct list_head pg_list; 65 struct list_head pg_list;
60 unsigned long pg_bytes_written; 66 unsigned long pg_bytes_written;
@@ -64,11 +70,10 @@ struct nfs_pageio_descriptor {
64 char pg_moreio; 70 char pg_moreio;
65 71
66 struct inode *pg_inode; 72 struct inode *pg_inode;
67 int (*pg_doio)(struct nfs_pageio_descriptor *); 73 const struct nfs_pageio_ops *pg_ops;
68 int pg_ioflags; 74 int pg_ioflags;
69 int pg_error; 75 int pg_error;
70 struct pnfs_layout_segment *pg_lseg; 76 struct pnfs_layout_segment *pg_lseg;
71 bool (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);
72}; 77};
73 78
74#define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags)) 79#define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags))
@@ -85,7 +90,7 @@ extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst,
85 pgoff_t idx_start, unsigned int npages, int tag); 90 pgoff_t idx_start, unsigned int npages, int tag);
86extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc, 91extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
87 struct inode *inode, 92 struct inode *inode,
88 int (*doio)(struct nfs_pageio_descriptor *desc), 93 const struct nfs_pageio_ops *pg_ops,
89 size_t bsize, 94 size_t bsize,
90 int how); 95 int how);
91extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *, 96extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
@@ -100,6 +105,9 @@ extern void nfs_unlock_request(struct nfs_page *req);
100extern int nfs_set_page_tag_locked(struct nfs_page *req); 105extern int nfs_set_page_tag_locked(struct nfs_page *req);
101extern void nfs_clear_page_tag_locked(struct nfs_page *req); 106extern void nfs_clear_page_tag_locked(struct nfs_page *req);
102 107
108extern int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
109extern int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc);
110
103 111
104/* 112/*
105 * Lock the page of an asynchronous request without getting a new reference 113 * Lock the page of an asynchronous request without getting a new reference