diff options
-rw-r--r-- | fs/nfs/internal.h | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 2 | ||||
-rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 2 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 57 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 10 | ||||
-rw-r--r-- | fs/nfs/write.c | 39 | ||||
-rw-r--r-- | include/linux/nfs_page.h | 3 |
7 files changed, 80 insertions, 37 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index d74d7dea9173..09e20de31901 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -305,8 +305,12 @@ extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); | |||
305 | extern void nfs_readdata_release(struct nfs_read_data *rdata); | 305 | extern void nfs_readdata_release(struct nfs_read_data *rdata); |
306 | 306 | ||
307 | /* write.c */ | 307 | /* write.c */ |
308 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | ||
309 | struct list_head *head); | ||
308 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | 310 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, |
309 | struct inode *inode, int ioflags); | 311 | struct inode *inode, int ioflags); |
312 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); | ||
313 | extern void nfs_writedata_release(struct nfs_write_data *wdata); | ||
310 | extern void nfs_commit_free(struct nfs_write_data *p); | 314 | extern void nfs_commit_free(struct nfs_write_data *p); |
311 | extern int nfs_initiate_write(struct nfs_write_data *data, | 315 | extern int nfs_initiate_write(struct nfs_write_data *data, |
312 | struct rpc_clnt *clnt, | 316 | struct rpc_clnt *clnt, |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index fc556d6b90f1..fbc5b42d1970 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -741,7 +741,7 @@ static const struct nfs_pageio_ops filelayout_pg_read_ops = { | |||
741 | static const struct nfs_pageio_ops filelayout_pg_write_ops = { | 741 | static const struct nfs_pageio_ops filelayout_pg_write_ops = { |
742 | .pg_init = filelayout_pg_init_write, | 742 | .pg_init = filelayout_pg_init_write, |
743 | .pg_test = filelayout_pg_test, | 743 | .pg_test = filelayout_pg_test, |
744 | .pg_doio = nfs_generic_pg_writepages, | 744 | .pg_doio = pnfs_generic_pg_writepages, |
745 | }; | 745 | }; |
746 | 746 | ||
747 | static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg) | 747 | static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg) |
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index add62894f364..7d49bb160b46 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -1013,7 +1013,7 @@ static const struct nfs_pageio_ops objio_pg_read_ops = { | |||
1013 | static const struct nfs_pageio_ops objio_pg_write_ops = { | 1013 | static const struct nfs_pageio_ops objio_pg_write_ops = { |
1014 | .pg_init = pnfs_generic_pg_init_write, | 1014 | .pg_init = pnfs_generic_pg_init_write, |
1015 | .pg_test = objio_pg_test, | 1015 | .pg_test = objio_pg_test, |
1016 | .pg_doio = nfs_generic_pg_writepages, | 1016 | .pg_doio = pnfs_generic_pg_writepages, |
1017 | }; | 1017 | }; |
1018 | 1018 | ||
1019 | static struct pnfs_layoutdriver_type objlayout_type = { | 1019 | static struct pnfs_layoutdriver_type objlayout_type = { |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 9eca5a8cdbdd..93c73299588d 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1170,15 +1170,30 @@ pnfs_ld_write_done(struct nfs_write_data *data) | |||
1170 | } | 1170 | } |
1171 | EXPORT_SYMBOL_GPL(pnfs_ld_write_done); | 1171 | EXPORT_SYMBOL_GPL(pnfs_ld_write_done); |
1172 | 1172 | ||
1173 | enum pnfs_try_status | 1173 | static void |
1174 | pnfs_write_through_mds(struct nfs_pageio_descriptor *desc, | ||
1175 | struct nfs_write_data *data) | ||
1176 | { | ||
1177 | list_splice_tail_init(&data->pages, &desc->pg_list); | ||
1178 | if (data->req && list_empty(&data->req->wb_list)) | ||
1179 | nfs_list_add_request(data->req, &desc->pg_list); | ||
1180 | nfs_pageio_reset_write_mds(desc); | ||
1181 | desc->pg_recoalesce = 1; | ||
1182 | nfs_writedata_release(data); | ||
1183 | } | ||
1184 | |||
1185 | static enum pnfs_try_status | ||
1174 | pnfs_try_to_write_data(struct nfs_write_data *wdata, | 1186 | pnfs_try_to_write_data(struct nfs_write_data *wdata, |
1175 | const struct rpc_call_ops *call_ops, int how) | 1187 | const struct rpc_call_ops *call_ops, |
1188 | struct pnfs_layout_segment *lseg, | ||
1189 | int how) | ||
1176 | { | 1190 | { |
1177 | struct inode *inode = wdata->inode; | 1191 | struct inode *inode = wdata->inode; |
1178 | enum pnfs_try_status trypnfs; | 1192 | enum pnfs_try_status trypnfs; |
1179 | struct nfs_server *nfss = NFS_SERVER(inode); | 1193 | struct nfs_server *nfss = NFS_SERVER(inode); |
1180 | 1194 | ||
1181 | wdata->mds_ops = call_ops; | 1195 | wdata->mds_ops = call_ops; |
1196 | wdata->lseg = get_lseg(lseg); | ||
1182 | 1197 | ||
1183 | dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__, | 1198 | dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__, |
1184 | inode->i_ino, wdata->args.count, wdata->args.offset, how); | 1199 | inode->i_ino, wdata->args.count, wdata->args.offset, how); |
@@ -1194,6 +1209,44 @@ pnfs_try_to_write_data(struct nfs_write_data *wdata, | |||
1194 | return trypnfs; | 1209 | return trypnfs; |
1195 | } | 1210 | } |
1196 | 1211 | ||
1212 | static void | ||
1213 | pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *head, int how) | ||
1214 | { | ||
1215 | struct nfs_write_data *data; | ||
1216 | const struct rpc_call_ops *call_ops = desc->pg_rpc_callops; | ||
1217 | struct pnfs_layout_segment *lseg = desc->pg_lseg; | ||
1218 | |||
1219 | desc->pg_lseg = NULL; | ||
1220 | while (!list_empty(head)) { | ||
1221 | enum pnfs_try_status trypnfs; | ||
1222 | |||
1223 | data = list_entry(head->next, struct nfs_write_data, list); | ||
1224 | list_del_init(&data->list); | ||
1225 | |||
1226 | trypnfs = pnfs_try_to_write_data(data, call_ops, lseg, how); | ||
1227 | if (trypnfs == PNFS_NOT_ATTEMPTED) | ||
1228 | pnfs_write_through_mds(desc, data); | ||
1229 | } | ||
1230 | put_lseg(lseg); | ||
1231 | } | ||
1232 | |||
1233 | int | ||
1234 | pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | ||
1235 | { | ||
1236 | LIST_HEAD(head); | ||
1237 | int ret; | ||
1238 | |||
1239 | ret = nfs_generic_flush(desc, &head); | ||
1240 | if (ret != 0) { | ||
1241 | put_lseg(desc->pg_lseg); | ||
1242 | desc->pg_lseg = NULL; | ||
1243 | return ret; | ||
1244 | } | ||
1245 | pnfs_do_multiple_writes(desc, &head, desc->pg_ioflags); | ||
1246 | return 0; | ||
1247 | } | ||
1248 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); | ||
1249 | |||
1197 | /* | 1250 | /* |
1198 | * Called by non rpc-based layout drivers | 1251 | * Called by non rpc-based layout drivers |
1199 | */ | 1252 | */ |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index c40ffa52c1ab..078670dfbe04 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -155,11 +155,10 @@ bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int) | |||
155 | 155 | ||
156 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); | 156 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); |
157 | void unset_pnfs_layoutdriver(struct nfs_server *); | 157 | void unset_pnfs_layoutdriver(struct nfs_server *); |
158 | enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, | ||
159 | const struct rpc_call_ops *, int); | ||
160 | void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); | 158 | void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); |
161 | int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc); | 159 | int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc); |
162 | void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); | 160 | void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); |
161 | int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc); | ||
163 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); | 162 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); |
164 | int pnfs_layout_process(struct nfs4_layoutget *lgp); | 163 | int pnfs_layout_process(struct nfs4_layoutget *lgp); |
165 | void pnfs_free_lseg_list(struct list_head *tmp_list); | 164 | void pnfs_free_lseg_list(struct list_head *tmp_list); |
@@ -328,13 +327,6 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg) | |||
328 | { | 327 | { |
329 | } | 328 | } |
330 | 329 | ||
331 | static inline enum pnfs_try_status | ||
332 | pnfs_try_to_write_data(struct nfs_write_data *data, | ||
333 | const struct rpc_call_ops *call_ops, int how) | ||
334 | { | ||
335 | return PNFS_NOT_ATTEMPTED; | ||
336 | } | ||
337 | |||
338 | static inline int pnfs_return_layout(struct inode *ino) | 330 | static inline int pnfs_return_layout(struct inode *ino) |
339 | { | 331 | { |
340 | return 0; | 332 | return 0; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index c88a1ab42c39..cabe5f6611b9 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -97,7 +97,7 @@ void nfs_writedata_free(struct nfs_write_data *p) | |||
97 | mempool_free(p, nfs_wdata_mempool); | 97 | mempool_free(p, nfs_wdata_mempool); |
98 | } | 98 | } |
99 | 99 | ||
100 | static void nfs_writedata_release(struct nfs_write_data *wdata) | 100 | void nfs_writedata_release(struct nfs_write_data *wdata) |
101 | { | 101 | { |
102 | put_lseg(wdata->lseg); | 102 | put_lseg(wdata->lseg); |
103 | put_nfs_open_context(wdata->args.context); | 103 | put_nfs_open_context(wdata->args.context); |
@@ -887,25 +887,15 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
887 | 887 | ||
888 | static int nfs_do_write(struct nfs_write_data *data, | 888 | static int nfs_do_write(struct nfs_write_data *data, |
889 | const struct rpc_call_ops *call_ops, | 889 | const struct rpc_call_ops *call_ops, |
890 | struct pnfs_layout_segment *lseg, | ||
891 | int how) | 890 | int how) |
892 | { | 891 | { |
893 | struct inode *inode = data->args.context->path.dentry->d_inode; | 892 | struct inode *inode = data->args.context->path.dentry->d_inode; |
894 | 893 | ||
895 | if (lseg != NULL) { | ||
896 | data->lseg = get_lseg(lseg); | ||
897 | if (pnfs_try_to_write_data(data, call_ops, how) == PNFS_ATTEMPTED) | ||
898 | return 0; | ||
899 | put_lseg(data->lseg); | ||
900 | data->lseg = NULL; | ||
901 | } | ||
902 | |||
903 | return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how); | 894 | return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how); |
904 | } | 895 | } |
905 | 896 | ||
906 | static int nfs_do_multiple_writes(struct list_head *head, | 897 | static int nfs_do_multiple_writes(struct list_head *head, |
907 | const struct rpc_call_ops *call_ops, | 898 | const struct rpc_call_ops *call_ops, |
908 | struct pnfs_layout_segment *lseg, | ||
909 | int how) | 899 | int how) |
910 | { | 900 | { |
911 | struct nfs_write_data *data; | 901 | struct nfs_write_data *data; |
@@ -917,7 +907,7 @@ static int nfs_do_multiple_writes(struct list_head *head, | |||
917 | data = list_entry(head->next, struct nfs_write_data, list); | 907 | data = list_entry(head->next, struct nfs_write_data, list); |
918 | list_del_init(&data->list); | 908 | list_del_init(&data->list); |
919 | 909 | ||
920 | ret2 = nfs_do_write(data, call_ops, lseg, how); | 910 | ret2 = nfs_do_write(data, call_ops, how); |
921 | if (ret == 0) | 911 | if (ret == 0) |
922 | ret = ret2; | 912 | ret = ret2; |
923 | } | 913 | } |
@@ -1037,23 +1027,24 @@ out: | |||
1037 | return ret; | 1027 | return ret; |
1038 | } | 1028 | } |
1039 | 1029 | ||
1040 | int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | 1030 | int nfs_generic_flush(struct nfs_pageio_descriptor *desc, struct list_head *head) |
1031 | { | ||
1032 | if (desc->pg_bsize < PAGE_CACHE_SIZE) | ||
1033 | return nfs_flush_multi(desc, head); | ||
1034 | return nfs_flush_one(desc, head); | ||
1035 | } | ||
1036 | |||
1037 | static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | ||
1041 | { | 1038 | { |
1042 | LIST_HEAD(head); | 1039 | LIST_HEAD(head); |
1043 | int ret; | 1040 | int ret; |
1044 | 1041 | ||
1045 | if (desc->pg_bsize < PAGE_CACHE_SIZE) | 1042 | ret = nfs_generic_flush(desc, &head); |
1046 | ret = nfs_flush_multi(desc, &head); | ||
1047 | else | ||
1048 | ret = nfs_flush_one(desc, &head); | ||
1049 | if (ret == 0) | 1043 | if (ret == 0) |
1050 | ret = nfs_do_multiple_writes(&head, desc->pg_rpc_callops, | 1044 | ret = nfs_do_multiple_writes(&head, desc->pg_rpc_callops, |
1051 | desc->pg_lseg, desc->pg_ioflags); | 1045 | desc->pg_ioflags); |
1052 | put_lseg(desc->pg_lseg); | ||
1053 | desc->pg_lseg = NULL; | ||
1054 | return ret; | 1046 | return ret; |
1055 | } | 1047 | } |
1056 | EXPORT_SYMBOL_GPL(nfs_generic_pg_writepages); | ||
1057 | 1048 | ||
1058 | static const struct nfs_pageio_ops nfs_pageio_write_ops = { | 1049 | static const struct nfs_pageio_ops nfs_pageio_write_ops = { |
1059 | .pg_test = nfs_generic_pg_test, | 1050 | .pg_test = nfs_generic_pg_test, |
@@ -1068,6 +1059,12 @@ void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | |||
1068 | } | 1059 | } |
1069 | EXPORT_SYMBOL_GPL(nfs_pageio_init_write_mds); | 1060 | EXPORT_SYMBOL_GPL(nfs_pageio_init_write_mds); |
1070 | 1061 | ||
1062 | void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio) | ||
1063 | { | ||
1064 | pgio->pg_ops = &nfs_pageio_write_ops; | ||
1065 | pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->wsize; | ||
1066 | } | ||
1067 | |||
1071 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | 1068 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, |
1072 | struct inode *inode, int ioflags) | 1069 | struct inode *inode, int ioflags) |
1073 | { | 1070 | { |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 0a48f842f83c..e2791a27a901 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
@@ -108,9 +108,6 @@ extern void nfs_unlock_request(struct nfs_page *req); | |||
108 | extern int nfs_set_page_tag_locked(struct nfs_page *req); | 108 | extern int nfs_set_page_tag_locked(struct nfs_page *req); |
109 | extern void nfs_clear_page_tag_locked(struct nfs_page *req); | 109 | extern void nfs_clear_page_tag_locked(struct nfs_page *req); |
110 | 110 | ||
111 | extern int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc); | ||
112 | |||
113 | |||
114 | /* | 111 | /* |
115 | * Lock the page of an asynchronous request without getting a new reference | 112 | * Lock the page of an asynchronous request without getting a new reference |
116 | */ | 113 | */ |