aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-12 13:42:02 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-15 09:12:17 -0400
commit275acaafd45fbc8ecc3beabd6367e60b3049606a (patch)
tree7da9d9a606c274742d41860cb429c7d25a917f1d /fs/nfs/write.c
parent3b6091846d5b6113d695c79caec7cc96b62d469b (diff)
NFS: Clean up: split out the RPC transmission from nfs_pagein_multi/one
...and do the same for nfs_flush_multi/one. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c93
1 files changed, 52 insertions, 41 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index d9dd744588d4..bd4b34e5870b 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -903,6 +903,27 @@ static int nfs_do_write(struct nfs_write_data *data,
903 return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how); 903 return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how);
904} 904}
905 905
906static int nfs_do_multiple_writes(struct list_head *head,
907 const struct rpc_call_ops *call_ops,
908 struct pnfs_layout_segment *lseg,
909 int how)
910{
911 struct nfs_write_data *data;
912 int ret = 0;
913
914 while (!list_empty(head)) {
915 int ret2;
916
917 data = list_entry(head->next, struct nfs_write_data, list);
918 list_del_init(&data->list);
919
920 ret2 = nfs_do_write(data, call_ops, lseg, how);
921 if (ret == 0)
922 ret = ret2;
923 }
924 return ret;
925}
926
906/* If a nfs_flush_* function fails, it should remove reqs from @head and 927/* If a nfs_flush_* function fails, it should remove reqs from @head and
907 * call this on each, which will prepare them to be retried on next 928 * call this on each, which will prepare them to be retried on next
908 * writeback using standard nfs. 929 * writeback using standard nfs.
@@ -920,7 +941,7 @@ static void nfs_redirty_request(struct nfs_page *req)
920 * Generate multiple small requests to write out a single 941 * Generate multiple small requests to write out a single
921 * contiguous dirty area on one page. 942 * contiguous dirty area on one page.
922 */ 943 */
923static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) 944static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head *res)
924{ 945{
925 struct nfs_page *req = nfs_list_entry(desc->pg_list.next); 946 struct nfs_page *req = nfs_list_entry(desc->pg_list.next);
926 struct page *page = req->wb_page; 947 struct page *page = req->wb_page;
@@ -929,8 +950,6 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
929 unsigned int offset; 950 unsigned int offset;
930 int requests = 0; 951 int requests = 0;
931 int ret = 0; 952 int ret = 0;
932 struct pnfs_layout_segment *lseg = desc->pg_lseg;
933 LIST_HEAD(list);
934 953
935 nfs_list_remove_request(req); 954 nfs_list_remove_request(req);
936 955
@@ -940,6 +959,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
940 desc->pg_ioflags &= ~FLUSH_COND_STABLE; 959 desc->pg_ioflags &= ~FLUSH_COND_STABLE;
941 960
942 961
962 offset = 0;
943 nbytes = desc->pg_count; 963 nbytes = desc->pg_count;
944 do { 964 do {
945 size_t len = min(nbytes, wsize); 965 size_t len = min(nbytes, wsize);
@@ -947,47 +967,23 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
947 data = nfs_writedata_alloc(1); 967 data = nfs_writedata_alloc(1);
948 if (!data) 968 if (!data)
949 goto out_bad; 969 goto out_bad;
950 list_add(&data->list, &list); 970 data->pagevec[0] = page;
971 nfs_write_rpcsetup(req, data, wsize, offset, desc->pg_ioflags);
972 list_add(&data->list, res);
951 requests++; 973 requests++;
952 nbytes -= len; 974 nbytes -= len;
975 offset += len;
953 } while (nbytes != 0); 976 } while (nbytes != 0);
954 atomic_set(&req->wb_complete, requests); 977 atomic_set(&req->wb_complete, requests);
955
956 ClearPageError(page);
957 offset = 0;
958 nbytes = desc->pg_count;
959 do {
960 int ret2;
961
962 data = list_entry(list.next, struct nfs_write_data, list);
963 list_del_init(&data->list);
964
965 data->pagevec[0] = page;
966
967 if (nbytes < wsize)
968 wsize = nbytes;
969 nfs_write_rpcsetup(req, data, wsize, offset, desc->pg_ioflags);
970 ret2 = nfs_do_write(data, &nfs_write_partial_ops, lseg,
971 desc->pg_ioflags);
972 if (ret == 0)
973 ret = ret2;
974 offset += wsize;
975 nbytes -= wsize;
976 } while (nbytes != 0);
977
978 put_lseg(lseg);
979 desc->pg_lseg = NULL;
980 return ret; 978 return ret;
981 979
982out_bad: 980out_bad:
983 while (!list_empty(&list)) { 981 while (!list_empty(res)) {
984 data = list_entry(list.next, struct nfs_write_data, list); 982 data = list_entry(res->next, struct nfs_write_data, list);
985 list_del(&data->list); 983 list_del(&data->list);
986 nfs_writedata_free(data); 984 nfs_writedata_free(data);
987 } 985 }
988 nfs_redirty_request(req); 986 nfs_redirty_request(req);
989 put_lseg(lseg);
990 desc->pg_lseg = NULL;
991 return -ENOMEM; 987 return -ENOMEM;
992} 988}
993 989
@@ -999,13 +995,12 @@ out_bad:
999 * This is the case if nfs_updatepage detects a conflicting request 995 * This is the case if nfs_updatepage detects a conflicting request
1000 * that has been written but not committed. 996 * that has been written but not committed.
1001 */ 997 */
1002static int nfs_flush_one(struct nfs_pageio_descriptor *desc) 998static int nfs_flush_one(struct nfs_pageio_descriptor *desc, struct list_head *res)
1003{ 999{
1004 struct nfs_page *req; 1000 struct nfs_page *req;
1005 struct page **pages; 1001 struct page **pages;
1006 struct nfs_write_data *data; 1002 struct nfs_write_data *data;
1007 struct list_head *head = &desc->pg_list; 1003 struct list_head *head = &desc->pg_list;
1008 struct pnfs_layout_segment *lseg = desc->pg_lseg;
1009 int ret = 0; 1004 int ret = 0;
1010 1005
1011 data = nfs_writedata_alloc(nfs_page_array_len(desc->pg_base, 1006 data = nfs_writedata_alloc(nfs_page_array_len(desc->pg_base,
@@ -1035,18 +1030,34 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc)
1035 1030
1036 /* Set up the argument struct */ 1031 /* Set up the argument struct */
1037 nfs_write_rpcsetup(req, data, desc->pg_count, 0, desc->pg_ioflags); 1032 nfs_write_rpcsetup(req, data, desc->pg_count, 0, desc->pg_ioflags);
1038 ret = nfs_do_write(data, &nfs_write_full_ops, lseg, desc->pg_ioflags); 1033 list_add(&data->list, res);
1039out: 1034out:
1040 put_lseg(lseg); /* Cleans any gotten in ->pg_test */
1041 desc->pg_lseg = NULL;
1042 return ret; 1035 return ret;
1043} 1036}
1044 1037
1045int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) 1038int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1046{ 1039{
1047 if (desc->pg_bsize < PAGE_CACHE_SIZE) 1040 LIST_HEAD(head);
1048 return nfs_flush_multi(desc); 1041 int ret;
1049 return nfs_flush_one(desc); 1042
1043 if (desc->pg_bsize < PAGE_CACHE_SIZE) {
1044 ret = nfs_flush_multi(desc, &head);
1045 if (ret == 0)
1046 ret = nfs_do_multiple_writes(&head,
1047 &nfs_write_partial_ops,
1048 desc->pg_lseg,
1049 desc->pg_ioflags);
1050 } else {
1051 ret = nfs_flush_one(desc, &head);
1052 if (ret == 0)
1053 ret = nfs_do_multiple_writes(&head,
1054 &nfs_write_full_ops,
1055 desc->pg_lseg,
1056 desc->pg_ioflags);
1057 }
1058 put_lseg(desc->pg_lseg);
1059 desc->pg_lseg = NULL;
1060 return ret;
1050} 1061}
1051EXPORT_SYMBOL_GPL(nfs_generic_pg_writepages); 1062EXPORT_SYMBOL_GPL(nfs_generic_pg_writepages);
1052 1063