提交 e0b7d420 编写于 作者: T Trond Myklebust

pNFS: Don't discard layout segments that are marked for return

If there are layout segments that are marked for return, then we need
to ensure that pnfs_mark_matching_lsegs_return() does not just
silently discard them, but it should tell the caller that there is a
layoutreturn scheduled.
Signed-off-by: NTrond Myklebust <trond.myklebust@hammerspace.com>
上级 cd3f77d7
......@@ -283,13 +283,15 @@ static u32 initiate_file_draining(struct nfs_client *clp,
goto unlock;
}
if (pnfs_mark_matching_lsegs_return(lo, &free_me_list,
switch (pnfs_mark_matching_lsegs_return(lo, &free_me_list,
&args->cbl_range,
be32_to_cpu(args->cbl_stateid.seqid))) {
case 0:
case -EBUSY:
/* There are layout segments that need to be returned */
rv = NFS4_OK;
goto unlock;
}
break;
case -ENOENT:
/* Embrace your forgetfulness! */
rv = NFS4ERR_NOMATCHING_LAYOUT;
......@@ -297,6 +299,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
&args->cbl_range);
}
}
unlock:
spin_unlock(&ino->i_lock);
pnfs_free_lseg_list(&free_me_list);
......
......@@ -2238,15 +2238,31 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
return ERR_PTR(-EAGAIN);
}
static int
mark_lseg_invalid_or_return(struct pnfs_layout_segment *lseg,
struct list_head *tmp_list)
{
if (!mark_lseg_invalid(lseg, tmp_list))
return 0;
pnfs_cache_lseg_for_layoutreturn(lseg->pls_layout, lseg);
return 1;
}
/**
* pnfs_mark_matching_lsegs_return - Free or return matching layout segments
* @lo: pointer to layout header
* @tmp_list: list header to be used with pnfs_free_lseg_list()
* @return_range: describe layout segment ranges to be returned
* @seq: stateid seqid to match
*
* This function is mainly intended for use by layoutrecall. It attempts
* to free the layout segment immediately, or else to mark it for return
* as soon as its reference count drops to zero.
*
* Returns
* - 0: a layoutreturn needs to be scheduled.
* - EBUSY: there are layout segment that are still in use.
* - ENOENT: there are no layout segments that need to be returned.
*/
int
pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
......@@ -2259,9 +2275,6 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
dprintk("%s:Begin lo %p\n", __func__, lo);
if (list_empty(&lo->plh_segs))
return 0;
assert_spin_locked(&lo->plh_inode->i_lock);
list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
......@@ -2271,16 +2284,23 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
lseg, lseg->pls_range.iomode,
lseg->pls_range.offset,
lseg->pls_range.length);
if (mark_lseg_invalid(lseg, tmp_list))
if (mark_lseg_invalid_or_return(lseg, tmp_list))
continue;
remaining++;
set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags);
}
if (remaining)
if (remaining) {
pnfs_set_plh_return_info(lo, return_range->iomode, seq);
return -EBUSY;
}
return remaining;
if (!list_empty(&lo->plh_return_segs)) {
pnfs_set_plh_return_info(lo, return_range->iomode, seq);
return 0;
}
return -ENOENT;
}
void pnfs_error_mark_layout_for_return(struct inode *inode,
......@@ -2305,7 +2325,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
* segments at hand when sending layoutreturn. See pnfs_put_lseg()
* for how it works.
*/
if (!pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, &range, 0)) {
if (pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, &range, 0) != -EBUSY) {
nfs4_stateid stateid;
enum pnfs_iomode iomode;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册