Commit e0b7d420 authored by Trond Myklebust's avatar 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: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent cd3f77d7
...@@ -283,13 +283,15 @@ static u32 initiate_file_draining(struct nfs_client *clp, ...@@ -283,13 +283,15 @@ static u32 initiate_file_draining(struct nfs_client *clp,
goto unlock; 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, &args->cbl_range,
be32_to_cpu(args->cbl_stateid.seqid))) { be32_to_cpu(args->cbl_stateid.seqid))) {
case 0:
case -EBUSY:
/* There are layout segments that need to be returned */
rv = NFS4_OK; rv = NFS4_OK;
goto unlock; break;
} case -ENOENT:
/* Embrace your forgetfulness! */ /* Embrace your forgetfulness! */
rv = NFS4ERR_NOMATCHING_LAYOUT; rv = NFS4ERR_NOMATCHING_LAYOUT;
...@@ -297,6 +299,7 @@ static u32 initiate_file_draining(struct nfs_client *clp, ...@@ -297,6 +299,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo, NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
&args->cbl_range); &args->cbl_range);
} }
}
unlock: unlock:
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
pnfs_free_lseg_list(&free_me_list); pnfs_free_lseg_list(&free_me_list);
......
...@@ -2238,15 +2238,31 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) ...@@ -2238,15 +2238,31 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
return ERR_PTR(-EAGAIN); 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 * pnfs_mark_matching_lsegs_return - Free or return matching layout segments
* @lo: pointer to layout header * @lo: pointer to layout header
* @tmp_list: list header to be used with pnfs_free_lseg_list() * @tmp_list: list header to be used with pnfs_free_lseg_list()
* @return_range: describe layout segment ranges to be returned * @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 * This function is mainly intended for use by layoutrecall. It attempts
* to free the layout segment immediately, or else to mark it for return * to free the layout segment immediately, or else to mark it for return
* as soon as its reference count drops to zero. * 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 int
pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo, pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
...@@ -2259,9 +2275,6 @@ 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); dprintk("%s:Begin lo %p\n", __func__, lo);
if (list_empty(&lo->plh_segs))
return 0;
assert_spin_locked(&lo->plh_inode->i_lock); assert_spin_locked(&lo->plh_inode->i_lock);
list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) 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, ...@@ -2271,16 +2284,23 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
lseg, lseg->pls_range.iomode, lseg, lseg->pls_range.iomode,
lseg->pls_range.offset, lseg->pls_range.offset,
lseg->pls_range.length); lseg->pls_range.length);
if (mark_lseg_invalid(lseg, tmp_list)) if (mark_lseg_invalid_or_return(lseg, tmp_list))
continue; continue;
remaining++; remaining++;
set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags); set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags);
} }
if (remaining) if (remaining) {
pnfs_set_plh_return_info(lo, return_range->iomode, seq); 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, void pnfs_error_mark_layout_for_return(struct inode *inode,
...@@ -2305,7 +2325,7 @@ 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() * segments at hand when sending layoutreturn. See pnfs_put_lseg()
* for how it works. * 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; nfs4_stateid stateid;
enum pnfs_iomode iomode; enum pnfs_iomode iomode;
......
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