Add SMB3.11 mount option synonym for new dialect
Subsystems (3)
PATCH 1/5 Add SMB3.11 mount option synonym for new dialect
From: Steve French <[email protected]>
Most people think of SMB 3.1.1 as SMB version 3.11 so add synonym for "vers=3.1.1" of "vers=3.11" on mount.
Also make sure that unlike SMB3.0 and 3.02 we don't send validate negotiate on mount (it is handled by negotiate contexts) - add list of SMB3.11 specific functions (distinct from 3.0 dialect).
--- fs/cifs/cifsglob.h | 3 +- fs/cifs/connect.c | 3 +- fs/cifs/smb2ops.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-)
fs/cifs/cifsglob.h +2 -1
@@ -1622,6 +1622,7 @@ extern struct smb_version_values smb30_values;/*extern struct smb_version_operations smb302_operations;*/ /* not needed yet */ extern struct smb_version_values smb302_values;#define SMB311_VERSION_STRING "3.1.1" -/*extern struct smb_version_operations smb311_operations;*/ /* not needed yet */ +#define ALT_SMB311_VERSION_STRING "3.11" +extern struct smb_version_operations smb311_operations;extern struct smb_version_values smb311_values;#endif /* _CIFS_GLOB_H */
fs/cifs/connect.c +2 -1
@@ -282,6 +282,7 @@ static const match_table_t cifs_smb_version_tokens = { { Smb_302, SMB302_VERSION_STRING }, #ifdef CONFIG_CIFS_SMB311 { Smb_311, SMB311_VERSION_STRING }, + { Smb_311, ALT_SMB311_VERSION_STRING }, #endif /* SMB311 */ { Smb_version_err, NULL } };
@@ -1139,7 +1140,7 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)break ;#ifdef CONFIG_CIFS_SMB311 case Smb_311: - vol->ops = &smb30_operations;/* currently identical with 3.0 */ + vol->ops = &smb311_operations; vol->vals = &smb311_values;break ;#endif /* SMB311 */
fs/cifs/smb2ops.c +86 -0
92 lines not on this page · raw message
Signature · 1 line
2.1.4
A message that is not in the archive (sent off-list or not yet received): 1435534570-10864-1-git-send-email-steve.french-7I+n7zu2hftEKMMhf/[email protected]
PATCH 2/5 Add reflink copy over SMB3.11 with new FSCTL_DUPLICATE_EXTENTS
Getting fantastic copy performance with cp --reflink over SMB3.11 using the new FSCTL_DUPLICATE_EXTENTS.
This FSCTL was added in the SMB3.11 dialect (testing was against REFS file system) so have put it as a 3.11 protocol specific operation ("vers=3.1.1" on the mount). Tested at the SMB3 plugfest in Redmond.
It depends on the new FS Attribute (BLOCK_REFCOUNTING) which is used to advertise support for the ability to do this ioctl (if you can support multiple files pointing to the same block than this refcounting ability or equivalent is needed to support the new reflink-like duplicate extent SMB3 ioctl.
--- fs/cifs/cifsglob.h | 3 +++ fs/cifs/cifspdu.h | 2 ++ fs/cifs/ioctl.c | 16 +++++++++++++--- fs/cifs/smb2ops.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/cifs/smb2pdu.h | 8 ++++++++ fs/cifs/smbfsctl.h | 1 + 6 files changed, 75 insertions(+), 3 deletions(-)
fs/cifs/cifsglob.h +3 -0
@@ -390,6 +390,9 @@ struct smb_version_operations {int (*clone_range)(const unsigned int ,struct cifsFileInfo *src_file,struct cifsFileInfo *target_file,u64 src_off,u64 len,u64 dest_off); +int (*duplicate_extents)(const unsigned int ,struct cifsFileInfo *src, +struct cifsFileInfo *target_file,u64 src_off,u64 len, +u64 dest_off);int (*validate_negotiate)(const unsigned int ,struct cifs_tcon *); ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *, const unsigned char *, const unsigned char *, char *,
fs/cifs/cifspdu.h +2 -0
@@ -2255,6 +2255,8 @@ typedef struct {/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */ +#define FILE_SUPPORTS_SPARSE_VDL 0x10000000/* faster nonsparse extend */ +#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000/* allow ioctl dup extents */ #define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000#define FILE_SUPPORTS_USN_JOURNAL 0x02000000#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
fs/cifs/ioctl.c +13 -3
@@ -31,12 +31,14 @@#include "cifsproto.h" #include "cifs_debug.h" #include "cifsfs.h" +#include <linux/btrfs.h> #define CIFS_IOCTL_MAGIC 0xCF#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)static long cifs_ioctl_clone (unsigned int xid,struct file *dst_file, -unsigned long srcfd,u64 off,u64 len,u64 destoff) +unsigned long srcfd,u64 off,u64 len,u64 destoff, +bool dup_extents) {int rc;struct cifsFileInfo *smb_file_target = dst_file->private_data;
@@ -109,9 +111,14 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file,truncate_inode_pages_range (&target_inode->i_data, destoff,PAGE_CACHE_ALIGN (destoff + len)-1 ); -if (target_tcon->ses->server->ops->clone_range) +if (dup_extents && target_tcon->ses->server->ops->duplicate_extents) + rc = target_tcon->ses->server->ops->duplicate_extents (xid, + smb_file_src, smb_file_target, off, len, destoff); +else if (!dup_extents && target_tcon->ses->server->ops->clone_range) rc = target_tcon->ses->server->ops->clone_range (xid, smb_file_src, smb_file_target, off, len, destoff); +else + rc = -EOPNOTSUPP ;/* force revalidate of size and timestamps of target file now that target is updated on the server */
@@ -205,7 +212,10 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) }break ;case CIFS_IOC_COPYCHUNK_FILE : - rc =cifs_ioctl_clone (xid, filep, arg,0 ,0 ,0 ); + rc =cifs_ioctl_clone (xid, filep, arg,0 ,0 ,0 , false); +break ; +case BTRFS_IOC_CLONE : + rc =cifs_ioctl_clone (xid, filep, arg,0 ,0 ,0 , true);break ;default :cifs_dbg (FYI ,"unsupported ioctl\n" );
fs/cifs/smb2ops.c +48 -0
60 lines not on this page · raw message
fs/cifs/smb2pdu.h +8 -0
@@ -654,6 +654,14 @@ struct compress_ioctl {__le16 CompressionState;/* See cifspdu.h for possible flag values */ } __packed; +struct duplicate_extents_to_file { +__u64 PersistentFileHandle;/* source file handle, opaque endianness */ +__u64 VolatileFileHandle; +__le64 SourceFileOffset; +__le64 TargetFileOffset; +__le64 ByteCount;/* Bytes to be copied */ +} __packed; +struct smb2_ioctl_req {struct smb2_hdr hdr;__le16 StructureSize;/* Must be 57 */
fs/cifs/smbfsctl.h +1 -0
@@ -78,6 +78,7 @@#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF/* BB add struct */ #define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134/* BB add struct */ #define FSCTL_FILE_LEVEL_TRIM 0x00098208/* BB add struct */ +#define FSCTL_DUPLICATE_EXTENTS_TO_FILE 0x00098344#define FSCTL_SIS_LINK_FILES 0x0009C104#define FSCTL_PIPE_PEEK 0x0011400C/* BB add struct */ #define FSCTL_PIPE_TRANSCEIVE 0x0011C017/* BB add struct */
Signature · 1 line
2.1.4
PATCH 4/5 Add ioctl to set integrity
In reply to a message not in the archiveFrom: Steve French <[email protected]>
set integrity increases reliability of files stored on SMB3 servers. Add ioctl to allow setting this on files on SMB3 and later mounts.
--- fs/cifs/cifsglob.h | 2 ++ fs/cifs/ioctl.c | 11 +++++++++++ fs/cifs/smb2ops.c | 24 ++++++++++++++++++++++++ fs/cifs/smb2pdu.h | 1 + 4 files changed, 38 insertions(+)
fs/cifs/cifsglob.h +2 -0
@@ -372,6 +372,8 @@ struct smb_version_operations {void (*new_lease_key)(struct cifs_fid *);int (*generate_signingkey)(struct cifs_ses *);int (*calc_signature)(struct smb_rqst *,struct TCP_Server_Info *); +int (*set_integrity)(const unsigned int ,struct cifs_tcon *tcon, +struct cifsFileInfo *src_file);int (*query_mf_symlink)(unsigned int ,struct cifs_tcon *,struct cifs_sb_info *,const unsigned char *,char *,unsigned int *);
fs/cifs/ioctl.c +11 -0
@@ -35,6 +35,7 @@#define CIFS_IOCTL_MAGIC 0xCF#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int) +#define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4) static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, unsigned long srcfd, u64 off, u64 len, u64 destoff,
@@ -217,6 +218,16 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)case BTRFS_IOC_CLONE : rc =cifs_ioctl_clone (xid, filep, arg,0 ,0 ,0 , true);break ; +case CIFS_IOC_SET_INTEGRITY : +if (pSMBFile ==NULL ) +break ; + tcon =tlink_tcon (pSMBFile->tlink); +if (tcon->ses->server->ops->set_integrity) + rc = tcon->ses->server->ops->set_integrity (xid, + tcon, pSMBFile); +else + rc = -EOPNOTSUPP ; +break ;default :cifs_dbg (FYI ,"unsupported ioctl\n" );break ;
fs/cifs/smb2ops.c +24 -0
@@ -862,6 +862,28 @@ smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, }static int +smb3_set_integrity (const unsigned int xid,struct cifs_tcon *tcon, +struct cifsFileInfo *cfile) +{ +struct fsctl_set_integrity_information_req integr_info; +char *retbuf =NULL ; +unsigned int ret_data_len; + + integr_info.ChecksumAlgorithm =cpu_to_le16 (CHECKSUM_TYPE_UNCHANGED ); + integr_info.Flags =0 ; + integr_info.Reserved =0 ; + +return SMB2_ioctl (xid, tcon, cfile->fid.persistent_fid, + cfile->fid.volatile_fid, +FSCTL_SET_INTEGRITY_INFORMATION , + true/* is_fsctl */ , (char *)&integr_info, +sizeof (struct fsctl_set_integrity_information_req ), + (char **)&retbuf, + &ret_data_len); + +} + +static int smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, const char *path, struct cifs_sb_info *cifs_sb, struct cifs_fid *fid, __u16 search_flags,
@@ -1671,6 +1693,7 @@ struct smb_version_operations smb30_operations = { .new_lease_key = smb2_new_lease_key, .generate_signingkey = generate_smb3signingkey, .calc_signature = smb3_calc_signature, + .set_integrity = smb3_set_integrity, .is_read_op = smb21_is_read_op, .set_oplock_level = smb3_set_oplock_level, .create_lease_buf = smb3_create_lease_buf,
@@ -1756,6 +1779,7 @@ struct smb_version_operations smb311_operations = { .new_lease_key = smb2_new_lease_key, .generate_signingkey = generate_smb3signingkey, .calc_signature = smb3_calc_signature, + .set_integrity = smb3_set_integrity, .is_read_op = smb21_is_read_op, .set_oplock_level = smb3_set_oplock_level, .create_lease_buf = smb3_create_lease_buf,
fs/cifs/smb2pdu.h +1 -0
@@ -638,6 +638,7 @@ struct fsctl_get_integrity_information_rsp {/* Integrity ChecksumAlgorithm choices for above */ #define CHECKSUM_TYPE_NONE 0x0000#define CHECKSUM_TYPE_CRC64 0x0002 +#define CHECKSUM_TYPE_UNCHANGED 0xFFFF/* set only */ /* Integrity flags for above */ #define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001
Signature · 1 line
2.1.4
PATCH 5/5 Update negotiate protocol for SMB3.11 dialect
In reply to a message not in the archiveFrom: Steve French <[email protected]>
Send negotiate contexts when SMB3.11 dialect is negotiated (ie the preauth and the encryption contexts) and Initialize SMB3.11 preauth negotiate context salt to random bytes
Followon patch will update session setup and tree connect
--- fs/cifs/smb2pdu.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- fs/cifs/smb2pdu.h | 6 +++--- 2 files changed, 60 insertions(+), 5 deletions(-)
fs/cifs/smb2pdu.c +57 -2
@@ -304,6 +304,59 @@ small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,return rc; } +#ifdef CONFIG_CIFS_SMB311 +/* offset is sizeof smb2_negotiate_req - 4 but rounded up to 8 bytes */ +#define OFFSET_OF_NEG_CONTEXT 0x68/* sizeof(struct smb2_negotiate_req) - 4 */ + + +#define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1) +#define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2) + +static void +build_preauth_ctxt (struct smb2_preauth_neg_context *pneg_ctxt) +{ + pneg_ctxt->ContextType =SMB2_PREAUTH_INTEGRITY_CAPABILITIES ; + pneg_ctxt->DataLength =cpu_to_le16 (38 ); + pneg_ctxt->HashAlgorithmCount =cpu_to_le16 (1 ); + pneg_ctxt->SaltLength =cpu_to_le16 (SMB311_SALT_SIZE ); +get_random_bytes (pneg_ctxt->Salt,SMB311_SALT_SIZE ); + pneg_ctxt->HashAlgorithms =SMB2_PREAUTH_INTEGRITY_SHA512 ; +} + +static void +build_encrypt_ctxt (struct smb2_encryption_neg_context *pneg_ctxt) +{ + pneg_ctxt->ContextType =SMB2_ENCRYPTION_CAPABILITIES ; + pneg_ctxt->DataLength =cpu_to_le16 (6 ); + pneg_ctxt->CipherCount =cpu_to_le16 (2 ); + pneg_ctxt->Ciphers[0 ] =SMB2_ENCRYPTION_AES128_GCM ; + pneg_ctxt->Ciphers[1 ] =SMB2_ENCRYPTION_AES128_CCM ; +} + +static void +assemble_neg_contexts (struct smb2_negotiate_req *req) +{ + +/* +4 is to account for the RFC1001 len field */ +char *pneg_ctxt = (char *)req +OFFSET_OF_NEG_CONTEXT +4 ; + +build_preauth_ctxt ((struct smb2_preauth_neg_context *)pneg_ctxt); +/* Add 2 to size to round to 8 byte boundary */ + pneg_ctxt +=2 +sizeof (struct smb2_preauth_neg_context ); +build_encrypt_ctxt ((struct smb2_encryption_neg_context *)pneg_ctxt); + req->NegotiateContextOffset =cpu_to_le32 (OFFSET_OF_NEG_CONTEXT ); + req->NegotiateContextCount =cpu_to_le16 (2 ); +inc_rfc1001_len (req,4 +sizeof (struct smb2_preauth_neg_context ) +2 + +sizeof (struct smb2_encryption_neg_context ));/* calculate hash */ +} +#else +static void assemble_neg_contexts (struct smb2_negotiate_req *req) +{ +return ; +} +#endif /* SMB311 */ + +/* * * SMB2 Worker functions follow:
@@ -363,10 +416,12 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)/* ClientGUID must be zero for SMB2.02 dialect */ if (ses->server->vals->protocol_id ==SMB20_PROT_ID )memset (req->ClientGUID,0 ,SMB2_CLIENT_GUID_SIZE ); -else +else {memcpy (req->ClientGUID, server->client_guid,SMB2_CLIENT_GUID_SIZE ); - +if (ses->server->vals->protocol_id ==SMB311_PROT_ID ) +assemble_neg_contexts (req); + } iov[0 ].iov_base = (char *)req;/* 4 for rfc1002 length field */ iov[0 ].iov_len =get_rfc1002_length (req) +4 ;
fs/cifs/smb2pdu.h +3 -3
@@ -220,7 +220,7 @@ struct smb2_negotiate_req {#define SMB311_SALT_SIZE 32/* Hash Algorithm Types */ -#define SMB2_PREAUTH_INTEGRITY_SHA512 0x0001 +#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001)struct smb2_preauth_neg_context {__le16 ContextType;/* 1 */
@@ -240,8 +240,8 @@ struct smb2_encryption_neg_context {__le16 ContextType;/* 2 */ __le16 DataLength;__le32 Reserved; -__le16 CipherCount;/* 1 for time being, only AES-128-CCM */ -__le16 Ciphers;/* Ciphers[0] since only one used now */ +__le16 CipherCount;/* AES-128-GCM and AES-128-CCM */ +__le16 Ciphers[2 ];/* Ciphers[0] since only one used now */ } __packed;struct smb2_negotiate_rsp {
Signature · 1 line
2.1.4
PATCH 3/5 Add Get/Set Integrity Information structure definitions
In reply to Steve FrenchFrom: Steve French <[email protected]>
--- fs/cifs/smb2pdu.h | 22 ++++++++++++++++++++++ fs/cifs/smbfsctl.h | 2 ++ 2 files changed, 24 insertions(+)
fs/cifs/smb2pdu.h +22 -0
@@ -621,6 +621,28 @@ struct copychunk_ioctl_rsp {__le32 TotalBytesWritten; } __packed; +struct fsctl_set_integrity_information_req { +__le16 ChecksumAlgorithm; +__le16 Reserved; +__le32 Flags; +} __packed; + +struct fsctl_get_integrity_information_rsp { +__le16 ChecksumAlgorithm; +__le16 Reserved; +__le32 Flags; +__le32 ChecksumChunkSizeInBytes; +__le32 ClusterSizeInBytes; +} __packed; + +/* Integrity ChecksumAlgorithm choices for above */ +#define CHECKSUM_TYPE_NONE 0x0000 +#define CHECKSUM_TYPE_CRC64 0x0002 + +/* Integrity flags for above */ +#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001 + +struct validate_negotiate_info_req {__le32 Capabilities;__u8 Guid[SMB2_CLIENT_GUID_SIZE ];
fs/cifs/smbfsctl.h +2 -0
@@ -75,11 +75,13 @@#define FSCTL_QUERY_SPARING_INFO 0x00090138/* BB add struct */ #define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194/* BB add struct */ #define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4/* BB add struct */ +#define FSCTL_GET_INTEGRITY_INFORMATION 0x0009027C#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF/* BB add struct */ #define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134/* BB add struct */ #define FSCTL_FILE_LEVEL_TRIM 0x00098208/* BB add struct */ #define FSCTL_DUPLICATE_EXTENTS_TO_FILE 0x00098344#define FSCTL_SIS_LINK_FILES 0x0009C104 +#define FSCTL_SET_INTEGRITY_INFORMATION 0x0009C280#define FSCTL_PIPE_PEEK 0x0011400C/* BB add struct */ #define FSCTL_PIPE_TRANSCEIVE 0x0011C017/* BB add struct */ /* strange that the number for this op is not sequential with previous op */
Signature · 1 line
2.1.4