Commit 1751c3638f2a07a8c66a803a31791bab9bd3fced

Authored by Trond Myklebust
1 parent f062eb6ced

NFS: Cleanup of the nfs_pageio code in preparation for a pnfs bugfix

We need to ensure that the layouts are set up before we can decide to
coalesce requests. To do so, we want to further split up the struct
nfs_pageio_descriptor operations into an initialisation callback, a
coalescing test callback, and a 'do i/o' callback.

This patch cleans up the existing callback methods before adding the
'initialisation' callback.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 8 changed files with 131 additions and 41 deletions Side-by-side Diff

fs/nfs/nfs4filelayout.c
... ... @@ -658,7 +658,7 @@
658 658 * return true : coalesce page
659 659 * return false : don't coalesce page
660 660 */
661   -bool
  661 +static bool
662 662 filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
663 663 struct nfs_page *req)
664 664 {
... ... @@ -681,6 +681,16 @@
681 681 return (p_stripe == r_stripe);
682 682 }
683 683  
  684 +static const struct nfs_pageio_ops filelayout_pg_read_ops = {
  685 + .pg_test = filelayout_pg_test,
  686 + .pg_doio = nfs_generic_pg_readpages,
  687 +};
  688 +
  689 +static const struct nfs_pageio_ops filelayout_pg_write_ops = {
  690 + .pg_test = filelayout_pg_test,
  691 + .pg_doio = nfs_generic_pg_writepages,
  692 +};
  693 +
684 694 static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg)
685 695 {
686 696 return !FILELAYOUT_LSEG(lseg)->commit_through_mds;
... ... @@ -878,7 +888,8 @@
878 888 .owner = THIS_MODULE,
879 889 .alloc_lseg = filelayout_alloc_lseg,
880 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 893 .mark_pnfs_commit = filelayout_mark_pnfs_commit,
883 894 .choose_commit_list = filelayout_choose_commit_list,
884 895 .commit_pagelist = filelayout_commit_pagelist,
fs/nfs/objlayout/objio_osd.c
... ... @@ -1007,6 +1007,16 @@
1007 1007 OBJIO_LSEG(pgio->pg_lseg)->max_io_size;
1008 1008 }
1009 1009  
  1010 +static const struct nfs_pageio_ops objio_pg_read_ops = {
  1011 + .pg_test = objio_pg_test,
  1012 + .pg_doio = nfs_generic_pg_readpages,
  1013 +};
  1014 +
  1015 +static const struct nfs_pageio_ops objio_pg_write_ops = {
  1016 + .pg_test = objio_pg_test,
  1017 + .pg_doio = nfs_generic_pg_writepages,
  1018 +};
  1019 +
1010 1020 static struct pnfs_layoutdriver_type objlayout_type = {
1011 1021 .id = LAYOUT_OSD2_OBJECTS,
1012 1022 .name = "LAYOUT_OSD2_OBJECTS",
... ... @@ -1020,7 +1030,8 @@
1020 1030  
1021 1031 .read_pagelist = objlayout_read_pagelist,
1022 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 1036 .free_deviceid_node = objio_free_deviceid_node,
1026 1037  
... ... @@ -230,7 +230,7 @@
230 230 */
231 231 void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
232 232 struct inode *inode,
233   - int (*doio)(struct nfs_pageio_descriptor *),
  233 + const struct nfs_pageio_ops *pg_ops,
234 234 size_t bsize,
235 235 int io_flags)
236 236 {
237 237  
... ... @@ -241,12 +241,10 @@
241 241 desc->pg_base = 0;
242 242 desc->pg_moreio = 0;
243 243 desc->pg_inode = inode;
244   - desc->pg_doio = doio;
  244 + desc->pg_ops = pg_ops;
245 245 desc->pg_ioflags = io_flags;
246 246 desc->pg_error = 0;
247 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 @@
276 274 return false;
277 275 if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
278 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 @@
311 309 static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
312 310 {
313 311 if (!list_empty(&desc->pg_list)) {
314   - int error = desc->pg_doio(desc);
  312 + int error = desc->pg_ops->pg_doio(desc);
315 313 if (error < 0)
316 314 desc->pg_error = error;
317 315 else
... ... @@ -1056,6 +1056,30 @@
1056 1056 }
1057 1057  
1058 1058 bool
  1059 +pnfs_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 +
  1070 +bool
  1071 +pnfs_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 +
  1082 +bool
1059 1083 pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
1060 1084 struct nfs_page *req)
1061 1085 {
... ... @@ -87,7 +87,8 @@
87 87 void (*free_lseg) (struct pnfs_layout_segment *lseg);
88 88  
89 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 93 /* Returns true if layoutdriver wants to divert this request to
93 94 * driver's commit routine.
... ... @@ -152,6 +153,10 @@
152 153 pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
153 154 loff_t pos, u64 count, enum pnfs_iomode access_type,
154 155 gfp_t gfp_flags);
  156 +
  157 +bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
  158 +bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int);
  159 +
155 160 void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
156 161 void unset_pnfs_layoutdriver(struct nfs_server *);
157 162 enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
... ... @@ -293,15 +298,6 @@
293 298 return 0;
294 299 }
295 300  
296   -static 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 301 #else /* CONFIG_NFS_V4_1 */
306 302  
307 303 static inline void pnfs_destroy_all_layouts(struct nfs_client *clp)
308 304  
... ... @@ -385,9 +381,14 @@
385 381 {
386 382 }
387 383  
388   -static inline void pnfs_pageio_init(struct nfs_pageio_descriptor *pgio,
389   - struct inode *inode)
  384 +static inline bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
390 385 {
  386 + return false;
  387 +}
  388 +
  389 +static inline bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags)
  390 +{
  391 + return false;
391 392 }
392 393  
393 394 static inline void
... ... @@ -32,6 +32,7 @@
32 32  
33 33 static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc);
34 34 static int nfs_pagein_one(struct nfs_pageio_descriptor *desc);
  35 +static const struct nfs_pageio_ops nfs_pageio_read_ops;
35 36 static const struct rpc_call_ops nfs_read_partial_ops;
36 37 static const struct rpc_call_ops nfs_read_full_ops;
37 38  
... ... @@ -113,6 +114,20 @@
113 114 }
114 115 }
115 116  
  117 +static 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 +
  124 +static 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 +
116 131 int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
117 132 struct page *page)
118 133 {
119 134  
... ... @@ -131,14 +146,11 @@
131 146 if (len < PAGE_CACHE_SIZE)
132 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 150 nfs_list_add_request(new, &pgio.pg_list);
136 151 pgio.pg_count = len;
137 152  
138   - if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
139   - nfs_pagein_multi(&pgio);
140   - else
141   - nfs_pagein_one(&pgio);
  153 + nfs_pageio_complete(&pgio);
142 154 return 0;
143 155 }
144 156  
... ... @@ -365,6 +377,20 @@
365 377 return ret;
366 378 }
367 379  
  380 +int 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 +}
  386 +EXPORT_SYMBOL_GPL(nfs_generic_pg_readpages);
  387 +
  388 +
  389 +static 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 395 * This is the callback from RPC telling us whether a reply was
370 396 * received or some error occurred (timeout or socket shutdown).
... ... @@ -635,8 +661,6 @@
635 661 .pgio = &pgio,
636 662 };
637 663 struct inode *inode = mapping->host;
638   - struct nfs_server *server = NFS_SERVER(inode);
639   - size_t rsize = server->rsize;
640 664 unsigned long npages;
641 665 int ret = -ESTALE;
642 666  
... ... @@ -664,10 +688,7 @@
664 688 if (ret == 0)
665 689 goto read_complete; /* all pages were read */
666 690  
667   - if (rsize < PAGE_CACHE_SIZE)
668   - nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
669   - else
670   - nfs_pageio_init(&pgio, inode, nfs_pagein_one, rsize, 0);
  691 + nfs_pageio_init_read(&pgio, inode);
671 692  
672 693 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
673 694  
... ... @@ -1033,15 +1033,31 @@
1033 1033 return ret;
1034 1034 }
1035 1035  
1036   -static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
  1036 +int 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 +}
  1042 +EXPORT_SYMBOL_GPL(nfs_generic_pg_writepages);
  1043 +
  1044 +static 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 +
  1049 +static void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
1037 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)
1042   - nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags);
1043   - else
1044   - nfs_pageio_init(pgio, inode, nfs_flush_one, wsize, ioflags);
  1056 +static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
  1057 + struct inode *inode, int ioflags)
  1058 +{
  1059 + if (!pnfs_pageio_init_write(pgio, inode, ioflags))
  1060 + nfs_pageio_init_write_mds(pgio, inode, ioflags);
1045 1061 }
1046 1062  
1047 1063 /*
include/linux/nfs_page.h
... ... @@ -55,6 +55,12 @@
55 55 struct nfs_writeverf wb_verf; /* Commit cookie */
56 56 };
57 57  
  58 +struct nfs_pageio_descriptor;
  59 +struct 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 +
58 64 struct nfs_pageio_descriptor {
59 65 struct list_head pg_list;
60 66 unsigned long pg_bytes_written;
61 67  
... ... @@ -64,11 +70,10 @@
64 70 char pg_moreio;
65 71  
66 72 struct inode *pg_inode;
67   - int (*pg_doio)(struct nfs_pageio_descriptor *);
  73 + const struct nfs_pageio_ops *pg_ops;
68 74 int pg_ioflags;
69 75 int pg_error;
70 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 79 #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags))
... ... @@ -85,7 +90,7 @@
85 90 pgoff_t idx_start, unsigned int npages, int tag);
86 91 extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
87 92 struct inode *inode,
88   - int (*doio)(struct nfs_pageio_descriptor *desc),
  93 + const struct nfs_pageio_ops *pg_ops,
89 94 size_t bsize,
90 95 int how);
91 96 extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
... ... @@ -99,6 +104,9 @@
99 104 extern void nfs_unlock_request(struct nfs_page *req);
100 105 extern int nfs_set_page_tag_locked(struct nfs_page *req);
101 106 extern void nfs_clear_page_tag_locked(struct nfs_page *req);
  107 +
  108 +extern int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
  109 +extern int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc);
102 110  
103 111  
104 112 /*