aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorPeng Tao <peng_tao@emc.com>2011-07-30 20:52:33 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-31 12:18:15 -0400
commita9bae5666d0510ad69bdb437371c9a3e6b770705 (patch)
tree5f94d5b75d7d870df9812f1bf277d91d9d7d66c1 /fs
parent9fa4075878a5faac872a63f4a97ce79c776264e9 (diff)
pnfs: let layoutcommit handle a list of lseg
There can be multiple lseg per file, so layoutcommit should be able to handle it. [Needed in v3.0] CC: Stable Tree <stable@kernel.org> Signed-off-by: Peng Tao <peng_tao@emc.com> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Jim Rees <rees@umich.edu> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4proc.c8
-rw-r--r--fs/nfs/pnfs.c32
-rw-r--r--fs/nfs/pnfs.h2
3 files changed, 25 insertions, 17 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 079614deca3f..efa6ae822ca8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5912,9 +5912,15 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
5912static void nfs4_layoutcommit_release(void *calldata) 5912static void nfs4_layoutcommit_release(void *calldata)
5913{ 5913{
5914 struct nfs4_layoutcommit_data *data = calldata; 5914 struct nfs4_layoutcommit_data *data = calldata;
5915 struct pnfs_layout_segment *lseg, *tmp;
5915 5916
5916 /* Matched by references in pnfs_set_layoutcommit */ 5917 /* Matched by references in pnfs_set_layoutcommit */
5917 put_lseg(data->lseg); 5918 list_for_each_entry_safe(lseg, tmp, &data->lseg_list, pls_lc_list) {
5919 list_del_init(&lseg->pls_lc_list);
5920 if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT,
5921 &lseg->pls_flags))
5922 put_lseg(lseg);
5923 }
5918 put_rpccred(data->cred); 5924 put_rpccred(data->cred);
5919 kfree(data); 5925 kfree(data);
5920} 5926}
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index ab2cb04f8a28..a7e5f17f7776 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -225,6 +225,7 @@ static void
225init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg) 225init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg)
226{ 226{
227 INIT_LIST_HEAD(&lseg->pls_list); 227 INIT_LIST_HEAD(&lseg->pls_list);
228 INIT_LIST_HEAD(&lseg->pls_lc_list);
228 atomic_set(&lseg->pls_refcount, 1); 229 atomic_set(&lseg->pls_refcount, 1);
229 smp_mb(); 230 smp_mb();
230 set_bit(NFS_LSEG_VALID, &lseg->pls_flags); 231 set_bit(NFS_LSEG_VALID, &lseg->pls_flags);
@@ -1356,16 +1357,17 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
1356EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages); 1357EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages);
1357 1358
1358/* 1359/*
1359 * Currently there is only one (whole file) write lseg. 1360 * There can be multiple RW segments.
1360 */ 1361 */
1361static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode) 1362static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp)
1362{ 1363{
1363 struct pnfs_layout_segment *lseg, *rv = NULL; 1364 struct pnfs_layout_segment *lseg;
1364 1365
1365 list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) 1366 list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) {
1366 if (lseg->pls_range.iomode == IOMODE_RW) 1367 if (lseg->pls_range.iomode == IOMODE_RW &&
1367 rv = lseg; 1368 test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
1368 return rv; 1369 list_add(&lseg->pls_lc_list, listp);
1370 }
1369} 1371}
1370 1372
1371void 1373void
@@ -1377,12 +1379,14 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
1377 1379
1378 spin_lock(&nfsi->vfs_inode.i_lock); 1380 spin_lock(&nfsi->vfs_inode.i_lock);
1379 if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { 1381 if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
1380 /* references matched in nfs4_layoutcommit_release */
1381 get_lseg(wdata->lseg);
1382 mark_as_dirty = true; 1382 mark_as_dirty = true;
1383 dprintk("%s: Set layoutcommit for inode %lu ", 1383 dprintk("%s: Set layoutcommit for inode %lu ",
1384 __func__, wdata->inode->i_ino); 1384 __func__, wdata->inode->i_ino);
1385 } 1385 }
1386 if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &wdata->lseg->pls_flags)) {
1387 /* references matched in nfs4_layoutcommit_release */
1388 get_lseg(wdata->lseg);
1389 }
1386 if (end_pos > nfsi->layout->plh_lwb) 1390 if (end_pos > nfsi->layout->plh_lwb)
1387 nfsi->layout->plh_lwb = end_pos; 1391 nfsi->layout->plh_lwb = end_pos;
1388 spin_unlock(&nfsi->vfs_inode.i_lock); 1392 spin_unlock(&nfsi->vfs_inode.i_lock);
@@ -1409,7 +1413,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
1409{ 1413{
1410 struct nfs4_layoutcommit_data *data; 1414 struct nfs4_layoutcommit_data *data;
1411 struct nfs_inode *nfsi = NFS_I(inode); 1415 struct nfs_inode *nfsi = NFS_I(inode);
1412 struct pnfs_layout_segment *lseg;
1413 loff_t end_pos; 1416 loff_t end_pos;
1414 int status = 0; 1417 int status = 0;
1415 1418
@@ -1426,17 +1429,15 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
1426 goto out; 1429 goto out;
1427 } 1430 }
1428 1431
1432 INIT_LIST_HEAD(&data->lseg_list);
1429 spin_lock(&inode->i_lock); 1433 spin_lock(&inode->i_lock);
1430 if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { 1434 if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
1431 spin_unlock(&inode->i_lock); 1435 spin_unlock(&inode->i_lock);
1432 kfree(data); 1436 kfree(data);
1433 goto out; 1437 goto out;
1434 } 1438 }
1435 /* 1439
1436 * Currently only one (whole file) write lseg which is referenced 1440 pnfs_list_write_lseg(inode, &data->lseg_list);
1437 * in pnfs_set_layoutcommit and will be found.
1438 */
1439 lseg = pnfs_list_write_lseg(inode);
1440 1441
1441 end_pos = nfsi->layout->plh_lwb; 1442 end_pos = nfsi->layout->plh_lwb;
1442 nfsi->layout->plh_lwb = 0; 1443 nfsi->layout->plh_lwb = 0;
@@ -1446,7 +1447,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
1446 spin_unlock(&inode->i_lock); 1447 spin_unlock(&inode->i_lock);
1447 1448
1448 data->args.inode = inode; 1449 data->args.inode = inode;
1449 data->lseg = lseg;
1450 data->cred = get_rpccred(nfsi->layout->plh_lc_cred); 1450 data->cred = get_rpccred(nfsi->layout->plh_lc_cred);
1451 nfs_fattr_init(&data->fattr); 1451 nfs_fattr_init(&data->fattr);
1452 data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; 1452 data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 1f5cb47e2a2c..b94f874886ca 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -36,10 +36,12 @@
36enum { 36enum {
37 NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */ 37 NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */
38 NFS_LSEG_ROC, /* roc bit received from server */ 38 NFS_LSEG_ROC, /* roc bit received from server */
39 NFS_LSEG_LAYOUTCOMMIT, /* layoutcommit bit set for layoutcommit */
39}; 40};
40 41
41struct pnfs_layout_segment { 42struct pnfs_layout_segment {
42 struct list_head pls_list; 43 struct list_head pls_list;
44 struct list_head pls_lc_list;
43 struct pnfs_layout_range pls_range; 45 struct pnfs_layout_range pls_range;
44 atomic_t pls_refcount; 46 atomic_t pls_refcount;
45 unsigned long pls_flags; 47 unsigned long pls_flags;