diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 57 |
1 files changed, 55 insertions, 2 deletions
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 | */ |