summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsfs.c5
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/connect.c25
-rw-r--r--fs/cifs/fs_context.c8
-rw-r--r--fs/cifs/fs_context.h2
5 files changed, 43 insertions, 0 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 5d32561ae2ed..f810b25dfeb8 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -638,6 +638,11 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_printf(s, ",multichannel,max_channels=%zu",
tcon->ses->chan_max);
+#ifdef CONFIG_CIFS_SWN_UPCALL
+ if (tcon->use_witness)
+ seq_puts(s, ",witness");
+#endif
+
return 0;
}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index b46809260e79..78438102f091 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1086,6 +1086,9 @@ struct cifs_tcon {
int remap:2;
struct list_head ulist; /* cache update list */
#endif
+#ifdef CONFIG_CIFS_SWN_UPCALL
+ bool use_witness:1; /* use witness protocol */
+#endif
};
/*
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index ec80b6c3e20f..ead1c086b88d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1944,6 +1944,8 @@ cifs_put_tcon(struct cifs_tcon *tcon)
return;
}
+ /* TODO witness unregister */
+
list_del_init(&tcon->tcon_list);
spin_unlock(&cifs_tcp_ses_lock);
@@ -2104,6 +2106,26 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
}
tcon->use_resilient = true;
}
+#ifdef CONFIG_CIFS_SWN_UPCALL
+ tcon->use_witness = false;
+ if (ctx->witness) {
+ if (ses->server->vals->protocol_id >= SMB30_PROT_ID) {
+ if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER) {
+ /* TODO witness register */
+ tcon->use_witness = true;
+ } else {
+ /* TODO: try to extend for non-cluster uses (eg multichannel) */
+ cifs_dbg(VFS, "witness requested on mount but no CLUSTER capability on share\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ }
+ } else {
+ cifs_dbg(VFS, "SMB3 or later required for witness option\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ }
+ }
+#endif
/* If the user really knows what they are doing they can override */
if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
@@ -3856,6 +3878,9 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
ctx->sectype = master_tcon->ses->sectype;
ctx->sign = master_tcon->ses->sign;
ctx->seal = master_tcon->seal;
+#ifdef CONFIG_CIFS_SWN_UPCALL
+ ctx->witness = master_tcon->use_witness;
+#endif
rc = cifs_set_vol_auth(ctx, master_tcon->ses);
if (rc) {
diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c
index 9120d148c5f1..fe5cc60f4393 100644
--- a/fs/cifs/fs_context.c
+++ b/fs/cifs/fs_context.c
@@ -119,6 +119,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
fsparam_flag("modesid", Opt_modesid),
fsparam_flag("rootfs", Opt_rootfs),
fsparam_flag("compress", Opt_compress),
+ fsparam_flag("witness", Opt_witness),
/* Mount options which take numeric value */
fsparam_u32("backupuid", Opt_backupuid),
@@ -1004,6 +1005,13 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
if (cifs_parse_cache_flavor(param->string, ctx) != 0)
goto cifs_parse_mount_err;
break;
+ case Opt_witness:
+#ifndef CONFIG_CIFS_SWN_UPCALL
+ cifs_dbg(VFS, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
+ goto cifs_parse_mount_err;
+#endif
+ ctx->witness = true;
+ break;
case Opt_rootfs:
#ifdef CONFIG_CIFS_ROOT
ctx->rootfs = true;
diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h
index d4a905a80883..aaec8a819d34 100644
--- a/fs/cifs/fs_context.h
+++ b/fs/cifs/fs_context.h
@@ -102,6 +102,7 @@ enum cifs_param {
Opt_rootfs,
Opt_multichannel,
Opt_compress,
+ Opt_witness,
/* Mount options which take numeric value */
Opt_backupuid,
@@ -241,6 +242,7 @@ struct smb3_fs_context {
unsigned int max_channels;
__u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
bool rootfs:1; /* if it's a SMB root file system */
+ bool witness:1; /* use witness protocol */
char *mount_options;
};