smb: client: introduce reparse mount option
authorPaulo Alcantara <pc@manguebit.com>
Sun, 21 Jan 2024 16:28:21 +0000 (13:28 -0300)
committerSteve French <stfrench@microsoft.com>
Mon, 11 Mar 2024 00:33:54 +0000 (19:33 -0500)
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>
fs/smb/client/cifsglob.h
fs/smb/client/connect.c
fs/smb/client/fs_context.c
fs/smb/client/fs_context.h

index 20d3243b74492899a88337753622d1e73c5afb7c..14359cb14af4c9ba0d372b5ab10dce70fec2d0ac 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 ac9595504f4b11fa066a6516f034bff8bc09d56b..5d82921d63d172f3968fdde22954258d1bc58580 100644 (file)
@@ -2803,6 +2803,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 415e87635d5aab3f217146fa3348b822c37090c8..9f729617fa2087dc055bfa8774b8171eddfe6ceb 100644 (file)
@@ -174,6 +174,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),
@@ -296,6 +297,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) {                                               \
@@ -1566,6 +1596,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 ... */
 
@@ -1652,6 +1686,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 182ce11cbe9362eccf73eebadcdcfc2ee7ac7988..1f09754977e7ccdfaa029a078de7d6cf27d22b16 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,
@@ -148,6 +155,7 @@ enum cifs_param {
        Opt_vers,
        Opt_sec,
        Opt_cache,
+       Opt_reparse,
 
        /* Mount options to be ignored */
        Opt_ignore,
@@ -271,6 +279,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[];