diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-13 15:58:28 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-15 09:12:21 -0400 |
commit | 493292ddc78d18ee2ad2d5c24c2b7dd6a24641d2 (patch) | |
tree | cad42b32b7baa303189ddd6d791229c619f24f37 /fs | |
parent | d9156f9f364897e93bdd98b4ad22138de18f7c24 (diff) |
NFS: Move the pnfs read code into pnfs.c
...and ensure that we recoalese to take into account differences in
block sizes when falling back to read through the MDS.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/internal.h | 6 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 2 | ||||
-rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 2 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 57 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 10 | ||||
-rw-r--r-- | fs/nfs/read.c | 46 |
6 files changed, 83 insertions, 40 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 31e8b50011af..d74d7dea9173 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 *, | |||
291 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); | 291 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); |
292 | #endif | 292 | #endif |
293 | 293 | ||
294 | struct nfs_pageio_descriptor; | ||
294 | /* read.c */ | 295 | /* read.c */ |
295 | extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, | 296 | extern 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); |
297 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); | 298 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); |
299 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, | ||
300 | struct list_head *head); | ||
298 | 301 | ||
299 | struct nfs_pageio_descriptor; | ||
300 | extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, | 302 | extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, |
301 | struct inode *inode); | 303 | struct inode *inode); |
304 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); | ||
305 | extern void nfs_readdata_release(struct nfs_read_data *rdata); | ||
302 | 306 | ||
303 | /* write.c */ | 307 | /* write.c */ |
304 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | 308 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index af9bf9eed4ca..fc556d6b90f1 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -735,7 +735,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
735 | static const struct nfs_pageio_ops filelayout_pg_read_ops = { | 735 | static 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 | ||
741 | static const struct nfs_pageio_ops filelayout_pg_write_ops = { | 741 | static 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 70272d5355b2..add62894f364 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, | |||
1007 | static const struct nfs_pageio_ops objio_pg_read_ops = { | 1007 | static 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 | ||
1013 | static const struct nfs_pageio_ops objio_pg_write_ops = { | 1013 | static const struct nfs_pageio_ops objio_pg_write_ops = { |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 5b3cc3f4bb39..9eca5a8cdbdd 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 | } |
1217 | EXPORT_SYMBOL_GPL(pnfs_ld_read_done); | 1218 | EXPORT_SYMBOL_GPL(pnfs_ld_read_done); |
1218 | 1219 | ||
1220 | static void | ||
1221 | pnfs_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 | */ |
1222 | enum pnfs_try_status | 1235 | static enum pnfs_try_status |
1223 | pnfs_try_to_read_data(struct nfs_read_data *rdata, | 1236 | pnfs_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 | ||
1261 | static void | ||
1262 | pnfs_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 | |||
1282 | int | ||
1283 | pnfs_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 | } | ||
1297 | EXPORT_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 a59736eae6ec..c40ffa52c1ab 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -157,9 +157,8 @@ void set_pnfs_layoutdriver(struct nfs_server *, u32 id); | |||
157 | void unset_pnfs_layoutdriver(struct nfs_server *); | 157 | void unset_pnfs_layoutdriver(struct nfs_server *); |
158 | enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, | 158 | enum 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); |
160 | enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *, | ||
161 | const struct rpc_call_ops *); | ||
162 | void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); | 160 | void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); |
161 | int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc); | ||
163 | void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); | 162 | void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); |
164 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); | 163 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); |
165 | int pnfs_layout_process(struct nfs4_layoutget *lgp); | 164 | int 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 | ||
332 | static inline enum pnfs_try_status | 331 | static inline enum pnfs_try_status |
333 | pnfs_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 | |||
339 | static inline enum pnfs_try_status | ||
340 | pnfs_try_to_write_data(struct nfs_write_data *data, | 332 | pnfs_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 75088f58183b..d2f53ddd8260 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 | ||
70 | static void nfs_readdata_release(struct nfs_read_data *rdata) | 70 | void 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 | } |
121 | EXPORT_SYMBOL_GPL(nfs_pageio_init_read_mds); | 121 | EXPORT_SYMBOL_GPL(nfs_pageio_init_read_mds); |
122 | 122 | ||
123 | void 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 | |||
123 | static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, | 129 | static 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 | ||
237 | static int nfs_do_read(struct nfs_read_data *data, | 243 | static 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 | ||
254 | static int | 251 | static int |
255 | nfs_do_multiple_reads(struct list_head *head, | 252 | nfs_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 | ||
376 | int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | 372 | int 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 | |||
379 | static 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 | } |
393 | EXPORT_SYMBOL_GPL(nfs_generic_pg_readpages); | ||
394 | |||
395 | 389 | ||
396 | static const struct nfs_pageio_ops nfs_pageio_read_ops = { | 390 | static const struct nfs_pageio_ops nfs_pageio_read_ops = { |
397 | .pg_test = nfs_generic_pg_test, | 391 | .pg_test = nfs_generic_pg_test, |