diff options
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 53 |
1 files changed, 20 insertions, 33 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index b03ec1ba4d75..b6749967eead 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -835,7 +835,7 @@ static void nfs_execute_write(struct nfs_write_data *data) | |||
835 | * Generate multiple small requests to write out a single | 835 | * Generate multiple small requests to write out a single |
836 | * contiguous dirty area on one page. | 836 | * contiguous dirty area on one page. |
837 | */ | 837 | */ |
838 | static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how) | 838 | static int nfs_flush_multi(struct inode *inode, struct list_head *head, size_t count, int how) |
839 | { | 839 | { |
840 | struct nfs_page *req = nfs_list_entry(head->next); | 840 | struct nfs_page *req = nfs_list_entry(head->next); |
841 | struct page *page = req->wb_page; | 841 | struct page *page = req->wb_page; |
@@ -847,7 +847,7 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how) | |||
847 | 847 | ||
848 | nfs_list_remove_request(req); | 848 | nfs_list_remove_request(req); |
849 | 849 | ||
850 | nbytes = req->wb_bytes; | 850 | nbytes = count; |
851 | do { | 851 | do { |
852 | size_t len = min(nbytes, wsize); | 852 | size_t len = min(nbytes, wsize); |
853 | 853 | ||
@@ -862,23 +862,19 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how) | |||
862 | 862 | ||
863 | ClearPageError(page); | 863 | ClearPageError(page); |
864 | offset = 0; | 864 | offset = 0; |
865 | nbytes = req->wb_bytes; | 865 | nbytes = count; |
866 | do { | 866 | do { |
867 | data = list_entry(list.next, struct nfs_write_data, pages); | 867 | data = list_entry(list.next, struct nfs_write_data, pages); |
868 | list_del_init(&data->pages); | 868 | list_del_init(&data->pages); |
869 | 869 | ||
870 | data->pagevec[0] = page; | 870 | data->pagevec[0] = page; |
871 | 871 | ||
872 | if (nbytes > wsize) { | 872 | if (nbytes < wsize) |
873 | nfs_write_rpcsetup(req, data, &nfs_write_partial_ops, | 873 | wsize = nbytes; |
874 | wsize, offset, how); | 874 | nfs_write_rpcsetup(req, data, &nfs_write_partial_ops, |
875 | offset += wsize; | 875 | wsize, offset, how); |
876 | nbytes -= wsize; | 876 | offset += wsize; |
877 | } else { | 877 | nbytes -= wsize; |
878 | nfs_write_rpcsetup(req, data, &nfs_write_partial_ops, | ||
879 | nbytes, offset, how); | ||
880 | nbytes = 0; | ||
881 | } | ||
882 | nfs_execute_write(data); | 878 | nfs_execute_write(data); |
883 | } while (nbytes != 0); | 879 | } while (nbytes != 0); |
884 | 880 | ||
@@ -904,26 +900,23 @@ out_bad: | |||
904 | * This is the case if nfs_updatepage detects a conflicting request | 900 | * This is the case if nfs_updatepage detects a conflicting request |
905 | * that has been written but not committed. | 901 | * that has been written but not committed. |
906 | */ | 902 | */ |
907 | static int nfs_flush_one(struct inode *inode, struct list_head *head, int how) | 903 | static int nfs_flush_one(struct inode *inode, struct list_head *head, size_t count, int how) |
908 | { | 904 | { |
909 | struct nfs_page *req; | 905 | struct nfs_page *req; |
910 | struct page **pages; | 906 | struct page **pages; |
911 | struct nfs_write_data *data; | 907 | struct nfs_write_data *data; |
912 | unsigned int count; | ||
913 | 908 | ||
914 | data = nfs_writedata_alloc(NFS_SERVER(inode)->wsize); | 909 | data = nfs_writedata_alloc(count); |
915 | if (!data) | 910 | if (!data) |
916 | goto out_bad; | 911 | goto out_bad; |
917 | 912 | ||
918 | pages = data->pagevec; | 913 | pages = data->pagevec; |
919 | count = 0; | ||
920 | while (!list_empty(head)) { | 914 | while (!list_empty(head)) { |
921 | req = nfs_list_entry(head->next); | 915 | req = nfs_list_entry(head->next); |
922 | nfs_list_remove_request(req); | 916 | nfs_list_remove_request(req); |
923 | nfs_list_add_request(req, &data->pages); | 917 | nfs_list_add_request(req, &data->pages); |
924 | ClearPageError(req->wb_page); | 918 | ClearPageError(req->wb_page); |
925 | *pages++ = req->wb_page; | 919 | *pages++ = req->wb_page; |
926 | count += req->wb_bytes; | ||
927 | } | 920 | } |
928 | req = nfs_list_entry(data->pages.next); | 921 | req = nfs_list_entry(data->pages.next); |
929 | 922 | ||
@@ -946,28 +939,22 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, int how) | |||
946 | static int nfs_flush_list(struct inode *inode, struct list_head *head, int npages, int how) | 939 | static int nfs_flush_list(struct inode *inode, struct list_head *head, int npages, int how) |
947 | { | 940 | { |
948 | struct nfs_pageio_descriptor desc; | 941 | struct nfs_pageio_descriptor desc; |
949 | int (*flush_one)(struct inode *, struct list_head *, int); | ||
950 | int wpages = NFS_SERVER(inode)->wpages; | 942 | int wpages = NFS_SERVER(inode)->wpages; |
951 | int wsize = NFS_SERVER(inode)->wsize; | 943 | int wsize = NFS_SERVER(inode)->wsize; |
952 | int error; | ||
953 | 944 | ||
954 | flush_one = nfs_flush_one; | ||
955 | if (wsize < PAGE_CACHE_SIZE) | ||
956 | flush_one = nfs_flush_multi; | ||
957 | /* For single writes, FLUSH_STABLE is more efficient */ | 945 | /* For single writes, FLUSH_STABLE is more efficient */ |
958 | if (npages <= wpages && npages == NFS_I(inode)->npages | 946 | if (npages <= wpages && npages == NFS_I(inode)->npages |
959 | && nfs_list_entry(head->next)->wb_bytes <= wsize) | 947 | && nfs_list_entry(head->next)->wb_bytes <= wsize) |
960 | how |= FLUSH_STABLE; | 948 | how |= FLUSH_STABLE; |
961 | 949 | ||
962 | do { | 950 | if (wsize < PAGE_CACHE_SIZE) |
963 | nfs_pageio_init(&desc, wsize); | 951 | nfs_pageio_init(&desc, inode, nfs_flush_multi, wsize, how); |
964 | nfs_pageio_add_list(&desc, head); | 952 | else |
965 | error = flush_one(inode, &desc.pg_list, how); | 953 | nfs_pageio_init(&desc, inode, nfs_flush_one, wsize, how); |
966 | if (error < 0) | 954 | nfs_pageio_add_list(&desc, head); |
967 | goto out_err; | 955 | nfs_pageio_complete(&desc); |
968 | } while (!list_empty(head)); | 956 | if (desc.pg_error == 0) |
969 | return 0; | 957 | return 0; |
970 | out_err: | ||
971 | while (!list_empty(head)) { | 958 | while (!list_empty(head)) { |
972 | struct nfs_page *req = nfs_list_entry(head->next); | 959 | struct nfs_page *req = nfs_list_entry(head->next); |
973 | nfs_list_remove_request(req); | 960 | nfs_list_remove_request(req); |
@@ -975,7 +962,7 @@ out_err: | |||
975 | nfs_end_page_writeback(req->wb_page); | 962 | nfs_end_page_writeback(req->wb_page); |
976 | nfs_clear_page_writeback(req); | 963 | nfs_clear_page_writeback(req); |
977 | } | 964 | } |
978 | return error; | 965 | return desc.pg_error; |
979 | } | 966 | } |
980 | 967 | ||
981 | /* | 968 | /* |