diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-07-09 18:24:07 +0200 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-07-11 16:16:17 +0200 |
commit | faa4a54f0be15b5d81b574fb5a40db24345d1a6c (patch) | |
tree | 59936bd0b4c72517e745495401f7292b036a293d /fs | |
parent | pNFS: pnfs_roc_drain() fix a race with open (diff) | |
download | linux-faa4a54f0be15b5d81b574fb5a40db24345d1a6c.tar.xz linux-faa4a54f0be15b5d81b574fb5a40db24345d1a6c.zip |
pNFS: Don't throw out valid layout segments
It is OK for layout segments to remain hashed even if no-one holds any
references to them, provided that the segments are still valid.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/pnfs.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index b02e32e2abeb..18aa3b7962eb 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -422,6 +422,10 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg) pnfs_layoutreturn_before_put_lseg(lseg, lo, inode); if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) { + if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) { + spin_unlock(&inode->i_lock); + return; + } pnfs_get_layout_hdr(lo); pnfs_layout_remove_lseg(lo, lseg); spin_unlock(&inode->i_lock); @@ -462,6 +466,8 @@ pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg) test_bit(NFS_LSEG_VALID, &lseg->pls_flags)); if (atomic_dec_and_test(&lseg->pls_refcount)) { struct pnfs_layout_hdr *lo = lseg->pls_layout; + if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) + return; pnfs_get_layout_hdr(lo); pnfs_layout_remove_lseg(lo, lseg); pnfs_free_lseg_async(lseg); |