Commit dce81290eed64d24493989bb7a08f9e20495e184

Authored by Trond Myklebust
1 parent 493292ddc7

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>

Showing 7 changed files with 80 additions and 37 deletions Side-by-side Diff

... ... @@ -305,8 +305,12 @@
305 305 extern void nfs_readdata_release(struct nfs_read_data *rdata);
306 306  
307 307 /* write.c */
  308 +extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
  309 + struct list_head *head);
308 310 extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
309 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 314 extern void nfs_commit_free(struct nfs_write_data *p);
311 315 extern int nfs_initiate_write(struct nfs_write_data *data,
312 316 struct rpc_clnt *clnt,
fs/nfs/nfs4filelayout.c
... ... @@ -741,7 +741,7 @@
741 741 static const struct nfs_pageio_ops filelayout_pg_write_ops = {
742 742 .pg_init = filelayout_pg_init_write,
743 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 747 static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg)
fs/nfs/objlayout/objio_osd.c
... ... @@ -1013,7 +1013,7 @@
1013 1013 static const struct nfs_pageio_ops objio_pg_write_ops = {
1014 1014 .pg_init = pnfs_generic_pg_init_write,
1015 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 1019 static struct pnfs_layoutdriver_type objlayout_type = {
... ... @@ -1170,15 +1170,30 @@
1170 1170 }
1171 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 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 1191 struct inode *inode = wdata->inode;
1178 1192 enum pnfs_try_status trypnfs;
1179 1193 struct nfs_server *nfss = NFS_SERVER(inode);
1180 1194  
1181 1195 wdata->mds_ops = call_ops;
  1196 + wdata->lseg = get_lseg(lseg);
1182 1197  
1183 1198 dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__,
1184 1199 inode->i_ino, wdata->args.count, wdata->args.offset, how);
... ... @@ -1193,6 +1208,44 @@
1193 1208 dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs);
1194 1209 return trypnfs;
1195 1210 }
  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);
1196 1249  
1197 1250 /*
1198 1251 * Called by non rpc-based layout drivers
... ... @@ -155,11 +155,10 @@
155 155  
156 156 void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
157 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 158 void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
161 159 int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
162 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 162 bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req);
164 163 int pnfs_layout_process(struct nfs4_layoutget *lgp);
165 164 void pnfs_free_lseg_list(struct list_head *tmp_list);
... ... @@ -326,13 +325,6 @@
326 325  
327 326 static inline void put_lseg(struct pnfs_layout_segment *lseg)
328 327 {
329   -}
330   -
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 328 }
337 329  
338 330 static inline int pnfs_return_layout(struct inode *ino)
... ... @@ -97,7 +97,7 @@
97 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 102 put_lseg(wdata->lseg);
103 103 put_nfs_open_context(wdata->args.context);
104 104  
105 105  
... ... @@ -887,25 +887,15 @@
887 887  
888 888 static int nfs_do_write(struct nfs_write_data *data,
889 889 const struct rpc_call_ops *call_ops,
890   - struct pnfs_layout_segment *lseg,
891 890 int how)
892 891 {
893 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 894 return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how);
904 895 }
905 896  
906 897 static int nfs_do_multiple_writes(struct list_head *head,
907 898 const struct rpc_call_ops *call_ops,
908   - struct pnfs_layout_segment *lseg,
909 899 int how)
910 900 {
911 901 struct nfs_write_data *data;
... ... @@ -917,7 +907,7 @@
917 907 data = list_entry(head->next, struct nfs_write_data, list);
918 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 911 if (ret == 0)
922 912 ret = ret2;
923 913 }
924 914  
925 915  
926 916  
927 917  
... ... @@ -1037,23 +1027,24 @@
1037 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)
1041 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)
  1038 +{
1042 1039 LIST_HEAD(head);
1043 1040 int ret;
1044 1041  
1045   - if (desc->pg_bsize < PAGE_CACHE_SIZE)
1046   - ret = nfs_flush_multi(desc, &head);
1047   - else
1048   - ret = nfs_flush_one(desc, &head);
  1042 + ret = nfs_generic_flush(desc, &head);
1049 1043 if (ret == 0)
1050 1044 ret = nfs_do_multiple_writes(&head, desc->pg_rpc_callops,
1051   - desc->pg_lseg, desc->pg_ioflags);
1052   - put_lseg(desc->pg_lseg);
1053   - desc->pg_lseg = NULL;
  1045 + desc->pg_ioflags);
1054 1046 return ret;
1055 1047 }
1056   -EXPORT_SYMBOL_GPL(nfs_generic_pg_writepages);
1057 1048  
1058 1049 static const struct nfs_pageio_ops nfs_pageio_write_ops = {
1059 1050 .pg_test = nfs_generic_pg_test,
... ... @@ -1067,6 +1058,12 @@
1067 1058 NFS_SERVER(inode)->wsize, ioflags);
1068 1059 }
1069 1060 EXPORT_SYMBOL_GPL(nfs_pageio_init_write_mds);
  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 +}
1070 1067  
1071 1068 static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
1072 1069 struct inode *inode, int ioflags)
include/linux/nfs_page.h
... ... @@ -108,9 +108,6 @@
108 108 extern int nfs_set_page_tag_locked(struct nfs_page *req);
109 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 112 * Lock the page of an asynchronous request without getting a new reference
116 113 */