diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
| -rw-r--r-- | fs/nfs/pnfs.c | 21 | 
1 files changed, 15 insertions, 6 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 68a87be3e6f9..41a9b6b58fb9 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -469,6 +469,7 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,  		pnfs_clear_lseg_state(lseg, lseg_list);  	pnfs_clear_layoutreturn_info(lo);  	pnfs_free_returned_lsegs(lo, lseg_list, &range, 0); +	set_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags);  	if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags) &&  	    !test_and_set_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags))  		pnfs_clear_layoutreturn_waitbit(lo); @@ -1917,8 +1918,9 @@ static void nfs_layoutget_begin(struct pnfs_layout_hdr *lo)  static void nfs_layoutget_end(struct pnfs_layout_hdr *lo)  { -	if (atomic_dec_and_test(&lo->plh_outstanding)) -		wake_up_var(&lo->plh_outstanding); +	if (atomic_dec_and_test(&lo->plh_outstanding) && +	    test_and_clear_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags)) +		wake_up_bit(&lo->plh_flags, NFS_LAYOUT_DRAIN);  }  static bool pnfs_is_first_layoutget(struct pnfs_layout_hdr *lo) @@ -2025,11 +2027,11 @@ lookup_again:  	 * If the layout segment list is empty, but there are outstanding  	 * layoutget calls, then they might be subject to a layoutrecall.  	 */ -	if ((list_empty(&lo->plh_segs) || !pnfs_layout_is_valid(lo)) && +	if (test_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags) &&  	    atomic_read(&lo->plh_outstanding) != 0) {  		spin_unlock(&ino->i_lock); -		lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding, -					!atomic_read(&lo->plh_outstanding))); +		lseg = ERR_PTR(wait_on_bit(&lo->plh_flags, NFS_LAYOUT_DRAIN, +					   TASK_KILLABLE));  		if (IS_ERR(lseg))  			goto out_put_layout_hdr;  		pnfs_put_layout_hdr(lo); @@ -2152,6 +2154,12 @@ lookup_again:  		case -ERECALLCONFLICT:  		case -EAGAIN:  			break; +		case -ENODATA: +			/* The server returned NFS4ERR_LAYOUTUNAVAILABLE */ +			pnfs_layout_set_fail_bit( +				lo, pnfs_iomode_to_fail_bit(iomode)); +			lseg = NULL; +			goto out_put_layout_hdr;  		default:  			if (!nfs_error_is_fatal(PTR_ERR(lseg))) {  				pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode)); @@ -2407,7 +2415,8 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)  		goto out_forget;  	} -	if (!pnfs_layout_is_valid(lo) && !pnfs_is_first_layoutget(lo)) +	if (test_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags) && +	    !pnfs_is_first_layoutget(lo))  		goto out_forget;  	if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) {  |