diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/Kconfig | 15 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 9 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 10 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 4 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 114 | ||||
-rw-r--r-- | fs/cifs/smbdirect.c | 16 |
6 files changed, 143 insertions, 25 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index c71971c01c63..687da62daf4e 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -108,14 +108,13 @@ config CIFS_XATTR depends on CIFS help Extended attributes are name:value pairs associated with inodes by - the kernel or by users (see the attr(5) manual page, or visit - <http://acl.bestbits.at/> for details). CIFS maps the name of - extended attributes beginning with the user namespace prefix - to SMB/CIFS EAs. EAs are stored on Windows servers without the - user namespace prefix, but their names are seen by Linux cifs clients - prefaced by the user namespace prefix. The system namespace - (used by some filesystems to store ACLs) is not supported at - this time. + the kernel or by users (see the attr(5) manual page for details). + CIFS maps the name of extended attributes beginning with the user + namespace prefix to SMB/CIFS EAs. EAs are stored on Windows + servers without the user namespace prefix, but their names are + seen by Linux cifs clients prefaced by the user namespace prefix. + The system namespace (used by some filesystems to store ACLs) is + not supported at this time. If unsure, say Y. diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index c7a863219fa3..e35e711db68e 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -128,6 +128,10 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon) seq_puts(m, " type: CDROM "); else seq_printf(m, " type: %d ", dev_type); + if (tcon->seal) + seq_printf(m, " Encrypted"); + if (tcon->unix_ext) + seq_printf(m, " POSIX Extensions"); if (tcon->ses->server->ops->dump_share_caps) tcon->ses->server->ops->dump_share_caps(m, tcon); @@ -246,7 +250,10 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) atomic_read(&server->smbd_conn->mr_used_count)); skip_rdma: #endif - seq_printf(m, "\nNumber of credits: %d", server->credits); + seq_printf(m, "\nNumber of credits: %d Dialect 0x%x", + server->credits, server->dialect); + if (server->sign) + seq_printf(m, " signed"); i++; list_for_each(tmp2, &server->smb_ses_list) { ses = list_entry(tmp2, struct cifs_ses, diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index a7be591d8e18..32cdea67bbfd 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1239,9 +1239,11 @@ cifs_init_request_bufs(void) cifs_dbg(VFS, "CIFSMaxBufSize %d 0x%x\n", CIFSMaxBufSize, CIFSMaxBufSize); */ - cifs_req_cachep = kmem_cache_create("cifs_request", + cifs_req_cachep = kmem_cache_create_usercopy("cifs_request", CIFSMaxBufSize + max_hdr_size, 0, - SLAB_HWCACHE_ALIGN, NULL); + SLAB_HWCACHE_ALIGN, 0, + CIFSMaxBufSize + max_hdr_size, + NULL); if (cifs_req_cachep == NULL) return -ENOMEM; @@ -1267,9 +1269,9 @@ cifs_init_request_bufs(void) more SMBs to use small buffer alloc and is still much more efficient to alloc 1 per page off the slab compared to 17K (5page) alloc of large cifs buffers even when page debugging is on */ - cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", + cifs_sm_req_cachep = kmem_cache_create_usercopy("cifs_small_rq", MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN, - NULL); + 0, MAX_CIFS_SMALL_BUFFER_SIZE, NULL); if (cifs_sm_req_cachep == NULL) { mempool_destroy(cifs_req_poolp); kmem_cache_destroy(cifs_req_cachep); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4e0922d24eb2..9ceebf30eb22 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -6343,9 +6343,7 @@ SetEARetry: pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_EA); - parm_data = - (struct fealist *) (((char *) &pSMB->hdr.Protocol) + - offset); + parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset; pSMB->ParameterOffset = cpu_to_le16(param_offset); pSMB->DataOffset = cpu_to_le16(offset); pSMB->SetupCount = 1; diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 6eb9f9691ed4..2a2b34ccaf49 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -192,6 +192,35 @@ struct smb2_symlink_err_rsp { __u8 PathBuffer[0]; } __packed; +/* SMB 3.1.1 and later dialects. See MS-SMB2 section 2.2.2.1 */ +struct smb2_error_context_rsp { + __le32 ErrorDataLength; + __le32 ErrorId; + __u8 ErrorContextData; /* ErrorDataLength long array */ +} __packed; + +/* Defines for Type field below (see MS-SMB2 2.2.2.2.2.1) */ +#define MOVE_DST_IPADDR_V4 cpu_to_le32(0x00000001) +#define MOVE_DST_IPADDR_V6 cpu_to_le32(0x00000002) + +struct move_dst_ipaddr { + __le32 Type; + __u32 Reserved; + __u8 address[16]; /* IPv4 followed by 12 bytes rsvd or IPv6 address */ +} __packed; + +struct share_redirect_error_context_rsp { + __le32 StructureSize; + __le32 NotificationType; + __le32 ResourceNameOffset; + __le32 ResourceNameLength; + __le16 Flags; + __le16 TargetType; + __le32 IPAddrCount; + struct move_dst_ipaddr IpAddrMoveList[0]; + /* __u8 ResourceName[] */ /* Name of share as counted Unicode string */ +} __packed; + #define SMB2_CLIENT_GUID_SIZE 16 struct smb2_negotiate_req { @@ -320,7 +349,9 @@ struct smb2_logoff_rsp { } __packed; /* Flags/Reserved for SMB3.1.1 */ -#define SMB2_SHAREFLAG_CLUSTER_RECONNECT 0x0001 +#define SMB2_TREE_CONNECT_FLAG_CLUSTER_RECONNECT cpu_to_le16(0x0001) +#define SMB2_TREE_CONNECT_FLAG_REDIRECT_TO_OWNER cpu_to_le16(0x0002) +#define SMB2_TREE_CONNECT_FLAG_EXTENSION_PRESENT cpu_to_le16(0x0004) struct smb2_tree_connect_req { struct smb2_sync_hdr sync_hdr; @@ -331,6 +362,82 @@ struct smb2_tree_connect_req { __u8 Buffer[1]; /* variable length */ } __packed; +/* See MS-SMB2 section 2.2.9.2 */ +/* Context Types */ +#define SMB2_RESERVED_TREE_CONNECT_CONTEXT_ID 0x0000 +#define SMB2_REMOTED_IDENTITY_TREE_CONNECT_CONTEXT_ID cpu_to_le16(0x0001) + +struct tree_connect_contexts { + __le16 ContextType; + __le16 DataLength; + __le32 Reserved; + __u8 Data[0]; +} __packed; + +/* Remoted identity tree connect context structures - see MS-SMB2 2.2.9.2.1 */ +struct smb3_blob_data { + __le16 BlobSize; + __u8 BlobData[0]; +} __packed; + +/* Valid values for Attr */ +#define SE_GROUP_MANDATORY 0x00000001 +#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002 +#define SE_GROUP_ENABLED 0x00000004 +#define SE_GROUP_OWNER 0x00000008 +#define SE_GROUP_USE_FOR_DENY_ONLY 0x00000010 +#define SE_GROUP_INTEGRITY 0x00000020 +#define SE_GROUP_INTEGRITY_ENABLED 0x00000040 +#define SE_GROUP_RESOURCE 0x20000000 +#define SE_GROUP_LOGON_ID 0xC0000000 + +/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */ + +struct sid_array_data { + __le16 SidAttrCount; + /* SidAttrList - array of sid_attr_data structs */ +} __packed; + +struct luid_attr_data { + +} __packed; + +/* + * struct privilege_data is the same as BLOB_DATA - see MS-SMB2 2.2.9.2.1.5 + * but with size of LUID_ATTR_DATA struct and BlobData set to LUID_ATTR DATA + */ + +struct privilege_array_data { + __le16 PrivilegeCount; + /* array of privilege_data structs */ +} __packed; + +struct remoted_identity_tcon_context { + __le16 TicketType; /* must be 0x0001 */ + __le16 TicketSize; /* total size of this struct */ + __le16 User; /* offset to SID_ATTR_DATA struct with user info */ + __le16 UserName; /* offset to null terminated Unicode username string */ + __le16 Domain; /* offset to null terminated Unicode domain name */ + __le16 Groups; /* offset to SID_ARRAY_DATA struct with group info */ + __le16 RestrictedGroups; /* similar to above */ + __le16 Privileges; /* offset to PRIVILEGE_ARRAY_DATA struct */ + __le16 PrimaryGroup; /* offset to SID_ARRAY_DATA struct */ + __le16 Owner; /* offset to BLOB_DATA struct */ + __le16 DefaultDacl; /* offset to BLOB_DATA struct */ + __le16 DeviceGroups; /* offset to SID_ARRAY_DATA struct */ + __le16 UserClaims; /* offset to BLOB_DATA struct */ + __le16 DeviceClaims; /* offset to BLOB_DATA struct */ + __u8 TicketInfo[0]; /* variable length buf - remoted identity data */ +} __packed; + +struct smb2_tree_connect_req_extension { + __le32 TreeConnectContextOffset; + __le16 TreeConnectContextCount; + __u8 Reserved[10]; + __u8 PathName[0]; /* variable sized array */ + /* followed by array of TreeConnectContexts */ +} __packed; + struct smb2_tree_connect_rsp { struct smb2_hdr hdr; __le16 StructureSize; /* Must be 16 */ @@ -365,7 +472,8 @@ struct smb2_tree_connect_rsp { #define SHI1005_FLAGS_ENABLE_HASH_V1 0x00002000 #define SHI1005_FLAGS_ENABLE_HASH_V2 0x00004000 #define SHI1005_FLAGS_ENCRYPT_DATA 0x00008000 -#define SHI1005_FLAGS_ALL 0x0000FF33 +#define SMB2_SHAREFLAG_IDENTITY_REMOTING 0x00040000 /* 3.1.1 */ +#define SHI1005_FLAGS_ALL 0x0004FF33 /* Possible share capabilities */ #define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008) /* all dialects */ @@ -373,6 +481,7 @@ struct smb2_tree_connect_rsp { #define SMB2_SHARE_CAP_SCALEOUT cpu_to_le32(0x00000020) /* 3.0 */ #define SMB2_SHARE_CAP_CLUSTER cpu_to_le32(0x00000040) /* 3.0 */ #define SMB2_SHARE_CAP_ASYMMETRIC cpu_to_le32(0x00000080) /* 3.02 */ +#define SMB2_SHARE_CAP_REDIRECT_TO_OWNER cpu_to_le32(0x00000100) /* 3.1.1 */ struct smb2_tree_disconnect_req { struct smb2_sync_hdr sync_hdr; @@ -556,6 +665,7 @@ struct create_context { #define SMB2_LEASE_WRITE_CACHING cpu_to_le32(0x04) #define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS cpu_to_le32(0x02) +#define SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET cpu_to_le32(0x00000004) #define SMB2_LEASE_KEY_SIZE 16 diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index 5130492847eb..91710eb571fb 100644 --- a/fs/cifs/smbdirect.c +++ b/fs/cifs/smbdirect.c @@ -217,9 +217,10 @@ static void smbd_destroy_rdma_work(struct work_struct *work) spin_unlock_irqrestore( &info->reassembly_queue_lock, flags); put_receive_buffer(info, response); - } + } else + spin_unlock_irqrestore(&info->reassembly_queue_lock, flags); } while (response); - spin_unlock_irqrestore(&info->reassembly_queue_lock, flags); + info->reassembly_data_length = 0; log_rdma_event(INFO, "free receive buffers\n"); @@ -1934,15 +1935,16 @@ again: * No need to lock if we are not at the * end of the queue */ - if (!queue_length) + if (queue_length) + list_del(&response->list); + else { spin_lock_irq( &info->reassembly_queue_lock); - list_del(&response->list); - queue_removed++; - if (!queue_length) + list_del(&response->list); spin_unlock_irq( &info->reassembly_queue_lock); - + } + queue_removed++; info->count_reassembly_queue--; info->count_dequeue_reassembly_queue++; put_receive_buffer(info, response); |