aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/internal.h6
-rw-r--r--fs/nfs/nfs4filelayout.c2
-rw-r--r--fs/nfs/objlayout/objio_osd.c2
-rw-r--r--fs/nfs/pnfs.c57
-rw-r--r--fs/nfs/pnfs.h10
-rw-r--r--fs/nfs/read.c46
-rw-r--r--include/linux/nfs_page.h1
7 files changed, 83 insertions, 41 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 31e8b50011a..d74d7dea917 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -291,14 +291,18 @@ extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
291extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); 291extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh);
292#endif 292#endif
293 293
294struct nfs_pageio_descriptor;
294/* read.c */ 295/* read.c */
295extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, 296extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt,
296 const struct rpc_call_ops *call_ops); 297 const struct rpc_call_ops *call_ops);
297extern void nfs_read_prepare(struct rpc_task *task, void *calldata); 298extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
299extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
300 struct list_head *head);
298 301
299struct nfs_pageio_descriptor;
300extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, 302extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
301 struct inode *inode); 303 struct inode *inode);
304extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
305extern void nfs_readdata_release(struct nfs_read_data *rdata);
302 306
303/* write.c */ 307/* write.c */
304extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, 308extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index af9bf9eed4c..fc556d6b90f 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -735,7 +735,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
735static const struct nfs_pageio_ops filelayout_pg_read_ops = { 735static const struct nfs_pageio_ops filelayout_pg_read_ops = {
736 .pg_init = filelayout_pg_init_read, 736 .pg_init = filelayout_pg_init_read,
737 .pg_test = filelayout_pg_test, 737 .pg_test = filelayout_pg_test,
738 .pg_doio = nfs_generic_pg_readpages, 738 .pg_doio = pnfs_generic_pg_readpages,
739}; 739};
740 740
741static const struct nfs_pageio_ops filelayout_pg_write_ops = { 741static const struct nfs_pageio_ops filelayout_pg_write_ops = {
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
index 70272d5355b..add62894f36 100644
--- a/fs/nfs/objlayout/objio_osd.c
+++ b/fs/nfs/objlayout/objio_osd.c
@@ -1007,7 +1007,7 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
1007static const struct nfs_pageio_ops objio_pg_read_ops = { 1007static const struct nfs_pageio_ops objio_pg_read_ops = {
1008 .pg_init = pnfs_generic_pg_init_read, 1008 .pg_init = pnfs_generic_pg_init_read,
1009 .pg_test = objio_pg_test, 1009 .pg_test = objio_pg_test,
1010 .pg_doio = nfs_generic_pg_readpages, 1010 .pg_doio = pnfs_generic_pg_readpages,
1011}; 1011};
1012 1012
1013static const struct nfs_pageio_ops objio_pg_write_ops = { 1013static const struct nfs_pageio_ops objio_pg_write_ops = {
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 5b3cc3f4bb3..9eca5a8cdbd 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -28,6 +28,7 @@
28 */ 28 */
29 29
30#include <linux/nfs_fs.h> 30#include <linux/nfs_fs.h>
31#include <linux/nfs_page.h>
31#include "internal.h" 32#include "internal.h"
32#include "pnfs.h" 33#include "pnfs.h"
33#include "iostat.h" 34#include "iostat.h"
@@ -1216,18 +1217,32 @@ pnfs_ld_read_done(struct nfs_read_data *data)
1216} 1217}
1217EXPORT_SYMBOL_GPL(pnfs_ld_read_done); 1218EXPORT_SYMBOL_GPL(pnfs_ld_read_done);
1218 1219
1220static void
1221pnfs_read_through_mds(struct nfs_pageio_descriptor *desc,
1222 struct nfs_read_data *data)
1223{
1224 list_splice_tail_init(&data->pages, &desc->pg_list);
1225 if (data->req && list_empty(&data->req->wb_list))
1226 nfs_list_add_request(data->req, &desc->pg_list);
1227 nfs_pageio_reset_read_mds(desc);
1228 desc->pg_recoalesce = 1;
1229 nfs_readdata_release(data);
1230}
1231
1219/* 1232/*
1220 * Call the appropriate parallel I/O subsystem read function. 1233 * Call the appropriate parallel I/O subsystem read function.
1221 */ 1234 */
1222enum pnfs_try_status 1235static enum pnfs_try_status
1223pnfs_try_to_read_data(struct nfs_read_data *rdata, 1236pnfs_try_to_read_data(struct nfs_read_data *rdata,
1224 const struct rpc_call_ops *call_ops) 1237 const struct rpc_call_ops *call_ops,
1238 struct pnfs_layout_segment *lseg)
1225{ 1239{
1226 struct inode *inode = rdata->inode; 1240 struct inode *inode = rdata->inode;
1227 struct nfs_server *nfss = NFS_SERVER(inode); 1241 struct nfs_server *nfss = NFS_SERVER(inode);
1228 enum pnfs_try_status trypnfs; 1242 enum pnfs_try_status trypnfs;
1229 1243
1230 rdata->mds_ops = call_ops; 1244 rdata->mds_ops = call_ops;
1245 rdata->lseg = get_lseg(lseg);
1231 1246
1232 dprintk("%s: Reading ino:%lu %u@%llu\n", 1247 dprintk("%s: Reading ino:%lu %u@%llu\n",
1233 __func__, inode->i_ino, rdata->args.count, rdata->args.offset); 1248 __func__, inode->i_ino, rdata->args.count, rdata->args.offset);
@@ -1243,6 +1258,44 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata,
1243 return trypnfs; 1258 return trypnfs;
1244} 1259}
1245 1260
1261static void
1262pnfs_do_multiple_reads(struct nfs_pageio_descriptor *desc, struct list_head *head)
1263{
1264 struct nfs_read_data *data;
1265 const struct rpc_call_ops *call_ops = desc->pg_rpc_callops;
1266 struct pnfs_layout_segment *lseg = desc->pg_lseg;
1267
1268 desc->pg_lseg = NULL;
1269 while (!list_empty(head)) {
1270 enum pnfs_try_status trypnfs;
1271
1272 data = list_entry(head->next, struct nfs_read_data, list);
1273 list_del_init(&data->list);
1274
1275 trypnfs = pnfs_try_to_read_data(data, call_ops, lseg);
1276 if (trypnfs == PNFS_NOT_ATTEMPTED)
1277 pnfs_read_through_mds(desc, data);
1278 }
1279 put_lseg(lseg);
1280}
1281
1282int
1283pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
1284{
1285 LIST_HEAD(head);
1286 int ret;
1287
1288 ret = nfs_generic_pagein(desc, &head);
1289 if (ret != 0) {
1290 put_lseg(desc->pg_lseg);
1291 desc->pg_lseg = NULL;
1292 return ret;
1293 }
1294 pnfs_do_multiple_reads(desc, &head);
1295 return 0;
1296}
1297EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages);
1298
1246/* 1299/*
1247 * Currently there is only one (whole file) write lseg. 1300 * Currently there is only one (whole file) write lseg.
1248 */ 1301 */
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index a59736eae6e..c40ffa52c1a 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -157,9 +157,8 @@ void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
157void unset_pnfs_layoutdriver(struct nfs_server *); 157void unset_pnfs_layoutdriver(struct nfs_server *);
158enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, 158enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
159 const struct rpc_call_ops *, int); 159 const struct rpc_call_ops *, int);
160enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *,
161 const struct rpc_call_ops *);
162void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); 160void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
161int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
163void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); 162void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *);
164bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); 163bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req);
165int pnfs_layout_process(struct nfs4_layoutget *lgp); 164int pnfs_layout_process(struct nfs4_layoutget *lgp);
@@ -330,13 +329,6 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg)
330} 329}
331 330
332static inline enum pnfs_try_status 331static inline enum pnfs_try_status
333pnfs_try_to_read_data(struct nfs_read_data *data,
334 const struct rpc_call_ops *call_ops)
335{
336 return PNFS_NOT_ATTEMPTED;
337}
338
339static inline enum pnfs_try_status
340pnfs_try_to_write_data(struct nfs_write_data *data, 332pnfs_try_to_write_data(struct nfs_write_data *data,
341 const struct rpc_call_ops *call_ops, int how) 333 const struct rpc_call_ops *call_ops, int how)
342{ 334{
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 75088f58183..d2f53ddd826 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -67,7 +67,7 @@ void nfs_readdata_free(struct nfs_read_data *p)
67 mempool_free(p, nfs_rdata_mempool); 67 mempool_free(p, nfs_rdata_mempool);
68} 68}
69 69
70static void nfs_readdata_release(struct nfs_read_data *rdata) 70void nfs_readdata_release(struct nfs_read_data *rdata)
71{ 71{
72 put_lseg(rdata->lseg); 72 put_lseg(rdata->lseg);
73 put_nfs_open_context(rdata->args.context); 73 put_nfs_open_context(rdata->args.context);
@@ -120,6 +120,12 @@ void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
120} 120}
121EXPORT_SYMBOL_GPL(nfs_pageio_init_read_mds); 121EXPORT_SYMBOL_GPL(nfs_pageio_init_read_mds);
122 122
123void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
124{
125 pgio->pg_ops = &nfs_pageio_read_ops;
126 pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->rsize;
127}
128
123static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, 129static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
124 struct inode *inode) 130 struct inode *inode)
125{ 131{
@@ -235,26 +241,16 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
235} 241}
236 242
237static int nfs_do_read(struct nfs_read_data *data, 243static int nfs_do_read(struct nfs_read_data *data,
238 const struct rpc_call_ops *call_ops, 244 const struct rpc_call_ops *call_ops)
239 struct pnfs_layout_segment *lseg)
240{ 245{
241 struct inode *inode = data->args.context->path.dentry->d_inode; 246 struct inode *inode = data->args.context->path.dentry->d_inode;
242 247
243 if (lseg) {
244 data->lseg = get_lseg(lseg);
245 if (pnfs_try_to_read_data(data, call_ops) == PNFS_ATTEMPTED)
246 return 0;
247 put_lseg(data->lseg);
248 data->lseg = NULL;
249 }
250
251 return nfs_initiate_read(data, NFS_CLIENT(inode), call_ops); 248 return nfs_initiate_read(data, NFS_CLIENT(inode), call_ops);
252} 249}
253 250
254static int 251static int
255nfs_do_multiple_reads(struct list_head *head, 252nfs_do_multiple_reads(struct list_head *head,
256 const struct rpc_call_ops *call_ops, 253 const struct rpc_call_ops *call_ops)
257 struct pnfs_layout_segment *lseg)
258{ 254{
259 struct nfs_read_data *data; 255 struct nfs_read_data *data;
260 int ret = 0; 256 int ret = 0;
@@ -265,7 +261,7 @@ nfs_do_multiple_reads(struct list_head *head,
265 data = list_entry(head->next, struct nfs_read_data, list); 261 data = list_entry(head->next, struct nfs_read_data, list);
266 list_del_init(&data->list); 262 list_del_init(&data->list);
267 263
268 ret2 = nfs_do_read(data, call_ops, lseg); 264 ret2 = nfs_do_read(data, call_ops);
269 if (ret == 0) 265 if (ret == 0)
270 ret = ret2; 266 ret = ret2;
271 } 267 }
@@ -373,25 +369,23 @@ out:
373 return ret; 369 return ret;
374} 370}
375 371
376int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) 372int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, struct list_head *head)
373{
374 if (desc->pg_bsize < PAGE_CACHE_SIZE)
375 return nfs_pagein_multi(desc, head);
376 return nfs_pagein_one(desc, head);
377}
378
379static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
377{ 380{
378 LIST_HEAD(head); 381 LIST_HEAD(head);
379 int ret; 382 int ret;
380 383
381 if (desc->pg_bsize < PAGE_CACHE_SIZE) 384 ret = nfs_generic_pagein(desc, &head);
382 ret = nfs_pagein_multi(desc, &head);
383 else
384 ret = nfs_pagein_one(desc, &head);
385
386 if (ret == 0) 385 if (ret == 0)
387 ret = nfs_do_multiple_reads(&head, desc->pg_rpc_callops, 386 ret = nfs_do_multiple_reads(&head, desc->pg_rpc_callops);
388 desc->pg_lseg);
389 put_lseg(desc->pg_lseg);
390 desc->pg_lseg = NULL;
391 return ret; 387 return ret;
392} 388}
393EXPORT_SYMBOL_GPL(nfs_generic_pg_readpages);
394
395 389
396static const struct nfs_pageio_ops nfs_pageio_read_ops = { 390static const struct nfs_pageio_ops nfs_pageio_read_ops = {
397 .pg_test = nfs_generic_pg_test, 391 .pg_test = nfs_generic_pg_test,
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 7241b2a2a4d..0a48f842f83 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -108,7 +108,6 @@ extern void nfs_unlock_request(struct nfs_page *req);
108extern int nfs_set_page_tag_locked(struct nfs_page *req); 108extern int nfs_set_page_tag_locked(struct nfs_page *req);
109extern void nfs_clear_page_tag_locked(struct nfs_page *req); 109extern void nfs_clear_page_tag_locked(struct nfs_page *req);
110 110
111extern int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
112extern int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc); 111extern int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc);
113 112
114 113