diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-12 13:42:02 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-15 09:12:17 -0400 |
commit | 275acaafd45fbc8ecc3beabd6367e60b3049606a (patch) | |
tree | 7da9d9a606c274742d41860cb429c7d25a917f1d /fs/nfs/write.c | |
parent | 3b6091846d5b6113d695c79caec7cc96b62d469b (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.c | 93 |
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 | ||
906 | static 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 | */ |
923 | static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) | 944 | static 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 | ||
982 | out_bad: | 980 | out_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 | */ |
1002 | static int nfs_flush_one(struct nfs_pageio_descriptor *desc) | 998 | static 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); |
1039 | out: | 1034 | out: |
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 | ||
1045 | int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | 1038 | int 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 | } |
1051 | EXPORT_SYMBOL_GPL(nfs_generic_pg_writepages); | 1062 | EXPORT_SYMBOL_GPL(nfs_generic_pg_writepages); |
1052 | 1063 | ||