diff options
author | Peng Tao <peng_tao@emc.com> | 2011-07-30 20:52:33 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-31 12:18:15 -0400 |
commit | a9bae5666d0510ad69bdb437371c9a3e6b770705 (patch) | |
tree | 5f94d5b75d7d870df9812f1bf277d91d9d7d66c1 /fs | |
parent | 9fa4075878a5faac872a63f4a97ce79c776264e9 (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.c | 8 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 32 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 2 |
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) | |||
5912 | static void nfs4_layoutcommit_release(void *calldata) | 5912 | static 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 | |||
225 | init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg) | 225 | init_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) | |||
1356 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages); | 1357 | EXPORT_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 | */ |
1361 | static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode) | 1362 | static 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 | ||
1371 | void | 1373 | void |
@@ -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 @@ | |||
36 | enum { | 36 | enum { |
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 | ||
41 | struct pnfs_layout_segment { | 42 | struct 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; |