aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-13 15:59:19 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-15 09:12:22 -0400
commitdce81290eed64d24493989bb7a08f9e20495e184 (patch)
treeeb25c828d3343196fe31d95da2d7d743692fa71e
parent493292ddc78d18ee2ad2d5c24c2b7dd6a24641d2 (diff)
NFS: Move the pnfs write code into pnfs.c
...and ensure that we recoalese to take into account differences in differences in block sizes when falling back to write through the MDS. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-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 */