Skip to content

Commit 9254c8a

Browse files
Mike Snitzerchucklever
authored andcommitted
nfsd: disallow file locking and delegations for NFSv4 reexport
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. 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@kernel.org> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent fbfdc9f commit 9254c8a

File tree

4 files changed

+40
-5
lines changed

4 files changed

+40
-5
lines changed

Documentation/filesystems/nfs/reexport.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@ Reboot recovery
2626
---------------
2727

2828
The NFS protocol's normal reboot recovery mechanisms don't work for the
29-
case when the reexport server reboots. Clients will lose any locks
30-
they held before the reboot, and further IO will result in errors.
31-
Closing and reopening files should clear the errors.
29+
case when the reexport server reboots because the source server has not
30+
rebooted, and so it is not in grace. Since the source server is not in
31+
grace, it cannot offer any guarantees that the file won't have been
32+
changed between the locks getting lost and any attempt to recover them.
33+
The same applies to delegations and any associated locks. Clients are
34+
not allowed to get file locks or delegations from a reexport server, any
35+
attempts will fail with operation not supported.
3236

3337
Filehandle limits
3438
-----------------

fs/nfs/export.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,5 +154,6 @@ const struct export_operations nfs_export_ops = {
154154
EXPORT_OP_CLOSE_BEFORE_UNLINK |
155155
EXPORT_OP_REMOTE_FS |
156156
EXPORT_OP_NOATOMIC_ATTR |
157-
EXPORT_OP_FLUSH_ON_CLOSE,
157+
EXPORT_OP_FLUSH_ON_CLOSE |
158+
EXPORT_OP_NOLOCKS,
158159
};

fs/nfsd/nfs4state.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6010,6 +6010,15 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
60106010
if (!nf)
60116011
return ERR_PTR(-EAGAIN);
60126012

6013+
/*
6014+
* File delegations and associated locks cannot be recovered if the
6015+
* export is from an NFS proxy server.
6016+
*/
6017+
if (exportfs_cannot_lock(nf->nf_file->f_path.mnt->mnt_sb->s_export_op)) {
6018+
nfsd_file_put(nf);
6019+
return ERR_PTR(-EOPNOTSUPP);
6020+
}
6021+
60136022
spin_lock(&state_lock);
60146023
spin_lock(&fp->fi_lock);
60156024
if (nfs4_delegation_exists(clp, fp))
@@ -8148,6 +8157,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
81488157
status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
81498158
if (status != nfs_ok)
81508159
return status;
8160+
if (exportfs_cannot_lock(cstate->current_fh.fh_dentry->d_sb->s_export_op)) {
8161+
status = nfserr_notsupp;
8162+
goto out;
8163+
}
81518164

81528165
if (lock->lk_is_new) {
81538166
if (nfsd4_has_session(cstate))
@@ -8487,6 +8500,11 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
84878500
status = nfserr_lock_range;
84888501
goto put_stateid;
84898502
}
8503+
if (exportfs_cannot_lock(nf->nf_file->f_path.mnt->mnt_sb->s_export_op)) {
8504+
status = nfserr_notsupp;
8505+
goto put_file;
8506+
}
8507+
84908508
file_lock = locks_alloc_lock();
84918509
if (!file_lock) {
84928510
dprintk("NFSD: %s: unable to allocate lock!\n", __func__);

include/linux/exportfs.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,10 +279,22 @@ struct export_operations {
279279
atomic attribute updates
280280
*/
281281
#define EXPORT_OP_FLUSH_ON_CLOSE (0x20) /* fs flushes file data on close */
282-
#define EXPORT_OP_ASYNC_LOCK (0x40) /* fs can do async lock request */
282+
#define EXPORT_OP_NOLOCKS (0x40) /* no file locking support */
283283
unsigned long flags;
284284
};
285285

286+
/**
287+
* exportfs_cannot_lock() - check if export implements file locking
288+
* @export_ops: the nfs export operations to check
289+
*
290+
* Returns true if the export does not support file locking.
291+
*/
292+
static inline bool
293+
exportfs_cannot_lock(const struct export_operations *export_ops)
294+
{
295+
return export_ops->flags & EXPORT_OP_NOLOCKS;
296+
}
297+
286298
extern int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
287299
int *max_len, struct inode *parent,
288300
int flags);

0 commit comments

Comments
 (0)