diff options
-rw-r--r-- | fs/nfs/inode.c | 4 | ||||
-rw-r--r-- | fs/nfs/write.c | 72 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 10 |
3 files changed, 56 insertions, 30 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index a0cda53461b3..60aac58270a8 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -137,7 +137,7 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) | |||
137 | static int | 137 | static int |
138 | nfs_write_inode(struct inode *inode, int sync) | 138 | nfs_write_inode(struct inode *inode, int sync) |
139 | { | 139 | { |
140 | int flags = sync ? FLUSH_WAIT : 0; | 140 | int flags = sync ? FLUSH_SYNC : 0; |
141 | int ret; | 141 | int ret; |
142 | 142 | ||
143 | ret = nfs_commit_inode(inode, flags); | 143 | ret = nfs_commit_inode(inode, flags); |
@@ -1051,7 +1051,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
1051 | int err; | 1051 | int err; |
1052 | 1052 | ||
1053 | /* Flush out writes to the server in order to update c/mtime */ | 1053 | /* Flush out writes to the server in order to update c/mtime */ |
1054 | nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT); | 1054 | nfs_sync_inode_wait(inode, 0, 0, FLUSH_NOCOMMIT); |
1055 | 1055 | ||
1056 | /* | 1056 | /* |
1057 | * We may force a getattr if the user cares about atime. | 1057 | * We may force a getattr if the user cares about atime. |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 2beb1268bb1b..3f5225404c97 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -539,8 +539,7 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
539 | * | 539 | * |
540 | * Interruptible by signals only if mounted with intr flag. | 540 | * Interruptible by signals only if mounted with intr flag. |
541 | */ | 541 | */ |
542 | static int | 542 | static int nfs_wait_on_requests_locked(struct inode *inode, unsigned long idx_start, unsigned int npages) |
543 | nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int npages) | ||
544 | { | 543 | { |
545 | struct nfs_inode *nfsi = NFS_I(inode); | 544 | struct nfs_inode *nfsi = NFS_I(inode); |
546 | struct nfs_page *req; | 545 | struct nfs_page *req; |
@@ -553,7 +552,6 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int | |||
553 | else | 552 | else |
554 | idx_end = idx_start + npages - 1; | 553 | idx_end = idx_start + npages - 1; |
555 | 554 | ||
556 | spin_lock(&nfsi->req_lock); | ||
557 | next = idx_start; | 555 | next = idx_start; |
558 | while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) { | 556 | while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) { |
559 | if (req->wb_index > idx_end) | 557 | if (req->wb_index > idx_end) |
@@ -566,15 +564,25 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int | |||
566 | spin_unlock(&nfsi->req_lock); | 564 | spin_unlock(&nfsi->req_lock); |
567 | error = nfs_wait_on_request(req); | 565 | error = nfs_wait_on_request(req); |
568 | nfs_release_request(req); | 566 | nfs_release_request(req); |
567 | spin_lock(&nfsi->req_lock); | ||
569 | if (error < 0) | 568 | if (error < 0) |
570 | return error; | 569 | return error; |
571 | spin_lock(&nfsi->req_lock); | ||
572 | res++; | 570 | res++; |
573 | } | 571 | } |
574 | spin_unlock(&nfsi->req_lock); | ||
575 | return res; | 572 | return res; |
576 | } | 573 | } |
577 | 574 | ||
575 | static int nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int npages) | ||
576 | { | ||
577 | struct nfs_inode *nfsi = NFS_I(inode); | ||
578 | int ret; | ||
579 | |||
580 | spin_lock(&nfsi->req_lock); | ||
581 | ret = nfs_wait_on_requests_locked(inode, idx_start, npages); | ||
582 | spin_unlock(&nfsi->req_lock); | ||
583 | return ret; | ||
584 | } | ||
585 | |||
578 | /* | 586 | /* |
579 | * nfs_scan_dirty - Scan an inode for dirty requests | 587 | * nfs_scan_dirty - Scan an inode for dirty requests |
580 | * @inode: NFS inode to scan | 588 | * @inode: NFS inode to scan |
@@ -626,6 +634,11 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_st | |||
626 | } | 634 | } |
627 | return res; | 635 | return res; |
628 | } | 636 | } |
637 | #else | ||
638 | static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages) | ||
639 | { | ||
640 | return 0; | ||
641 | } | ||
629 | #endif | 642 | #endif |
630 | 643 | ||
631 | static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr) | 644 | static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr) |
@@ -1421,6 +1434,11 @@ static const struct rpc_call_ops nfs_commit_ops = { | |||
1421 | .rpc_call_done = nfs_commit_done, | 1434 | .rpc_call_done = nfs_commit_done, |
1422 | .rpc_release = nfs_commit_release, | 1435 | .rpc_release = nfs_commit_release, |
1423 | }; | 1436 | }; |
1437 | #else | ||
1438 | static inline int nfs_commit_list(struct inode *inode, struct list_head *head, int how) | ||
1439 | { | ||
1440 | return 0; | ||
1441 | } | ||
1424 | #endif | 1442 | #endif |
1425 | 1443 | ||
1426 | static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, | 1444 | static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, |
@@ -1460,28 +1478,38 @@ int nfs_commit_inode(struct inode *inode, int how) | |||
1460 | } | 1478 | } |
1461 | #endif | 1479 | #endif |
1462 | 1480 | ||
1463 | int nfs_sync_inode(struct inode *inode, unsigned long idx_start, | 1481 | int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start, |
1464 | unsigned int npages, int how) | 1482 | unsigned int npages, int how) |
1465 | { | 1483 | { |
1484 | struct nfs_inode *nfsi = NFS_I(inode); | ||
1485 | LIST_HEAD(head); | ||
1466 | int nocommit = how & FLUSH_NOCOMMIT; | 1486 | int nocommit = how & FLUSH_NOCOMMIT; |
1467 | int wait = how & FLUSH_WAIT; | 1487 | int pages, ret; |
1468 | int error; | ||
1469 | |||
1470 | how &= ~(FLUSH_WAIT|FLUSH_NOCOMMIT); | ||
1471 | 1488 | ||
1489 | how &= ~FLUSH_NOCOMMIT; | ||
1490 | spin_lock(&nfsi->req_lock); | ||
1472 | do { | 1491 | do { |
1473 | if (wait) { | 1492 | ret = nfs_wait_on_requests_locked(inode, idx_start, npages); |
1474 | error = nfs_wait_on_requests(inode, idx_start, npages); | 1493 | if (ret != 0) |
1475 | if (error != 0) | ||
1476 | continue; | ||
1477 | } | ||
1478 | error = nfs_flush_inode(inode, idx_start, npages, how); | ||
1479 | if (error != 0) | ||
1480 | continue; | 1494 | continue; |
1481 | if (!nocommit) | 1495 | pages = nfs_scan_dirty(inode, &head, idx_start, npages); |
1482 | error = nfs_commit_inode(inode, how); | 1496 | if (pages != 0) { |
1483 | } while (error > 0); | 1497 | spin_unlock(&nfsi->req_lock); |
1484 | return error; | 1498 | ret = nfs_flush_list(inode, &head, pages, how); |
1499 | spin_lock(&nfsi->req_lock); | ||
1500 | continue; | ||
1501 | } | ||
1502 | if (nocommit) | ||
1503 | break; | ||
1504 | pages = nfs_scan_commit(inode, &head, 0, 0); | ||
1505 | if (pages == 0) | ||
1506 | break; | ||
1507 | spin_unlock(&nfsi->req_lock); | ||
1508 | ret = nfs_commit_list(inode, &head, how); | ||
1509 | spin_lock(&nfsi->req_lock); | ||
1510 | } while (ret >= 0); | ||
1511 | spin_unlock(&nfsi->req_lock); | ||
1512 | return ret; | ||
1485 | } | 1513 | } |
1486 | 1514 | ||
1487 | int nfs_init_writepagecache(void) | 1515 | int nfs_init_writepagecache(void) |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 55de0770df4a..cbebd7d1b9e8 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -56,9 +56,7 @@ | |||
56 | * When flushing a cluster of dirty pages, there can be different | 56 | * When flushing a cluster of dirty pages, there can be different |
57 | * strategies: | 57 | * strategies: |
58 | */ | 58 | */ |
59 | #define FLUSH_AGING 0 /* only flush old buffers */ | ||
60 | #define FLUSH_SYNC 1 /* file being synced, or contention */ | 59 | #define FLUSH_SYNC 1 /* file being synced, or contention */ |
61 | #define FLUSH_WAIT 2 /* wait for completion */ | ||
62 | #define FLUSH_STABLE 4 /* commit to stable storage */ | 60 | #define FLUSH_STABLE 4 /* commit to stable storage */ |
63 | #define FLUSH_LOWPRI 8 /* low priority background flush */ | 61 | #define FLUSH_LOWPRI 8 /* low priority background flush */ |
64 | #define FLUSH_HIGHPRI 16 /* high priority memory reclaim flush */ | 62 | #define FLUSH_HIGHPRI 16 /* high priority memory reclaim flush */ |
@@ -419,7 +417,7 @@ void nfs_commit_free(struct nfs_write_data *p); | |||
419 | * Try to write back everything synchronously (but check the | 417 | * Try to write back everything synchronously (but check the |
420 | * return value!) | 418 | * return value!) |
421 | */ | 419 | */ |
422 | extern int nfs_sync_inode(struct inode *, unsigned long, unsigned int, int); | 420 | extern int nfs_sync_inode_wait(struct inode *, unsigned long, unsigned int, int); |
423 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 421 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
424 | extern int nfs_commit_inode(struct inode *, int); | 422 | extern int nfs_commit_inode(struct inode *, int); |
425 | extern void nfs_commit_release(void *wdata); | 423 | extern void nfs_commit_release(void *wdata); |
@@ -440,7 +438,7 @@ nfs_have_writebacks(struct inode *inode) | |||
440 | static inline int | 438 | static inline int |
441 | nfs_wb_all(struct inode *inode) | 439 | nfs_wb_all(struct inode *inode) |
442 | { | 440 | { |
443 | int error = nfs_sync_inode(inode, 0, 0, FLUSH_WAIT); | 441 | int error = nfs_sync_inode_wait(inode, 0, 0, 0); |
444 | return (error < 0) ? error : 0; | 442 | return (error < 0) ? error : 0; |
445 | } | 443 | } |
446 | 444 | ||
@@ -449,8 +447,8 @@ nfs_wb_all(struct inode *inode) | |||
449 | */ | 447 | */ |
450 | static inline int nfs_wb_page_priority(struct inode *inode, struct page* page, int how) | 448 | static inline int nfs_wb_page_priority(struct inode *inode, struct page* page, int how) |
451 | { | 449 | { |
452 | int error = nfs_sync_inode(inode, page->index, 1, | 450 | int error = nfs_sync_inode_wait(inode, page->index, 1, |
453 | how | FLUSH_WAIT | FLUSH_STABLE); | 451 | how | FLUSH_STABLE); |
454 | return (error < 0) ? error : 0; | 452 | return (error < 0) ? error : 0; |
455 | } | 453 | } |
456 | 454 | ||