mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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:
		
							parent
							
								
									cd3f77d74a
								
							
						
					
					
						commit
						e0b7d420f7
					
				
					 2 changed files with 39 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue