diff options
author | Anna Schumaker <Anna.Schumaker@netapp.com> | 2014-05-06 09:12:32 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-05-28 18:40:36 -0400 |
commit | 0eecb2145c1ce18e36617008424a93836ad0a3bd (patch) | |
tree | 469884c95d6e3c65383800e0c41b197d44851543 | |
parent | a4cdda59111f92000297e0d3edb1e0e08ba3549b (diff) |
NFS: Create a common nfs_pgio_result_common function
Combining these functions will let me make a single nfs_rw_common_ops
struct (see the next patch).
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/internal.h | 1 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 23 | ||||
-rw-r--r-- | fs/nfs/read.c | 25 | ||||
-rw-r--r-- | fs/nfs/write.c | 51 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 2 | ||||
-rw-r--r-- | include/linux/nfs_page.h | 2 |
6 files changed, 54 insertions, 50 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 1959260f8c57..7c0ae364bdad 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -243,6 +243,7 @@ struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int | |||
243 | void nfs_pgio_data_release(struct nfs_pgio_data *); | 243 | void nfs_pgio_data_release(struct nfs_pgio_data *); |
244 | void nfs_pgio_prepare(struct rpc_task *, void *); | 244 | void nfs_pgio_prepare(struct rpc_task *, void *); |
245 | void nfs_pgio_release(void *); | 245 | void nfs_pgio_release(void *); |
246 | void nfs_pgio_result(struct rpc_task *, void *); | ||
246 | 247 | ||
247 | static inline void nfs_iocounter_init(struct nfs_io_counter *c) | 248 | static inline void nfs_iocounter_init(struct nfs_io_counter *c) |
248 | { | 249 | { |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 0fa211d35e40..f74df87058b6 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include "internal.h" | 24 | #include "internal.h" |
25 | #include "pnfs.h" | 25 | #include "pnfs.h" |
26 | 26 | ||
27 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | ||
28 | |||
27 | static struct kmem_cache *nfs_page_cachep; | 29 | static struct kmem_cache *nfs_page_cachep; |
28 | 30 | ||
29 | static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount) | 31 | static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount) |
@@ -447,6 +449,27 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
447 | } | 449 | } |
448 | EXPORT_SYMBOL_GPL(nfs_pageio_init); | 450 | EXPORT_SYMBOL_GPL(nfs_pageio_init); |
449 | 451 | ||
452 | /** | ||
453 | * nfs_pgio_result - Basic pageio error handling | ||
454 | * @task: The task that ran | ||
455 | * @calldata: Pageio data to check | ||
456 | */ | ||
457 | void nfs_pgio_result(struct rpc_task *task, void *calldata) | ||
458 | { | ||
459 | struct nfs_pgio_data *data = calldata; | ||
460 | struct inode *inode = data->header->inode; | ||
461 | |||
462 | dprintk("NFS: %s: %5u, (status %d)\n", __func__, | ||
463 | task->tk_pid, task->tk_status); | ||
464 | |||
465 | if (data->header->rw_ops->rw_done(task, data, inode) != 0) | ||
466 | return; | ||
467 | if (task->tk_status < 0) | ||
468 | nfs_set_pgio_error(data->header, task->tk_status, data->args.offset); | ||
469 | else | ||
470 | data->header->rw_ops->rw_result(task, data); | ||
471 | } | ||
472 | |||
450 | static bool nfs_match_open_context(const struct nfs_open_context *ctx1, | 473 | static bool nfs_match_open_context(const struct nfs_open_context *ctx1, |
451 | const struct nfs_open_context *ctx2) | 474 | const struct nfs_open_context *ctx2) |
452 | { | 475 | { |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index cfa15e828dd6..bc78bd248eb8 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -388,15 +388,10 @@ static const struct nfs_pageio_ops nfs_pageio_read_ops = { | |||
388 | * This is the callback from RPC telling us whether a reply was | 388 | * This is the callback from RPC telling us whether a reply was |
389 | * received or some error occurred (timeout or socket shutdown). | 389 | * received or some error occurred (timeout or socket shutdown). |
390 | */ | 390 | */ |
391 | int nfs_readpage_result(struct rpc_task *task, struct nfs_pgio_data *data) | 391 | static int nfs_readpage_done(struct rpc_task *task, struct nfs_pgio_data *data, |
392 | struct inode *inode) | ||
392 | { | 393 | { |
393 | struct inode *inode = data->header->inode; | 394 | int status = NFS_PROTO(inode)->read_done(task, data); |
394 | int status; | ||
395 | |||
396 | dprintk("NFS: %s: %5u, (status %d)\n", __func__, task->tk_pid, | ||
397 | task->tk_status); | ||
398 | |||
399 | status = NFS_PROTO(inode)->read_done(task, data); | ||
400 | if (status != 0) | 395 | if (status != 0) |
401 | return status; | 396 | return status; |
402 | 397 | ||
@@ -429,17 +424,11 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_pgio_data *data | |||
429 | rpc_restart_call_prepare(task); | 424 | rpc_restart_call_prepare(task); |
430 | } | 425 | } |
431 | 426 | ||
432 | static void nfs_readpage_result_common(struct rpc_task *task, void *calldata) | 427 | static void nfs_readpage_result(struct rpc_task *task, struct nfs_pgio_data *data) |
433 | { | 428 | { |
434 | struct nfs_pgio_data *data = calldata; | ||
435 | struct nfs_pgio_header *hdr = data->header; | 429 | struct nfs_pgio_header *hdr = data->header; |
436 | 430 | ||
437 | /* Note the only returns of nfs_readpage_result are 0 and -EAGAIN */ | 431 | if (data->res.eof) { |
438 | if (nfs_readpage_result(task, data) != 0) | ||
439 | return; | ||
440 | if (task->tk_status < 0) | ||
441 | nfs_set_pgio_error(hdr, task->tk_status, data->args.offset); | ||
442 | else if (data->res.eof) { | ||
443 | loff_t bound; | 432 | loff_t bound; |
444 | 433 | ||
445 | bound = data->args.offset + data->res.count; | 434 | bound = data->args.offset + data->res.count; |
@@ -456,7 +445,7 @@ static void nfs_readpage_result_common(struct rpc_task *task, void *calldata) | |||
456 | 445 | ||
457 | static const struct rpc_call_ops nfs_read_common_ops = { | 446 | static const struct rpc_call_ops nfs_read_common_ops = { |
458 | .rpc_call_prepare = nfs_pgio_prepare, | 447 | .rpc_call_prepare = nfs_pgio_prepare, |
459 | .rpc_call_done = nfs_readpage_result_common, | 448 | .rpc_call_done = nfs_pgio_result, |
460 | .rpc_release = nfs_pgio_release, | 449 | .rpc_release = nfs_pgio_release, |
461 | }; | 450 | }; |
462 | 451 | ||
@@ -625,4 +614,6 @@ static const struct nfs_rw_ops nfs_rw_read_ops = { | |||
625 | .rw_mode = FMODE_READ, | 614 | .rw_mode = FMODE_READ, |
626 | .rw_alloc_header = nfs_readhdr_alloc, | 615 | .rw_alloc_header = nfs_readhdr_alloc, |
627 | .rw_free_header = nfs_readhdr_free, | 616 | .rw_free_header = nfs_readhdr_free, |
617 | .rw_done = nfs_readpage_done, | ||
618 | .rw_result = nfs_readpage_result, | ||
628 | }; | 619 | }; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index ae799c96ec2b..1d3e1d75c8c5 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1255,20 +1255,6 @@ void nfs_commit_prepare(struct rpc_task *task, void *calldata) | |||
1255 | NFS_PROTO(data->inode)->commit_rpc_prepare(task, data); | 1255 | NFS_PROTO(data->inode)->commit_rpc_prepare(task, data); |
1256 | } | 1256 | } |
1257 | 1257 | ||
1258 | /* | ||
1259 | * Handle a write reply that flushes a whole page. | ||
1260 | * | ||
1261 | * FIXME: There is an inherent race with invalidate_inode_pages and | ||
1262 | * writebacks since the page->count is kept > 1 for as long | ||
1263 | * as the page has a write request pending. | ||
1264 | */ | ||
1265 | static void nfs_writeback_done_common(struct rpc_task *task, void *calldata) | ||
1266 | { | ||
1267 | struct nfs_pgio_data *data = calldata; | ||
1268 | |||
1269 | nfs_writeback_done(task, data); | ||
1270 | } | ||
1271 | |||
1272 | static void nfs_writeback_release_common(struct nfs_pgio_data *data) | 1258 | static void nfs_writeback_release_common(struct nfs_pgio_data *data) |
1273 | { | 1259 | { |
1274 | struct nfs_pgio_header *hdr = data->header; | 1260 | struct nfs_pgio_header *hdr = data->header; |
@@ -1288,7 +1274,7 @@ static void nfs_writeback_release_common(struct nfs_pgio_data *data) | |||
1288 | 1274 | ||
1289 | static const struct rpc_call_ops nfs_write_common_ops = { | 1275 | static const struct rpc_call_ops nfs_write_common_ops = { |
1290 | .rpc_call_prepare = nfs_pgio_prepare, | 1276 | .rpc_call_prepare = nfs_pgio_prepare, |
1291 | .rpc_call_done = nfs_writeback_done_common, | 1277 | .rpc_call_done = nfs_pgio_result, |
1292 | .rpc_release = nfs_pgio_release, | 1278 | .rpc_release = nfs_pgio_release, |
1293 | }; | 1279 | }; |
1294 | 1280 | ||
@@ -1320,16 +1306,11 @@ static int nfs_should_remove_suid(const struct inode *inode) | |||
1320 | /* | 1306 | /* |
1321 | * This function is called when the WRITE call is complete. | 1307 | * This function is called when the WRITE call is complete. |
1322 | */ | 1308 | */ |
1323 | void nfs_writeback_done(struct rpc_task *task, struct nfs_pgio_data *data) | 1309 | static int nfs_writeback_done(struct rpc_task *task, struct nfs_pgio_data *data, |
1310 | struct inode *inode) | ||
1324 | { | 1311 | { |
1325 | struct nfs_pgio_args *argp = &data->args; | ||
1326 | struct nfs_pgio_res *resp = &data->res; | ||
1327 | struct inode *inode = data->header->inode; | ||
1328 | int status; | 1312 | int status; |
1329 | 1313 | ||
1330 | dprintk("NFS: %5u nfs_writeback_done (status %d)\n", | ||
1331 | task->tk_pid, task->tk_status); | ||
1332 | |||
1333 | /* | 1314 | /* |
1334 | * ->write_done will attempt to use post-op attributes to detect | 1315 | * ->write_done will attempt to use post-op attributes to detect |
1335 | * conflicting writes by other clients. A strict interpretation | 1316 | * conflicting writes by other clients. A strict interpretation |
@@ -1339,11 +1320,11 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_pgio_data *data) | |||
1339 | */ | 1320 | */ |
1340 | status = NFS_PROTO(inode)->write_done(task, data); | 1321 | status = NFS_PROTO(inode)->write_done(task, data); |
1341 | if (status != 0) | 1322 | if (status != 0) |
1342 | return; | 1323 | return status; |
1343 | nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, resp->count); | 1324 | nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, data->res.count); |
1344 | 1325 | ||
1345 | #if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) | 1326 | #if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) |
1346 | if (resp->verf->committed < argp->stable && task->tk_status >= 0) { | 1327 | if (data->res.verf->committed < data->args.stable && task->tk_status >= 0) { |
1347 | /* We tried a write call, but the server did not | 1328 | /* We tried a write call, but the server did not |
1348 | * commit data to stable storage even though we | 1329 | * commit data to stable storage even though we |
1349 | * requested it. | 1330 | * requested it. |
@@ -1359,25 +1340,31 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_pgio_data *data) | |||
1359 | dprintk("NFS: faulty NFS server %s:" | 1340 | dprintk("NFS: faulty NFS server %s:" |
1360 | " (committed = %d) != (stable = %d)\n", | 1341 | " (committed = %d) != (stable = %d)\n", |
1361 | NFS_SERVER(inode)->nfs_client->cl_hostname, | 1342 | NFS_SERVER(inode)->nfs_client->cl_hostname, |
1362 | resp->verf->committed, argp->stable); | 1343 | data->res.verf->committed, data->args.stable); |
1363 | complain = jiffies + 300 * HZ; | 1344 | complain = jiffies + 300 * HZ; |
1364 | } | 1345 | } |
1365 | } | 1346 | } |
1366 | #endif | 1347 | #endif |
1367 | if (task->tk_status < 0) { | ||
1368 | nfs_set_pgio_error(data->header, task->tk_status, argp->offset); | ||
1369 | return; | ||
1370 | } | ||
1371 | 1348 | ||
1372 | /* Deal with the suid/sgid bit corner case */ | 1349 | /* Deal with the suid/sgid bit corner case */ |
1373 | if (nfs_should_remove_suid(inode)) | 1350 | if (nfs_should_remove_suid(inode)) |
1374 | nfs_mark_for_revalidate(inode); | 1351 | nfs_mark_for_revalidate(inode); |
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | /* | ||
1356 | * This function is called when the WRITE call is complete. | ||
1357 | */ | ||
1358 | static void nfs_writeback_result(struct rpc_task *task, struct nfs_pgio_data *data) | ||
1359 | { | ||
1360 | struct nfs_pgio_args *argp = &data->args; | ||
1361 | struct nfs_pgio_res *resp = &data->res; | ||
1375 | 1362 | ||
1376 | if (resp->count < argp->count) { | 1363 | if (resp->count < argp->count) { |
1377 | static unsigned long complain; | 1364 | static unsigned long complain; |
1378 | 1365 | ||
1379 | /* This a short write! */ | 1366 | /* This a short write! */ |
1380 | nfs_inc_stats(inode, NFSIOS_SHORTWRITE); | 1367 | nfs_inc_stats(data->header->inode, NFSIOS_SHORTWRITE); |
1381 | 1368 | ||
1382 | /* Has the server at least made some progress? */ | 1369 | /* Has the server at least made some progress? */ |
1383 | if (resp->count == 0) { | 1370 | if (resp->count == 0) { |
@@ -1911,4 +1898,6 @@ static const struct nfs_rw_ops nfs_rw_write_ops = { | |||
1911 | .rw_alloc_header = nfs_writehdr_alloc, | 1898 | .rw_alloc_header = nfs_writehdr_alloc, |
1912 | .rw_free_header = nfs_writehdr_free, | 1899 | .rw_free_header = nfs_writehdr_free, |
1913 | .rw_release = nfs_writeback_release_common, | 1900 | .rw_release = nfs_writeback_release_common, |
1901 | .rw_done = nfs_writeback_done, | ||
1902 | .rw_result = nfs_writeback_result, | ||
1914 | }; | 1903 | }; |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 7e0db561d829..919576b8e2cf 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -520,7 +520,6 @@ extern int nfs_writepage(struct page *page, struct writeback_control *wbc); | |||
520 | extern int nfs_writepages(struct address_space *, struct writeback_control *); | 520 | extern int nfs_writepages(struct address_space *, struct writeback_control *); |
521 | extern int nfs_flush_incompatible(struct file *file, struct page *page); | 521 | extern int nfs_flush_incompatible(struct file *file, struct page *page); |
522 | extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); | 522 | extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); |
523 | extern void nfs_writeback_done(struct rpc_task *, struct nfs_pgio_data *); | ||
524 | 523 | ||
525 | /* | 524 | /* |
526 | * Try to write back everything synchronously (but check the | 525 | * Try to write back everything synchronously (but check the |
@@ -553,7 +552,6 @@ nfs_have_writebacks(struct inode *inode) | |||
553 | extern int nfs_readpage(struct file *, struct page *); | 552 | extern int nfs_readpage(struct file *, struct page *); |
554 | extern int nfs_readpages(struct file *, struct address_space *, | 553 | extern int nfs_readpages(struct file *, struct address_space *, |
555 | struct list_head *, unsigned); | 554 | struct list_head *, unsigned); |
556 | extern int nfs_readpage_result(struct rpc_task *, struct nfs_pgio_data *); | ||
557 | extern int nfs_readpage_async(struct nfs_open_context *, struct inode *, | 555 | extern int nfs_readpage_async(struct nfs_open_context *, struct inode *, |
558 | struct page *); | 556 | struct page *); |
559 | 557 | ||
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index da00a4d6f470..01aa29c5ec42 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
@@ -57,6 +57,8 @@ struct nfs_rw_ops { | |||
57 | struct nfs_rw_header *(*rw_alloc_header)(void); | 57 | struct nfs_rw_header *(*rw_alloc_header)(void); |
58 | void (*rw_free_header)(struct nfs_rw_header *); | 58 | void (*rw_free_header)(struct nfs_rw_header *); |
59 | void (*rw_release)(struct nfs_pgio_data *); | 59 | void (*rw_release)(struct nfs_pgio_data *); |
60 | int (*rw_done)(struct rpc_task *, struct nfs_pgio_data *, struct inode *); | ||
61 | void (*rw_result)(struct rpc_task *, struct nfs_pgio_data *); | ||
60 | }; | 62 | }; |
61 | 63 | ||
62 | struct nfs_pageio_descriptor { | 64 | struct nfs_pageio_descriptor { |