smb: client: introduce reparse mount option
authorPaulo Alcantara <pc@manguebit.com>
Sun, 21 Jan 2024 16:28:21 +0000 (13:28 -0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 May 2024 14:22:47 +0000 (16:22 +0200)
[ Upstream commit eb90e8ecb2b54ac1af51e28596e0ef7ba351476d ]

Allow the user to create special files and symlinks by choosing
between WSL and NFS reparse points via 'reparse={nfs,wsl}' mount
options.  If unset or 'reparse=default', the client will default to
creating them via NFS reparse points.

Creating WSL reparse points isn't supported yet, so simply return
error when attempting to mount with 'reparse=wsl' for now.

Signed-off-by: Paulo Alcantara <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/smb/client/cifsglob.h
fs/smb/client/connect.c
fs/smb/client/fs_context.c
fs/smb/client/fs_context.h

index fdadda4024f46ac9922c3c4f9323dcbcf79bb2ca..08540541046c12d06cdc4616d1f58690333d0075 100644 (file)
@@ -153,6 +153,12 @@ enum securityEnum {
        Kerberos,               /* Kerberos via SPNEGO */
 };
 
+enum cifs_reparse_type {
+       CIFS_REPARSE_TYPE_NFS,
+       CIFS_REPARSE_TYPE_WSL,
+       CIFS_REPARSE_TYPE_DEFAULT = CIFS_REPARSE_TYPE_NFS,
+};
+
 struct session_key {
        unsigned int len;
        char *response;
index e28f011f11d6c1b0dd1bd5c6b0b39103e5254960..deba1cfd1180170df974685666a50ee0d5c540a7 100644 (file)
@@ -2805,6 +2805,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
                return 0;
        if (old->ctx->closetimeo != new->ctx->closetimeo)
                return 0;
+       if (old->ctx->reparse_type != new->ctx->reparse_type)
+               return 0;
 
        return 1;
 }
index f119035a827250b1dffa57f354283f0b2ea39ea8..535885fbdf51dbc4d381c793aced7f6d7d3a6f7a 100644 (file)
@@ -175,6 +175,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
        fsparam_string("vers", Opt_vers),
        fsparam_string("sec", Opt_sec),
        fsparam_string("cache", Opt_cache),
+       fsparam_string("reparse", Opt_reparse),
 
        /* Arguments that should be ignored */
        fsparam_flag("guest", Opt_ignore),
@@ -297,6 +298,35 @@ cifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_conte
        return 0;
 }
 
+static const match_table_t reparse_flavor_tokens = {
+       { Opt_reparse_default,  "default" },
+       { Opt_reparse_nfs,      "nfs" },
+       { Opt_reparse_wsl,      "wsl" },
+       { Opt_reparse_err,      NULL },
+};
+
+static int parse_reparse_flavor(struct fs_context *fc, char *value,
+                               struct smb3_fs_context *ctx)
+{
+       substring_t args[MAX_OPT_ARGS];
+
+       switch (match_token(value, reparse_flavor_tokens, args)) {
+       case Opt_reparse_default:
+               ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;
+               break;
+       case Opt_reparse_nfs:
+               ctx->reparse_type = CIFS_REPARSE_TYPE_NFS;
+               break;
+       case Opt_reparse_wsl:
+               cifs_errorf(fc, "unsupported reparse= option: %s\n", value);
+               return 1;
+       default:
+               cifs_errorf(fc, "bad reparse= option: %s\n", value);
+               return 1;
+       }
+       return 0;
+}
+
 #define DUP_CTX_STR(field)                                             \
 do {                                                                   \
        if (ctx->field) {                                               \
@@ -1595,6 +1625,10 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
        case Opt_rdma:
                ctx->rdma = true;
                break;
+       case Opt_reparse:
+               if (parse_reparse_flavor(fc, param->string, ctx))
+                       goto cifs_parse_mount_err;
+               break;
        }
        /* case Opt_ignore: - is ignored as expected ... */
 
@@ -1683,6 +1717,7 @@ int smb3_init_fs_context(struct fs_context *fc)
        ctx->backupgid_specified = false; /* no backup intent for a group */
 
        ctx->retrans = 1;
+       ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;
 
 /*
  *     short int override_uid = -1;
index 369a3fea1dfe0b7f6bb5c2d5dd993a08fbfa2a12..e77ee81846b31d73981fe758f43ee942d00cf065 100644 (file)
@@ -41,6 +41,13 @@ enum {
        Opt_cache_err
 };
 
+enum cifs_reparse_parm {
+       Opt_reparse_default,
+       Opt_reparse_nfs,
+       Opt_reparse_wsl,
+       Opt_reparse_err
+};
+
 enum cifs_sec_param {
        Opt_sec_krb5,
        Opt_sec_krb5i,
@@ -149,6 +156,7 @@ enum cifs_param {
        Opt_vers,
        Opt_sec,
        Opt_cache,
+       Opt_reparse,
 
        /* Mount options to be ignored */
        Opt_ignore,
@@ -275,6 +283,7 @@ struct smb3_fs_context {
        char *leaf_fullpath;
        struct cifs_ses *dfs_root_ses;
        bool dfs_automount:1; /* set for dfs automount only */
+       enum cifs_reparse_type reparse_type;
 };
 
 extern const struct fs_parameter_spec smb3_fs_parameters[];