diff options
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 38 |
1 files changed, 16 insertions, 22 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 92d9cadc6102..85ca49549b39 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -57,6 +57,7 @@ static const struct rpc_call_ops nfs_commit_ops; | |||
57 | static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops; | 57 | static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops; |
58 | static const struct nfs_commit_completion_ops nfs_commit_completion_ops; | 58 | static const struct nfs_commit_completion_ops nfs_commit_completion_ops; |
59 | static const struct nfs_rw_ops nfs_rw_write_ops; | 59 | static const struct nfs_rw_ops nfs_rw_write_ops; |
60 | static void nfs_inode_remove_request(struct nfs_page *req); | ||
60 | static void nfs_clear_request_commit(struct nfs_page *req); | 61 | static void nfs_clear_request_commit(struct nfs_page *req); |
61 | static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo, | 62 | static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo, |
62 | struct inode *inode); | 63 | struct inode *inode); |
@@ -591,23 +592,13 @@ release_request: | |||
591 | 592 | ||
592 | static void nfs_write_error(struct nfs_page *req, int error) | 593 | static void nfs_write_error(struct nfs_page *req, int error) |
593 | { | 594 | { |
595 | nfs_set_pageerror(page_file_mapping(req->wb_page)); | ||
594 | nfs_mapping_set_error(req->wb_page, error); | 596 | nfs_mapping_set_error(req->wb_page, error); |
597 | nfs_inode_remove_request(req); | ||
595 | nfs_end_page_writeback(req); | 598 | nfs_end_page_writeback(req); |
596 | nfs_release_request(req); | 599 | nfs_release_request(req); |
597 | } | 600 | } |
598 | 601 | ||
599 | static bool | ||
600 | nfs_error_is_fatal_on_server(int err) | ||
601 | { | ||
602 | switch (err) { | ||
603 | case 0: | ||
604 | case -ERESTARTSYS: | ||
605 | case -EINTR: | ||
606 | return false; | ||
607 | } | ||
608 | return nfs_error_is_fatal(err); | ||
609 | } | ||
610 | |||
611 | /* | 602 | /* |
612 | * Find an associated nfs write request, and prepare to flush it out | 603 | * Find an associated nfs write request, and prepare to flush it out |
613 | * May return an error if the user signalled nfs_wait_on_request(). | 604 | * May return an error if the user signalled nfs_wait_on_request(). |
@@ -615,7 +606,6 @@ nfs_error_is_fatal_on_server(int err) | |||
615 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | 606 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, |
616 | struct page *page) | 607 | struct page *page) |
617 | { | 608 | { |
618 | struct address_space *mapping; | ||
619 | struct nfs_page *req; | 609 | struct nfs_page *req; |
620 | int ret = 0; | 610 | int ret = 0; |
621 | 611 | ||
@@ -630,12 +620,11 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
630 | WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags)); | 620 | WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags)); |
631 | 621 | ||
632 | /* If there is a fatal error that covers this write, just exit */ | 622 | /* If there is a fatal error that covers this write, just exit */ |
633 | ret = 0; | 623 | ret = pgio->pg_error; |
634 | mapping = page_file_mapping(page); | 624 | if (nfs_error_is_fatal_on_server(ret)) |
635 | if (test_bit(AS_ENOSPC, &mapping->flags) || | ||
636 | test_bit(AS_EIO, &mapping->flags)) | ||
637 | goto out_launder; | 625 | goto out_launder; |
638 | 626 | ||
627 | ret = 0; | ||
639 | if (!nfs_pageio_add_request(pgio, req)) { | 628 | if (!nfs_pageio_add_request(pgio, req)) { |
640 | ret = pgio->pg_error; | 629 | ret = pgio->pg_error; |
641 | /* | 630 | /* |
@@ -647,6 +636,7 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
647 | } else | 636 | } else |
648 | ret = -EAGAIN; | 637 | ret = -EAGAIN; |
649 | nfs_redirty_request(req); | 638 | nfs_redirty_request(req); |
639 | pgio->pg_error = 0; | ||
650 | } else | 640 | } else |
651 | nfs_add_stats(page_file_mapping(page)->host, | 641 | nfs_add_stats(page_file_mapping(page)->host, |
652 | NFSIOS_WRITEPAGES, 1); | 642 | NFSIOS_WRITEPAGES, 1); |
@@ -666,7 +656,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, | |||
666 | ret = nfs_page_async_flush(pgio, page); | 656 | ret = nfs_page_async_flush(pgio, page); |
667 | if (ret == -EAGAIN) { | 657 | if (ret == -EAGAIN) { |
668 | redirty_page_for_writepage(wbc, page); | 658 | redirty_page_for_writepage(wbc, page); |
669 | ret = 0; | 659 | ret = AOP_WRITEPAGE_ACTIVATE; |
670 | } | 660 | } |
671 | return ret; | 661 | return ret; |
672 | } | 662 | } |
@@ -685,10 +675,11 @@ static int nfs_writepage_locked(struct page *page, | |||
685 | nfs_pageio_init_write(&pgio, inode, 0, | 675 | nfs_pageio_init_write(&pgio, inode, 0, |
686 | false, &nfs_async_write_completion_ops); | 676 | false, &nfs_async_write_completion_ops); |
687 | err = nfs_do_writepage(page, wbc, &pgio); | 677 | err = nfs_do_writepage(page, wbc, &pgio); |
678 | pgio.pg_error = 0; | ||
688 | nfs_pageio_complete(&pgio); | 679 | nfs_pageio_complete(&pgio); |
689 | if (err < 0) | 680 | if (err < 0) |
690 | return err; | 681 | return err; |
691 | if (pgio.pg_error < 0) | 682 | if (nfs_error_is_fatal(pgio.pg_error)) |
692 | return pgio.pg_error; | 683 | return pgio.pg_error; |
693 | return 0; | 684 | return 0; |
694 | } | 685 | } |
@@ -698,7 +689,8 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) | |||
698 | int ret; | 689 | int ret; |
699 | 690 | ||
700 | ret = nfs_writepage_locked(page, wbc); | 691 | ret = nfs_writepage_locked(page, wbc); |
701 | unlock_page(page); | 692 | if (ret != AOP_WRITEPAGE_ACTIVATE) |
693 | unlock_page(page); | ||
702 | return ret; | 694 | return ret; |
703 | } | 695 | } |
704 | 696 | ||
@@ -707,7 +699,8 @@ static int nfs_writepages_callback(struct page *page, struct writeback_control * | |||
707 | int ret; | 699 | int ret; |
708 | 700 | ||
709 | ret = nfs_do_writepage(page, wbc, data); | 701 | ret = nfs_do_writepage(page, wbc, data); |
710 | unlock_page(page); | 702 | if (ret != AOP_WRITEPAGE_ACTIVATE) |
703 | unlock_page(page); | ||
711 | return ret; | 704 | return ret; |
712 | } | 705 | } |
713 | 706 | ||
@@ -733,13 +726,14 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
733 | &nfs_async_write_completion_ops); | 726 | &nfs_async_write_completion_ops); |
734 | pgio.pg_io_completion = ioc; | 727 | pgio.pg_io_completion = ioc; |
735 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); | 728 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); |
729 | pgio.pg_error = 0; | ||
736 | nfs_pageio_complete(&pgio); | 730 | nfs_pageio_complete(&pgio); |
737 | nfs_io_completion_put(ioc); | 731 | nfs_io_completion_put(ioc); |
738 | 732 | ||
739 | if (err < 0) | 733 | if (err < 0) |
740 | goto out_err; | 734 | goto out_err; |
741 | err = pgio.pg_error; | 735 | err = pgio.pg_error; |
742 | if (err < 0) | 736 | if (nfs_error_is_fatal(err)) |
743 | goto out_err; | 737 | goto out_err; |
744 | return 0; | 738 | return 0; |
745 | out_err: | 739 | out_err: |