Re: [PATCH v4] nfsd: disallow file locking and delegations for NFSv4 reexport

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2025-02-10 at 11:25 -0500, cel@xxxxxxxxxx wrote:
> From: Mike Snitzer <snitzer@xxxxxxxxxx>
> 
> We do not and cannot support file locking with NFS reexport over
> NFSv4.x for the same reason we don't do it for NFSv3: NFS reexport
> server reboot cannot allow clients to recover locks because the source
> NFS server has not rebooted, and so it is not in grace. 
> 

Refresh my memory: how do we prevent this in v3? It seems like NLM
should use the same mechanism.

>  Since the
> source NFS server is not in grace, it cannot offer any guarantees that
> the file won't have been changed between the locks getting lost and
> any attempt to recover/reclaim them.  The same applies to delegations
> and any associated locks, so disallow them too.
> 
> Clients are no longer allowed to get file locks or delegations from a
> reexport server, any attempts will fail with operation not supported.
> 
> Update the "Reboot recovery" section accordingly in
> Documentation/filesystems/nfs/reexport.rst
> 
> Signed-off-by: Mike Snitzer <snitzer@xxxxxxxxxx>
> Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
> ---
>  Documentation/filesystems/nfs/reexport.rst | 10 +++++++---
>  fs/nfs/export.c                            |  3 ++-
>  fs/nfsd/nfs4state.c                        | 18 ++++++++++++++++++
>  include/linux/exportfs.h                   | 14 +++++++++++++-
>  4 files changed, 40 insertions(+), 5 deletions(-)
> 
> 
> Jeff and I believe that it is better to prevent data corruption for
> now than to continue to enable risky use cases. Thus I've forward-
> ported this patch to v6.14-rc2 and intend to include it in the
> nfsd-6.15 pull request.
> 
> We remain open to considering solutions that enable locking through
> to the back-end NFS server with appropriate lock recovery.
> 
> 
> diff --git a/Documentation/filesystems/nfs/reexport.rst b/Documentation/filesystems/nfs/reexport.rst
> index ff9ae4a46530..044be965d75e 100644
> --- a/Documentation/filesystems/nfs/reexport.rst
> +++ b/Documentation/filesystems/nfs/reexport.rst
> @@ -26,9 +26,13 @@ Reboot recovery
>  ---------------
>  
>  The NFS protocol's normal reboot recovery mechanisms don't work for the
> -case when the reexport server reboots.  Clients will lose any locks
> -they held before the reboot, and further IO will result in errors.
> -Closing and reopening files should clear the errors.
> +case when the reexport server reboots because the source server has not
> +rebooted, and so it is not in grace.  Since the source server is not in
> +grace, it cannot offer any guarantees that the file won't have been
> +changed between the locks getting lost and any attempt to recover them.
> +The same applies to delegations and any associated locks.  Clients are
> +not allowed to get file locks or delegations from a reexport server, any
> +attempts will fail with operation not supported.
>  
>  Filehandle limits
>  -----------------
> diff --git a/fs/nfs/export.c b/fs/nfs/export.c
> index be686b8e0c54..e9c233b6fd20 100644
> --- a/fs/nfs/export.c
> +++ b/fs/nfs/export.c
> @@ -154,5 +154,6 @@ const struct export_operations nfs_export_ops = {
>  		 EXPORT_OP_CLOSE_BEFORE_UNLINK	|
>  		 EXPORT_OP_REMOTE_FS		|
>  		 EXPORT_OP_NOATOMIC_ATTR	|
> -		 EXPORT_OP_FLUSH_ON_CLOSE,
> +		 EXPORT_OP_FLUSH_ON_CLOSE	|
> +		 EXPORT_OP_NOLOCKS,
>  };
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index b42e2ab7a042..f0fb6ca4b70c 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -6000,6 +6000,15 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
>  	if (!nf)
>  		return ERR_PTR(-EAGAIN);
>  
> +	/*
> +	 * File delegations and associated locks cannot be recovered if the
> +	 * export is from an NFS proxy server.
> +	 */
> +	if (exportfs_cannot_lock(nf->nf_file->f_path.mnt->mnt_sb->s_export_op)) {
> +		nfsd_file_put(nf);
> +		return ERR_PTR(-EOPNOTSUPP);
> +	}
> +
>  	spin_lock(&state_lock);
>  	spin_lock(&fp->fi_lock);
>  	if (nfs4_delegation_exists(clp, fp))
> @@ -8140,6 +8149,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  	status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
>  	if (status != nfs_ok)
>  		return status;
> +	if (exportfs_cannot_lock(cstate->current_fh.fh_dentry->d_sb->s_export_op)) {
> +		status = nfserr_notsupp;
> +		goto out;
> +	}
>  
>  	if (lock->lk_is_new) {
>  		if (nfsd4_has_session(cstate))
> @@ -8479,6 +8492,11 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  		status = nfserr_lock_range;
>  		goto put_stateid;
>  	}
> +	if (exportfs_cannot_lock(nf->nf_file->f_path.mnt->mnt_sb->s_export_op)) {
> +		status = nfserr_notsupp;
> +		goto put_file;
> +	}
> +
>  	file_lock = locks_alloc_lock();
>  	if (!file_lock) {
>  		dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
> diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
> index 4cc8801e50e3..ca6c605072c7 100644
> --- a/include/linux/exportfs.h
> +++ b/include/linux/exportfs.h
> @@ -259,10 +259,22 @@ struct export_operations {
>  						  atomic attribute updates
>  						*/
>  #define EXPORT_OP_FLUSH_ON_CLOSE	(0x20) /* fs flushes file data on close */
> -#define EXPORT_OP_ASYNC_LOCK		(0x40) /* fs can do async lock request */
> +#define EXPORT_OP_NOLOCKS		(0x40) /* no file locking support */
>  	unsigned long	flags;
>  };
>  
> +/**
> + * exportfs_cannot_lock() - check if export implements file locking
> + * @export_ops:	the nfs export operations to check
> + *
> + * Returns true if the export does not support file locking.
> + */
> +static inline bool
> +exportfs_cannot_lock(const struct export_operations *export_ops)
> +{
> +	return export_ops->flags & EXPORT_OP_NOLOCKS;
> +}
> +
>  extern int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
>  				    int *max_len, struct inode *parent,
>  				    int flags);


Aside from the question about NLM, this looks good:

Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>





[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux