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: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
Trond Myklebust 2018-06-23 10:28:40 -04:00
parent cd3f77d74a
commit e0b7d420f7
2 changed files with 39 additions and 16 deletions

View File

@ -283,19 +283,22 @@ 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;
/* Embrace your forgetfulness! */
rv = NFS4ERR_NOMATCHING_LAYOUT;
if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
&args->cbl_range);
if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
&args->cbl_range);
}
}
unlock:
spin_unlock(&ino->i_lock);

View File

@ -2238,15 +2238,31 @@ out_forget:
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;