aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c53
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 */
838static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how) 838static 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 */
907static int nfs_flush_one(struct inode *inode, struct list_head *head, int how) 903static 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)
946static int nfs_flush_list(struct inode *inode, struct list_head *head, int npages, int how) 939static 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;
970out_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/*