Commit e755d638 authored by Peng Tao's avatar Peng Tao Committed by Trond Myklebust

NFS41: make sure sending LAYOUTRETURN before close if marked so

If layout is marked by NFS_LAYOUT_RETURN_BEFORE_CLOSE, we should always
send LAYOUTRETURN before close, and we don't need to do ROC drain if we
do send LAYOUTRETURN.
Signed-off-by: default avatarPeng Tao <tao.peng@primarydata.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 36319608
...@@ -1064,7 +1064,7 @@ bool pnfs_roc(struct inode *ino) ...@@ -1064,7 +1064,7 @@ bool pnfs_roc(struct inode *ino)
struct pnfs_layout_segment *lseg, *tmp; struct pnfs_layout_segment *lseg, *tmp;
nfs4_stateid stateid; nfs4_stateid stateid;
LIST_HEAD(tmp_list); LIST_HEAD(tmp_list);
bool found = false, layoutreturn = false; bool found = false, layoutreturn = false, roc = false;
spin_lock(&ino->i_lock); spin_lock(&ino->i_lock);
lo = nfsi->layout; lo = nfsi->layout;
...@@ -1072,7 +1072,7 @@ bool pnfs_roc(struct inode *ino) ...@@ -1072,7 +1072,7 @@ bool pnfs_roc(struct inode *ino)
test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags))
goto out_noroc; goto out_noroc;
/* Don't return layout if we hold a delegation */ /* no roc if we hold a delegation */
if (nfs4_check_delegation(ino, FMODE_READ)) if (nfs4_check_delegation(ino, FMODE_READ))
goto out_noroc; goto out_noroc;
...@@ -1083,36 +1083,41 @@ bool pnfs_roc(struct inode *ino) ...@@ -1083,36 +1083,41 @@ bool pnfs_roc(struct inode *ino)
goto out_noroc; goto out_noroc;
} }
stateid = lo->plh_stateid;
/* always send layoutreturn if being marked so */
if (test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
&lo->plh_flags))
layoutreturn = pnfs_prepare_layoutreturn(lo);
pnfs_clear_retry_layoutget(lo); pnfs_clear_retry_layoutget(lo);
list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list)
if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { /* If we are sending layoutreturn, invalidate all valid lsegs */
if (layoutreturn || test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) {
mark_lseg_invalid(lseg, &tmp_list); mark_lseg_invalid(lseg, &tmp_list);
found = true; found = true;
} }
if (!found) /* pnfs_prepare_layoutreturn() grabs lo ref and it will be put
goto out_noroc; * in pnfs_roc_release(). We don't really send a layoutreturn but
if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) * still want others to view us like we are sending one!
goto out_noroc; *
lo->plh_return_iomode = IOMODE_ANY; * If pnfs_prepare_layoutreturn() fails, it means someone else is doing
pnfs_get_layout_hdr(lo); /* matched in pnfs_roc_release */ * LAYOUTRETURN, so we proceed like there are no layouts to return.
spin_unlock(&ino->i_lock); *
pnfs_free_lseg_list(&tmp_list); * ROC in three conditions:
pnfs_layoutcommit_inode(ino, true); * 1. there are ROC lsegs
return true; * 2. we don't send layoutreturn
* 3. no others are sending layoutreturn
*/
if (found && !layoutreturn && pnfs_prepare_layoutreturn(lo))
roc = true;
out_noroc: out_noroc:
if (lo) {
stateid = lo->plh_stateid;
if (test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
&lo->plh_flags))
layoutreturn = pnfs_prepare_layoutreturn(lo);
}
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
if (layoutreturn) { pnfs_free_lseg_list(&tmp_list);
pnfs_layoutcommit_inode(ino, true); pnfs_layoutcommit_inode(ino, true);
if (layoutreturn)
pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true); pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true);
} return roc;
return false;
} }
void pnfs_roc_release(struct inode *ino) void pnfs_roc_release(struct inode *ino)
......
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