NFS: make sure lock/nolock overriding local_lock mount option
authorChen Hanxiao <chenhx.fnst@fujitsu.com>
Tue, 2 Apr 2024 10:33:55 +0000 (18:33 +0800)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 20 May 2024 15:10:27 +0000 (11:10 -0400)
Currently, mount option lock/nolock and local_lock option
may override NFS_MOUNT_LOCAL_FLOCK NFS_MOUNT_LOCAL_FCNTL flags
when passing in different order:

mount -o vers=3,local_lock=all,lock:
local_lock=none

mount -o vers=3,lock,local_lock=all:
local_lock=all

This patch will let lock/nolock override local_lock option
as nfs(5) suggested.

Signed-off-by: Chen Hanxiao <chenhx.fnst@fujitsu.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/fs_context.c
fs/nfs/internal.h
fs/nfs/super.c

index d0a0956f8a13462ab305e18c437719b0ed612158..ec93306b7e79d4d0503b4e6a2e1d5d6a1a0a2067 100644 (file)
@@ -600,9 +600,11 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
                break;
        case Opt_lock:
                if (result.negated) {
+                       ctx->lock_status = NFS_LOCK_NOLOCK;
                        ctx->flags |= NFS_MOUNT_NONLM;
                        ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
                } else {
+                       ctx->lock_status = NFS_LOCK_LOCK;
                        ctx->flags &= ~NFS_MOUNT_NONLM;
                        ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
                }
index 06253695fe53f01708aed390004cbbd9651c5d57..dc0693b3d2144fca01af0893e1058a6885f1e825 100644 (file)
@@ -112,6 +112,7 @@ struct nfs_fs_context {
        unsigned short          protofamily;
        unsigned short          mountfamily;
        bool                    has_sec_mnt_opts;
+       int                     lock_status;
 
        struct {
                union {
@@ -153,6 +154,12 @@ struct nfs_fs_context {
        } clone_data;
 };
 
+enum nfs_lock_status {
+       NFS_LOCK_NOT_SET        = 0,
+       NFS_LOCK_LOCK           = 1,
+       NFS_LOCK_NOLOCK         = 2,
+};
+
 #define nfs_errorf(fc, fmt, ...) ((fc)->log.log ?              \
        errorf(fc, fmt, ## __VA_ARGS__) :                       \
        ({ dprintk(fmt "\n", ## __VA_ARGS__); }))
index dc03f98f7616a8ba4f7c4d65cbfec0aabe98f942..cbbd4866b0b7a41261042faf1b43344166208978 100644 (file)
@@ -901,6 +901,16 @@ static struct nfs_server *nfs_try_mount_request(struct fs_context *fc)
        rpc_authflavor_t authlist[NFS_MAX_SECFLAVORS];
        unsigned int authlist_len = ARRAY_SIZE(authlist);
 
+       /* make sure 'nolock'/'lock' override the 'local_lock' mount option */
+       if (ctx->lock_status) {
+               if (ctx->lock_status == NFS_LOCK_NOLOCK) {
+                       ctx->flags |= NFS_MOUNT_NONLM;
+                       ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
+               } else {
+                       ctx->flags &= ~NFS_MOUNT_NONLM;
+                       ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
+               }
+       }
        status = nfs_request_mount(fc, ctx->mntfh, authlist, &authlist_len);
        if (status)
                return ERR_PTR(status);