diff options
Diffstat (limited to 'fs/nfs/write.c')
| -rw-r--r-- | fs/nfs/write.c | 72 |
1 files changed, 50 insertions, 22 deletions
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) |
