aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2012-04-20 14:47:47 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-04-27 14:10:37 -0400
commit6c75dc0d498caa402fb17b1bf769835a9db875c8 (patch)
treeb367bb2428c011f20b8fd47a6dd0b8603ee136ba /fs/nfs/pnfs.c
parent4db6e0b74c0f6dfc2f9c0690e8df512e3b635983 (diff)
NFS: merge _full and _partial write rpc_ops
Decouple nfs_pgio_header and nfs_write_data, and have (possibly multiple) nfs_write_datas each take a refcount on nfs_pgio_header. For the moment keeps nfs_write_header as a way to preallocate a single nfs_write_data with the nfs_pgio_header. The code doesn't need this, and would be prettier without, but given the amount of churn I am already introducing I didn't want to play with tuning new mempools. This also fixes bug in pnfs_ld_handle_write_error. In the case of desc->pg_bsize < PAGE_CACHE_SIZE, the pages list was empty, causing replay attempt to do nothing. Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c58
1 files changed, 36 insertions, 22 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index d1a91dbe7654..d515f00614cd 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1199,7 +1199,9 @@ static void pnfs_ld_handle_write_error(struct nfs_write_data *data)
1199 clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags); 1199 clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
1200 pnfs_return_layout(hdr->inode); 1200 pnfs_return_layout(hdr->inode);
1201 } 1201 }
1202 data->task.tk_status = pnfs_write_done_resend_to_mds(hdr->inode, &hdr->pages); 1202 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
1203 data->task.tk_status = pnfs_write_done_resend_to_mds(hdr->inode,
1204 &hdr->pages);
1203} 1205}
1204 1206
1205/* 1207/*
@@ -1214,7 +1216,6 @@ void pnfs_ld_write_done(struct nfs_write_data *data)
1214 hdr->mds_ops->rpc_call_done(&data->task, data); 1216 hdr->mds_ops->rpc_call_done(&data->task, data);
1215 } else 1217 } else
1216 pnfs_ld_handle_write_error(data); 1218 pnfs_ld_handle_write_error(data);
1217 put_lseg(hdr->lseg);
1218 hdr->mds_ops->rpc_release(data); 1219 hdr->mds_ops->rpc_release(data);
1219} 1220}
1220EXPORT_SYMBOL_GPL(pnfs_ld_write_done); 1221EXPORT_SYMBOL_GPL(pnfs_ld_write_done);
@@ -1225,12 +1226,11 @@ pnfs_write_through_mds(struct nfs_pageio_descriptor *desc,
1225{ 1226{
1226 struct nfs_pgio_header *hdr = data->header; 1227 struct nfs_pgio_header *hdr = data->header;
1227 1228
1228 list_splice_tail_init(&hdr->pages, &desc->pg_list); 1229 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
1229 if (hdr->req && list_empty(&hdr->req->wb_list)) 1230 list_splice_tail_init(&hdr->pages, &desc->pg_list);
1230 nfs_list_add_request(hdr->req, &desc->pg_list); 1231 nfs_pageio_reset_write_mds(desc);
1231 nfs_pageio_reset_write_mds(desc); 1232 desc->pg_recoalesce = 1;
1232 desc->pg_recoalesce = 1; 1233 }
1233 put_lseg(hdr->lseg);
1234 nfs_writedata_release(data); 1234 nfs_writedata_release(data);
1235} 1235}
1236 1236
@@ -1246,18 +1246,12 @@ pnfs_try_to_write_data(struct nfs_write_data *wdata,
1246 struct nfs_server *nfss = NFS_SERVER(inode); 1246 struct nfs_server *nfss = NFS_SERVER(inode);
1247 1247
1248 hdr->mds_ops = call_ops; 1248 hdr->mds_ops = call_ops;
1249 hdr->lseg = get_lseg(lseg);
1250 1249
1251 dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__, 1250 dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__,
1252 inode->i_ino, wdata->args.count, wdata->args.offset, how); 1251 inode->i_ino, wdata->args.count, wdata->args.offset, how);
1253
1254 trypnfs = nfss->pnfs_curr_ld->write_pagelist(wdata, how); 1252 trypnfs = nfss->pnfs_curr_ld->write_pagelist(wdata, how);
1255 if (trypnfs == PNFS_NOT_ATTEMPTED) { 1253 if (trypnfs != PNFS_NOT_ATTEMPTED)
1256 put_lseg(hdr->lseg);
1257 hdr->lseg = NULL;
1258 } else
1259 nfs_inc_stats(inode, NFSIOS_PNFS_WRITE); 1254 nfs_inc_stats(inode, NFSIOS_PNFS_WRITE);
1260
1261 dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); 1255 dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs);
1262 return trypnfs; 1256 return trypnfs;
1263} 1257}
@@ -1273,7 +1267,7 @@ pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *he
1273 while (!list_empty(head)) { 1267 while (!list_empty(head)) {
1274 enum pnfs_try_status trypnfs; 1268 enum pnfs_try_status trypnfs;
1275 1269
1276 data = list_entry(head->next, struct nfs_write_data, list); 1270 data = list_first_entry(head, struct nfs_write_data, list);
1277 list_del_init(&data->list); 1271 list_del_init(&data->list);
1278 1272
1279 trypnfs = pnfs_try_to_write_data(data, call_ops, lseg, how); 1273 trypnfs = pnfs_try_to_write_data(data, call_ops, lseg, how);
@@ -1283,20 +1277,40 @@ pnfs_do_multiple_writes(struct nfs_pageio_descriptor *desc, struct list_head *he
1283 put_lseg(lseg); 1277 put_lseg(lseg);
1284} 1278}
1285 1279
1280static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)
1281{
1282 put_lseg(hdr->lseg);
1283 nfs_writehdr_free(hdr);
1284}
1285
1286int 1286int
1287pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) 1287pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1288{ 1288{
1289 LIST_HEAD(head); 1289 struct nfs_write_header *whdr;
1290 struct nfs_pgio_header *hdr;
1290 int ret; 1291 int ret;
1291 1292
1292 ret = nfs_generic_flush(desc, &head); 1293 whdr = nfs_writehdr_alloc();
1293 if (ret != 0) { 1294 if (!whdr) {
1295 nfs_async_write_error(&desc->pg_list);
1294 put_lseg(desc->pg_lseg); 1296 put_lseg(desc->pg_lseg);
1295 desc->pg_lseg = NULL; 1297 desc->pg_lseg = NULL;
1296 return ret; 1298 return -ENOMEM;
1297 } 1299 }
1298 pnfs_do_multiple_writes(desc, &head, desc->pg_ioflags); 1300 hdr = &whdr->header;
1299 return 0; 1301 nfs_pgheader_init(desc, hdr, pnfs_writehdr_free);
1302 hdr->lseg = get_lseg(desc->pg_lseg);
1303 atomic_inc(&hdr->refcnt);
1304 ret = nfs_generic_flush(desc, hdr);
1305 if (ret != 0) {
1306 put_lseg(desc->pg_lseg);
1307 desc->pg_lseg = NULL;
1308 set_bit(NFS_IOHDR_REDO, &hdr->flags);
1309 } else
1310 pnfs_do_multiple_writes(desc, &hdr->rpc_list, desc->pg_ioflags);
1311 if (atomic_dec_and_test(&hdr->refcnt))
1312 nfs_write_completion(hdr);
1313 return ret;
1300} 1314}
1301EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); 1315EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
1302 1316