aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/internal.h4
-rw-r--r--fs/nfs/nfs4filelayout.c2
-rw-r--r--fs/nfs/objlayout/objio_osd.c2
-rw-r--r--fs/nfs/pnfs.c57
-rw-r--r--fs/nfs/pnfs.h10
-rw-r--r--fs/nfs/write.c39
-rw-r--r--include/linux/nfs_page.h3
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);
305extern void nfs_readdata_release(struct nfs_read_data *rdata); 305extern void nfs_readdata_release(struct nfs_read_data *rdata);
306 306
307/* write.c */ 307/* write.c */
308extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
309 struct list_head *head);
308extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, 310extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
309 struct inode *inode, int ioflags); 311 struct inode *inode, int ioflags);
312extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
313extern void nfs_writedata_release(struct nfs_write_data *wdata);
310extern void nfs_commit_free(struct nfs_write_data *p); 314extern void nfs_commit_free(struct nfs_write_data *p);
311extern int nfs_initiate_write(struct nfs_write_data *data, 315extern 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 = {
741static const struct nfs_pageio_ops filelayout_pg_write_ops = { 741static 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
747static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg) 747static 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 = {
1013static const struct nfs_pageio_ops objio_pg_write_ops = { 1013static 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
1019static struct pnfs_layoutdriver_type objlayout_type = { 1019static 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}
1171EXPORT_SYMBOL_GPL(pnfs_ld_write_done); 1171EXPORT_SYMBOL_GPL(pnfs_ld_write_done);
1172 1172
1173enum pnfs_try_status 1173static void
1174pnfs_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
1185static enum pnfs_try_status
1174pnfs_try_to_write_data(struct nfs_write_data *wdata, 1186pnfs_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
1212static void
1213pnfs_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
1233int
1234pnfs_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}
1248EXPORT_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
156void set_pnfs_layoutdriver(struct nfs_server *, u32 id); 156void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
157void unset_pnfs_layoutdriver(struct nfs_server *); 157void unset_pnfs_layoutdriver(struct nfs_server *);
158enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
159 const struct rpc_call_ops *, int);
160void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); 158void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
161int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc); 159int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
162void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); 160void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *);
161int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc);
163bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); 162bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req);
164int pnfs_layout_process(struct nfs4_layoutget *lgp); 163int pnfs_layout_process(struct nfs4_layoutget *lgp);
165void pnfs_free_lseg_list(struct list_head *tmp_list); 164void 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
331static inline enum pnfs_try_status
332pnfs_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
338static inline int pnfs_return_layout(struct inode *ino) 330static 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
100static void nfs_writedata_release(struct nfs_write_data *wdata) 100void 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
888static int nfs_do_write(struct nfs_write_data *data, 888static 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
906static int nfs_do_multiple_writes(struct list_head *head, 897static 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
1040int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) 1030int 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
1037static 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}
1056EXPORT_SYMBOL_GPL(nfs_generic_pg_writepages);
1057 1048
1058static const struct nfs_pageio_ops nfs_pageio_write_ops = { 1049static 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}
1069EXPORT_SYMBOL_GPL(nfs_pageio_init_write_mds); 1060EXPORT_SYMBOL_GPL(nfs_pageio_init_write_mds);
1070 1061
1062void 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
1071static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, 1068static 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);
108extern int nfs_set_page_tag_locked(struct nfs_page *req); 108extern int nfs_set_page_tag_locked(struct nfs_page *req);
109extern void nfs_clear_page_tag_locked(struct nfs_page *req); 109extern void nfs_clear_page_tag_locked(struct nfs_page *req);
110 110
111extern 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 */