smb: client: introduce reparse mount option

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>
This commit is contained in:
Paulo Alcantara 2024-01-21 13:28:21 -03:00 committed by Steve French
parent 71f15c90e7
commit eb90e8ecb2
4 changed files with 52 additions and 0 deletions

View 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;

View 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;
}

View 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;

View 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[];