diff options
-rw-r--r-- | fs/cifs/cifsfs.c | 5 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/connect.c | 25 | ||||
-rw-r--r-- | fs/cifs/fs_context.c | 8 | ||||
-rw-r--r-- | fs/cifs/fs_context.h | 2 |
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; }; |