Commit aa1e0e3a authored by Peng Tao's avatar Peng Tao Committed by Tom Haynes

nfs41: send layoutreturn in last put_lseg

If current lseg is the last lseg marked with NFS_LSEG_LAYOUTRETURN,
send layoutreturn.
Signed-off-by: default avatarPeng Tao <tao.peng@primarydata.com>
Signed-off-by: default avatarTom Haynes <Thomas.Haynes@primarydata.com>
parent ce6ab4f2
...@@ -50,6 +50,10 @@ static DEFINE_SPINLOCK(pnfs_spinlock); ...@@ -50,6 +50,10 @@ static DEFINE_SPINLOCK(pnfs_spinlock);
*/ */
static LIST_HEAD(pnfs_modules_tbl); static LIST_HEAD(pnfs_modules_tbl);
static int
pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, nfs4_stateid stateid,
enum pnfs_iomode iomode);
/* Return the registered pnfs layout driver module matching given id */ /* Return the registered pnfs layout driver module matching given id */
static struct pnfs_layoutdriver_type * static struct pnfs_layoutdriver_type *
find_pnfs_driver_locked(u32 id) find_pnfs_driver_locked(u32 id)
...@@ -337,6 +341,29 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo, ...@@ -337,6 +341,29 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo,
rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq);
} }
/* Return true if layoutreturn is needed */
static bool
pnfs_layout_need_return(struct pnfs_layout_hdr *lo,
struct pnfs_layout_segment *lseg,
nfs4_stateid *stateid, enum pnfs_iomode *iomode)
{
struct pnfs_layout_segment *s;
if (!test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
return false;
list_for_each_entry(s, &lo->plh_segs, pls_list)
if (test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
return false;
*stateid = lo->plh_stateid;
*iomode = lo->plh_return_iomode;
/* decreased in pnfs_send_layoutreturn() */
lo->plh_block_lgets++;
lo->plh_return_iomode = 0;
return true;
}
void void
pnfs_put_lseg(struct pnfs_layout_segment *lseg) pnfs_put_lseg(struct pnfs_layout_segment *lseg)
{ {
...@@ -352,11 +379,20 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg) ...@@ -352,11 +379,20 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)
lo = lseg->pls_layout; lo = lseg->pls_layout;
inode = lo->plh_inode; inode = lo->plh_inode;
if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) { if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
bool need_return;
nfs4_stateid stateid;
enum pnfs_iomode iomode;
pnfs_get_layout_hdr(lo); pnfs_get_layout_hdr(lo);
pnfs_layout_remove_lseg(lo, lseg); pnfs_layout_remove_lseg(lo, lseg);
need_return = pnfs_layout_need_return(lo, lseg,
&stateid, &iomode);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
pnfs_free_lseg(lseg); pnfs_free_lseg(lseg);
pnfs_put_layout_hdr(lo); if (need_return)
pnfs_send_layoutreturn(lo, stateid, iomode);
else
pnfs_put_layout_hdr(lo);
} }
} }
EXPORT_SYMBOL_GPL(pnfs_put_lseg); EXPORT_SYMBOL_GPL(pnfs_put_lseg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment