diff options
Diffstat (limited to 'fs/nfs')
| -rw-r--r-- | fs/nfs/callback_proc.c | 1 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4file.c | 1 | ||||
| -rw-r--r-- | fs/nfs/pnfs.c | 21 | ||||
| -rw-r--r-- | fs/nfs/pnfs.h | 1 | 
5 files changed, 19 insertions, 6 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index c8520284dda7..c1eda73254e1 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -288,6 +288,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,  		rv = NFS4_OK;  		break;  	case -ENOENT: +		set_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags);  		/* Embrace your forgetfulness! */  		rv = NFS4ERR_NOMATCHING_LAYOUT; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a8ecdd527662..0c4e8dd6aa96 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2124,6 +2124,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,  		}  		goto out;  	} +	file->f_mode |= FMODE_CAN_ODIRECT;  	err = nfs_finish_open(ctx, ctx->dentry, file, open_flags);  	trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 03d3a270eff4..e88f6b18445e 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -93,6 +93,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)  	nfs_file_set_open_context(filp, ctx);  	nfs_fscache_open_file(inode, filp);  	err = 0; +	filp->f_mode |= FMODE_CAN_ODIRECT;  out_put_ctx:  	put_nfs_open_context(ctx); 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)) { diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 07f11489e4e9..f331f067691b 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -105,6 +105,7 @@ enum {  	NFS_LAYOUT_FIRST_LAYOUTGET,	/* Serialize first layoutget */  	NFS_LAYOUT_INODE_FREEING,	/* The inode is being freed */  	NFS_LAYOUT_HASHED,		/* The layout visible */ +	NFS_LAYOUT_DRAIN,  };  enum layoutdriver_policy_flags {  | 
