diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-19 13:32:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-19 13:32:16 -0400 |
commit | 7e3d2c8210e67ebff472a0b371bb0efb4236ef52 (patch) | |
tree | 534510c301bc6733393281755d24501be41615c5 | |
parent | 7a0d796100daa8e75cda2c166c85d57775704fd4 (diff) | |
parent | 4d6bcba70aeb4a512ead9c9eaf9edc6bbab00b14 (diff) |
Merge tag '5.4-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs updates from Steve French:
"Various cifs/smb3 fixes (including for share deleted cases) and
features including improved encrypted read performance, and various
debugging improvements.
Note that since I am at a test event this week with the Samba team,
and at the annual Storage Developer Conference/SMB3 Plugfest test
event next week a higher than usual number of fixes is expected later
next week as other features in progress get additional testing and
review during these two events"
* tag '5.4-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: (38 commits)
cifs: update internal module version number
cifs: modefromsid: write mode ACE first
cifs: cifsroot: add more err checking
smb3: add missing worker function for SMB3 change notify
cifs: Add support for root file systems
cifs: modefromsid: make room for 4 ACE
smb3: fix potential null dereference in decrypt offload
smb3: fix unmount hang in open_shroot
smb3: allow disabling requesting leases
smb3: improve handling of share deleted (and share recreated)
smb3: display max smb3 requests in flight at any one time
smb3: only offload decryption of read responses if multiple requests
cifs: add a helper to find an existing readable handle to a file
smb3: enable offload of decryption of large reads via mount option
smb3: allow parallelizing decryption of reads
cifs: add a debug macro that prints \\server\share for errors
smb3: fix signing verification of large reads
smb3: allow skipping signature verification for perf sensitive configurations
smb3: add dynamic tracepoints for flush and close
smb3: log warning if CSC policy conflicts with cache mount option
...
-rw-r--r-- | Documentation/filesystems/cifs/cifsroot.txt | 97 | ||||
-rw-r--r-- | fs/cifs/Kconfig | 8 | ||||
-rw-r--r-- | fs/cifs/Makefile | 2 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.h | 67 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifs_ioctl.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 81 | ||||
-rw-r--r-- | fs/cifs/cifsacl.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 28 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 19 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 5 | ||||
-rw-r--r-- | fs/cifs/cifsroot.c | 94 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 2 | ||||
-rw-r--r-- | fs/cifs/connect.c | 152 | ||||
-rw-r--r-- | fs/cifs/dir.c | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 80 | ||||
-rw-r--r-- | fs/cifs/inode.c | 19 | ||||
-rw-r--r-- | fs/cifs/smb2inode.c | 155 | ||||
-rw-r--r-- | fs/cifs/smb2maperror.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 201 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 287 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 2 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 4 | ||||
-rw-r--r-- | fs/cifs/smb2transport.c | 62 | ||||
-rw-r--r-- | fs/cifs/trace.h | 38 | ||||
-rw-r--r-- | fs/cifs/transport.c | 120 | ||||
-rw-r--r-- | include/linux/root_dev.h | 1 |
29 files changed, 1218 insertions, 319 deletions
diff --git a/Documentation/filesystems/cifs/cifsroot.txt b/Documentation/filesystems/cifs/cifsroot.txt new file mode 100644 index 000000000000..0fa1a2c36a40 --- /dev/null +++ b/Documentation/filesystems/cifs/cifsroot.txt | |||
@@ -0,0 +1,97 @@ | |||
1 | Mounting root file system via SMB (cifs.ko) | ||
2 | =========================================== | ||
3 | |||
4 | Written 2019 by Paulo Alcantara <palcantara@suse.de> | ||
5 | Written 2019 by Aurelien Aptel <aaptel@suse.com> | ||
6 | |||
7 | The CONFIG_CIFS_ROOT option enables experimental root file system | ||
8 | support over the SMB protocol via cifs.ko. | ||
9 | |||
10 | It introduces a new kernel command-line option called 'cifsroot=' | ||
11 | which will tell the kernel to mount the root file system over the | ||
12 | network by utilizing SMB or CIFS protocol. | ||
13 | |||
14 | In order to mount, the network stack will also need to be set up by | ||
15 | using 'ip=' config option. For more details, see | ||
16 | Documentation/filesystems/nfs/nfsroot.txt. | ||
17 | |||
18 | A CIFS root mount currently requires the use of SMB1+UNIX Extensions | ||
19 | which is only supported by the Samba server. SMB1 is the older | ||
20 | deprecated version of the protocol but it has been extended to support | ||
21 | POSIX features (See [1]). The equivalent extensions for the newer | ||
22 | recommended version of the protocol (SMB3) have not been fully | ||
23 | implemented yet which means SMB3 doesn't support some required POSIX | ||
24 | file system objects (e.g. block devices, pipes, sockets). | ||
25 | |||
26 | As a result, a CIFS root will default to SMB1 for now but the version | ||
27 | to use can nonetheless be changed via the 'vers=' mount option. This | ||
28 | default will change once the SMB3 POSIX extensions are fully | ||
29 | implemented. | ||
30 | |||
31 | Server configuration | ||
32 | ==================== | ||
33 | |||
34 | To enable SMB1+UNIX extensions you will need to set these global | ||
35 | settings in Samba smb.conf: | ||
36 | |||
37 | [global] | ||
38 | server min protocol = NT1 | ||
39 | unix extension = yes # default | ||
40 | |||
41 | Kernel command line | ||
42 | =================== | ||
43 | |||
44 | root=/dev/cifs | ||
45 | |||
46 | This is just a virtual device that basically tells the kernel to mount | ||
47 | the root file system via SMB protocol. | ||
48 | |||
49 | cifsroot=//<server-ip>/<share>[,options] | ||
50 | |||
51 | Enables the kernel to mount the root file system via SMB that are | ||
52 | located in the <server-ip> and <share> specified in this option. | ||
53 | |||
54 | The default mount options are set in fs/cifs/cifsroot.c. | ||
55 | |||
56 | server-ip | ||
57 | IPv4 address of the server. | ||
58 | |||
59 | share | ||
60 | Path to SMB share (rootfs). | ||
61 | |||
62 | options | ||
63 | Optional mount options. For more information, see mount.cifs(8). | ||
64 | |||
65 | Examples | ||
66 | ======== | ||
67 | |||
68 | Export root file system as a Samba share in smb.conf file. | ||
69 | |||
70 | ... | ||
71 | [linux] | ||
72 | path = /path/to/rootfs | ||
73 | read only = no | ||
74 | guest ok = yes | ||
75 | force user = root | ||
76 | force group = root | ||
77 | browseable = yes | ||
78 | writeable = yes | ||
79 | admin users = root | ||
80 | public = yes | ||
81 | create mask = 0777 | ||
82 | directory mask = 0777 | ||
83 | ... | ||
84 | |||
85 | Restart smb service. | ||
86 | |||
87 | # systemctl restart smb | ||
88 | |||
89 | Test it under QEMU on a kernel built with CONFIG_CIFS_ROOT and | ||
90 | CONFIG_IP_PNP options enabled. | ||
91 | |||
92 | # qemu-system-x86_64 -enable-kvm -cpu host -m 1024 \ | ||
93 | -kernel /path/to/linux/arch/x86/boot/bzImage -nographic \ | ||
94 | -append "root=/dev/cifs rw ip=dhcp cifsroot=//10.0.2.2/linux,username=foo,password=bar console=ttyS0 3" | ||
95 | |||
96 | |||
97 | 1: https://wiki.samba.org/index.php/UNIX_Extensions | ||
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 350bc3061656..22cf04fb32d3 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -211,3 +211,11 @@ config CIFS_FSCACHE | |||
211 | Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data | 211 | Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data |
212 | to be cached locally on disk through the general filesystem cache | 212 | to be cached locally on disk through the general filesystem cache |
213 | manager. If unsure, say N. | 213 | manager. If unsure, say N. |
214 | |||
215 | config CIFS_ROOT | ||
216 | bool "SMB root file system (Experimental)" | ||
217 | depends on CIFS=y && IP_PNP | ||
218 | help | ||
219 | Enables root file system support over SMB protocol. | ||
220 | |||
221 | Most people say N here. | ||
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 41332f20055b..51bae9340842 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
@@ -21,3 +21,5 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o dfs_cache.o | |||
21 | cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o | 21 | cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o |
22 | 22 | ||
23 | cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o | 23 | cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o |
24 | |||
25 | cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o | ||
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index a38d796f5ffe..0b4eee3bed66 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -452,6 +452,7 @@ static ssize_t cifs_stats_proc_write(struct file *file, | |||
452 | list_for_each(tmp1, &cifs_tcp_ses_list) { | 452 | list_for_each(tmp1, &cifs_tcp_ses_list) { |
453 | server = list_entry(tmp1, struct TCP_Server_Info, | 453 | server = list_entry(tmp1, struct TCP_Server_Info, |
454 | tcp_ses_list); | 454 | tcp_ses_list); |
455 | server->max_in_flight = 0; | ||
455 | #ifdef CONFIG_CIFS_STATS2 | 456 | #ifdef CONFIG_CIFS_STATS2 |
456 | for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) { | 457 | for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) { |
457 | atomic_set(&server->num_cmds[i], 0); | 458 | atomic_set(&server->num_cmds[i], 0); |
@@ -526,6 +527,7 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) | |||
526 | list_for_each(tmp1, &cifs_tcp_ses_list) { | 527 | list_for_each(tmp1, &cifs_tcp_ses_list) { |
527 | server = list_entry(tmp1, struct TCP_Server_Info, | 528 | server = list_entry(tmp1, struct TCP_Server_Info, |
528 | tcp_ses_list); | 529 | tcp_ses_list); |
530 | seq_printf(m, "\nMax requests in flight: %d", server->max_in_flight); | ||
529 | #ifdef CONFIG_CIFS_STATS2 | 531 | #ifdef CONFIG_CIFS_STATS2 |
530 | seq_puts(m, "\nTotal time spent processing by command. Time "); | 532 | seq_puts(m, "\nTotal time spent processing by command. Time "); |
531 | seq_printf(m, "units are jiffies (%d per second)\n", HZ); | 533 | seq_printf(m, "units are jiffies (%d per second)\n", HZ); |
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h index 3d392620a2f4..100b0056a369 100644 --- a/fs/cifs/cifs_debug.h +++ b/fs/cifs/cifs_debug.h | |||
@@ -80,6 +80,60 @@ do { \ | |||
80 | type, fmt, ##__VA_ARGS__); \ | 80 | type, fmt, ##__VA_ARGS__); \ |
81 | } while (0) | 81 | } while (0) |
82 | 82 | ||
83 | #define cifs_server_dbg_func(ratefunc, type, fmt, ...) \ | ||
84 | do { \ | ||
85 | const char *sn = ""; \ | ||
86 | if (server && server->hostname) \ | ||
87 | sn = server->hostname; \ | ||
88 | if ((type) & FYI && cifsFYI & CIFS_INFO) { \ | ||
89 | pr_debug_ ## ratefunc("%s: \\\\%s " fmt, \ | ||
90 | __FILE__, sn, ##__VA_ARGS__); \ | ||
91 | } else if ((type) & VFS) { \ | ||
92 | pr_err_ ## ratefunc("CIFS VFS: \\\\%s " fmt, \ | ||
93 | sn, ##__VA_ARGS__); \ | ||
94 | } else if ((type) & NOISY && (NOISY != 0)) { \ | ||
95 | pr_debug_ ## ratefunc("\\\\%s " fmt, \ | ||
96 | sn, ##__VA_ARGS__); \ | ||
97 | } \ | ||
98 | } while (0) | ||
99 | |||
100 | #define cifs_server_dbg(type, fmt, ...) \ | ||
101 | do { \ | ||
102 | if ((type) & ONCE) \ | ||
103 | cifs_server_dbg_func(once, \ | ||
104 | type, fmt, ##__VA_ARGS__); \ | ||
105 | else \ | ||
106 | cifs_server_dbg_func(ratelimited, \ | ||
107 | type, fmt, ##__VA_ARGS__); \ | ||
108 | } while (0) | ||
109 | |||
110 | #define cifs_tcon_dbg_func(ratefunc, type, fmt, ...) \ | ||
111 | do { \ | ||
112 | const char *tn = ""; \ | ||
113 | if (tcon && tcon->treeName) \ | ||
114 | tn = tcon->treeName; \ | ||
115 | if ((type) & FYI && cifsFYI & CIFS_INFO) { \ | ||
116 | pr_debug_ ## ratefunc("%s: %s " fmt, \ | ||
117 | __FILE__, tn, ##__VA_ARGS__); \ | ||
118 | } else if ((type) & VFS) { \ | ||
119 | pr_err_ ## ratefunc("CIFS VFS: %s " fmt, \ | ||
120 | tn, ##__VA_ARGS__); \ | ||
121 | } else if ((type) & NOISY && (NOISY != 0)) { \ | ||
122 | pr_debug_ ## ratefunc("%s " fmt, \ | ||
123 | tn, ##__VA_ARGS__); \ | ||
124 | } \ | ||
125 | } while (0) | ||
126 | |||
127 | #define cifs_tcon_dbg(type, fmt, ...) \ | ||
128 | do { \ | ||
129 | if ((type) & ONCE) \ | ||
130 | cifs_tcon_dbg_func(once, \ | ||
131 | type, fmt, ##__VA_ARGS__); \ | ||
132 | else \ | ||
133 | cifs_tcon_dbg_func(ratelimited, \ | ||
134 | type, fmt, ##__VA_ARGS__); \ | ||
135 | } while (0) | ||
136 | |||
83 | /* | 137 | /* |
84 | * debug OFF | 138 | * debug OFF |
85 | * --------- | 139 | * --------- |
@@ -91,6 +145,19 @@ do { \ | |||
91 | pr_debug(fmt, ##__VA_ARGS__); \ | 145 | pr_debug(fmt, ##__VA_ARGS__); \ |
92 | } while (0) | 146 | } while (0) |
93 | 147 | ||
148 | #define cifs_server_dbg(type, fmt, ...) \ | ||
149 | do { \ | ||
150 | if (0) \ | ||
151 | pr_debug("\\\\%s " fmt, \ | ||
152 | server->hostname, ##__VA_ARGS__); \ | ||
153 | } while (0) | ||
154 | |||
155 | #define cifs_tcon_dbg(type, fmt, ...) \ | ||
156 | do { \ | ||
157 | if (0) \ | ||
158 | pr_debug("%s " fmt, tcon->treeName, ##__VA_ARGS__); \ | ||
159 | } while (0) | ||
160 | |||
94 | #define cifs_info(fmt, ...) \ | 161 | #define cifs_info(fmt, ...) \ |
95 | do { \ | 162 | do { \ |
96 | pr_info("CIFS: "fmt, ##__VA_ARGS__); \ | 163 | pr_info("CIFS: "fmt, ##__VA_ARGS__); \ |
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index b326d2ca3765..6e7c4427369d 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -53,6 +53,8 @@ | |||
53 | #define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */ | 53 | #define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */ |
54 | #define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */ | 54 | #define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */ |
55 | #define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */ | 55 | #define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */ |
56 | #define CIFS_MOUNT_RO_CACHE 0x20000000 /* assumes share will not change */ | ||
57 | #define CIFS_MOUNT_RW_CACHE 0x40000000 /* assumes only client accessing */ | ||
56 | 58 | ||
57 | struct cifs_sb_info { | 59 | struct cifs_sb_info { |
58 | struct rb_root tlink_tree; | 60 | struct rb_root tlink_tree; |
diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h index 086ddc5108af..6c3bd07868d7 100644 --- a/fs/cifs/cifs_ioctl.h +++ b/fs/cifs/cifs_ioctl.h | |||
@@ -46,6 +46,7 @@ struct smb_snapshot_array { | |||
46 | /* query_info flags */ | 46 | /* query_info flags */ |
47 | #define PASSTHRU_QUERY_INFO 0x00000000 | 47 | #define PASSTHRU_QUERY_INFO 0x00000000 |
48 | #define PASSTHRU_FSCTL 0x00000001 | 48 | #define PASSTHRU_FSCTL 0x00000001 |
49 | #define PASSTHRU_SET_INFO 0x00000002 | ||
49 | struct smb_query_info { | 50 | struct smb_query_info { |
50 | __u32 info_type; | 51 | __u32 info_type; |
51 | __u32 file_info_class; | 52 | __u32 file_info_class; |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 1d377b7f2860..f842944a5c76 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -701,10 +701,9 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) | |||
701 | } | 701 | } |
702 | #endif | 702 | #endif |
703 | 703 | ||
704 | |||
705 | static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | 704 | static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, |
706 | struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, | 705 | struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, |
707 | struct cifs_fattr *fattr) | 706 | struct cifs_fattr *fattr, bool mode_from_special_sid) |
708 | { | 707 | { |
709 | int i; | 708 | int i; |
710 | int num_aces = 0; | 709 | int num_aces = 0; |
@@ -757,22 +756,34 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
757 | #ifdef CONFIG_CIFS_DEBUG2 | 756 | #ifdef CONFIG_CIFS_DEBUG2 |
758 | dump_ace(ppace[i], end_of_acl); | 757 | dump_ace(ppace[i], end_of_acl); |
759 | #endif | 758 | #endif |
760 | if (compare_sids(&(ppace[i]->sid), pownersid) == 0) | 759 | if (mode_from_special_sid && |
760 | (compare_sids(&(ppace[i]->sid), | ||
761 | &sid_unix_NFS_mode) == 0)) { | ||
762 | /* | ||
763 | * Full permissions are: | ||
764 | * 07777 = S_ISUID | S_ISGID | S_ISVTX | | ||
765 | * S_IRWXU | S_IRWXG | S_IRWXO | ||
766 | */ | ||
767 | fattr->cf_mode &= ~07777; | ||
768 | fattr->cf_mode |= | ||
769 | le32_to_cpu(ppace[i]->sid.sub_auth[2]); | ||
770 | break; | ||
771 | } else if (compare_sids(&(ppace[i]->sid), pownersid) == 0) | ||
761 | access_flags_to_mode(ppace[i]->access_req, | 772 | access_flags_to_mode(ppace[i]->access_req, |
762 | ppace[i]->type, | 773 | ppace[i]->type, |
763 | &fattr->cf_mode, | 774 | &fattr->cf_mode, |
764 | &user_mask); | 775 | &user_mask); |
765 | if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) | 776 | else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) |
766 | access_flags_to_mode(ppace[i]->access_req, | 777 | access_flags_to_mode(ppace[i]->access_req, |
767 | ppace[i]->type, | 778 | ppace[i]->type, |
768 | &fattr->cf_mode, | 779 | &fattr->cf_mode, |
769 | &group_mask); | 780 | &group_mask); |
770 | if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) | 781 | else if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) |
771 | access_flags_to_mode(ppace[i]->access_req, | 782 | access_flags_to_mode(ppace[i]->access_req, |
772 | ppace[i]->type, | 783 | ppace[i]->type, |
773 | &fattr->cf_mode, | 784 | &fattr->cf_mode, |
774 | &other_mask); | 785 | &other_mask); |
775 | if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) | 786 | else if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) |
776 | access_flags_to_mode(ppace[i]->access_req, | 787 | access_flags_to_mode(ppace[i]->access_req, |
777 | ppace[i]->type, | 788 | ppace[i]->type, |
778 | &fattr->cf_mode, | 789 | &fattr->cf_mode, |
@@ -795,22 +806,49 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
795 | 806 | ||
796 | 807 | ||
797 | static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, | 808 | static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, |
798 | struct cifs_sid *pgrpsid, __u64 nmode) | 809 | struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid) |
799 | { | 810 | { |
800 | u16 size = 0; | 811 | u16 size = 0; |
812 | u32 num_aces = 0; | ||
801 | struct cifs_acl *pnndacl; | 813 | struct cifs_acl *pnndacl; |
802 | 814 | ||
803 | pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl)); | 815 | pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl)); |
804 | 816 | ||
817 | if (modefromsid) { | ||
818 | struct cifs_ace *pntace = | ||
819 | (struct cifs_ace *)((char *)pnndacl + size); | ||
820 | int i; | ||
821 | |||
822 | pntace->type = ACCESS_ALLOWED; | ||
823 | pntace->flags = 0x0; | ||
824 | pntace->access_req = 0; | ||
825 | pntace->sid.num_subauth = 3; | ||
826 | pntace->sid.revision = 1; | ||
827 | for (i = 0; i < NUM_AUTHS; i++) | ||
828 | pntace->sid.authority[i] = | ||
829 | sid_unix_NFS_mode.authority[i]; | ||
830 | pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0]; | ||
831 | pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1]; | ||
832 | pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777); | ||
833 | |||
834 | /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ | ||
835 | pntace->size = cpu_to_le16(28); | ||
836 | size += 28; | ||
837 | num_aces++; | ||
838 | } | ||
839 | |||
805 | size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size), | 840 | size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size), |
806 | pownersid, nmode, S_IRWXU); | 841 | pownersid, nmode, S_IRWXU); |
842 | num_aces++; | ||
807 | size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), | 843 | size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), |
808 | pgrpsid, nmode, S_IRWXG); | 844 | pgrpsid, nmode, S_IRWXG); |
845 | num_aces++; | ||
809 | size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), | 846 | size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), |
810 | &sid_everyone, nmode, S_IRWXO); | 847 | &sid_everyone, nmode, S_IRWXO); |
848 | num_aces++; | ||
811 | 849 | ||
850 | pndacl->num_aces = cpu_to_le32(num_aces); | ||
812 | pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl)); | 851 | pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl)); |
813 | pndacl->num_aces = cpu_to_le32(3); | ||
814 | 852 | ||
815 | return 0; | 853 | return 0; |
816 | } | 854 | } |
@@ -851,7 +889,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |||
851 | 889 | ||
852 | /* Convert CIFS ACL to POSIX form */ | 890 | /* Convert CIFS ACL to POSIX form */ |
853 | static int parse_sec_desc(struct cifs_sb_info *cifs_sb, | 891 | static int parse_sec_desc(struct cifs_sb_info *cifs_sb, |
854 | struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr) | 892 | struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr, |
893 | bool get_mode_from_special_sid) | ||
855 | { | 894 | { |
856 | int rc = 0; | 895 | int rc = 0; |
857 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 896 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
@@ -900,7 +939,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, | |||
900 | 939 | ||
901 | if (dacloffset) | 940 | if (dacloffset) |
902 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, | 941 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, |
903 | group_sid_ptr, fattr); | 942 | group_sid_ptr, fattr, get_mode_from_special_sid); |
904 | else | 943 | else |
905 | cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */ | 944 | cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */ |
906 | 945 | ||
@@ -909,7 +948,8 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, | |||
909 | 948 | ||
910 | /* Convert permission bits from mode to equivalent CIFS ACL */ | 949 | /* Convert permission bits from mode to equivalent CIFS ACL */ |
911 | static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, | 950 | static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, |
912 | __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag) | 951 | __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, |
952 | bool mode_from_sid, int *aclflag) | ||
913 | { | 953 | { |
914 | int rc = 0; | 954 | int rc = 0; |
915 | __u32 dacloffset; | 955 | __u32 dacloffset; |
@@ -934,7 +974,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, | |||
934 | ndacl_ptr->num_aces = 0; | 974 | ndacl_ptr->num_aces = 0; |
935 | 975 | ||
936 | rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, | 976 | rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, |
937 | nmode); | 977 | nmode, mode_from_sid); |
938 | sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size); | 978 | sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size); |
939 | /* copy sec desc control portion & owner and group sids */ | 979 | /* copy sec desc control portion & owner and group sids */ |
940 | copy_sec_desc(pntsd, pnntsd, sidsoffset); | 980 | copy_sec_desc(pntsd, pnntsd, sidsoffset); |
@@ -1128,8 +1168,8 @@ out: | |||
1128 | /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */ | 1168 | /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */ |
1129 | int | 1169 | int |
1130 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | 1170 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
1131 | struct inode *inode, const char *path, | 1171 | struct inode *inode, bool mode_from_special_sid, |
1132 | const struct cifs_fid *pfid) | 1172 | const char *path, const struct cifs_fid *pfid) |
1133 | { | 1173 | { |
1134 | struct cifs_ntsd *pntsd = NULL; | 1174 | struct cifs_ntsd *pntsd = NULL; |
1135 | u32 acllen = 0; | 1175 | u32 acllen = 0; |
@@ -1156,8 +1196,11 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | |||
1156 | if (IS_ERR(pntsd)) { | 1196 | if (IS_ERR(pntsd)) { |
1157 | rc = PTR_ERR(pntsd); | 1197 | rc = PTR_ERR(pntsd); |
1158 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); | 1198 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); |
1199 | } else if (mode_from_special_sid) { | ||
1200 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true); | ||
1159 | } else { | 1201 | } else { |
1160 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr); | 1202 | /* get approximated mode from ACL */ |
1203 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false); | ||
1161 | kfree(pntsd); | 1204 | kfree(pntsd); |
1162 | if (rc) | 1205 | if (rc) |
1163 | cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); | 1206 | cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); |
@@ -1181,6 +1224,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, | |||
1181 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1224 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1182 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 1225 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
1183 | struct smb_version_operations *ops; | 1226 | struct smb_version_operations *ops; |
1227 | bool mode_from_sid; | ||
1184 | 1228 | ||
1185 | if (IS_ERR(tlink)) | 1229 | if (IS_ERR(tlink)) |
1186 | return PTR_ERR(tlink); | 1230 | return PTR_ERR(tlink); |
@@ -1218,8 +1262,13 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, | |||
1218 | return -ENOMEM; | 1262 | return -ENOMEM; |
1219 | } | 1263 | } |
1220 | 1264 | ||
1265 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) | ||
1266 | mode_from_sid = true; | ||
1267 | else | ||
1268 | mode_from_sid = false; | ||
1269 | |||
1221 | rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid, | 1270 | rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid, |
1222 | &aclflag); | 1271 | mode_from_sid, &aclflag); |
1223 | 1272 | ||
1224 | cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); | 1273 | cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); |
1225 | 1274 | ||
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index dd95a6fa24bf..eb428349f29a 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h | |||
@@ -45,7 +45,7 @@ | |||
45 | */ | 45 | */ |
46 | #define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \ | 46 | #define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \ |
47 | sizeof(struct cifs_acl) + \ | 47 | sizeof(struct cifs_acl) + \ |
48 | (sizeof(struct cifs_ace) * 3)) | 48 | (sizeof(struct cifs_ace) * 4)) |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * Maximum size of a string representation of a SID: | 51 | * Maximum size of a string representation of a SID: |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index e8afff702bb8..2e9c7f493f99 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -118,6 +118,7 @@ extern mempool_t *cifs_req_poolp; | |||
118 | extern mempool_t *cifs_mid_poolp; | 118 | extern mempool_t *cifs_mid_poolp; |
119 | 119 | ||
120 | struct workqueue_struct *cifsiod_wq; | 120 | struct workqueue_struct *cifsiod_wq; |
121 | struct workqueue_struct *decrypt_wq; | ||
121 | struct workqueue_struct *cifsoplockd_wq; | 122 | struct workqueue_struct *cifsoplockd_wq; |
122 | __u32 cifs_lock_secret; | 123 | __u32 cifs_lock_secret; |
123 | 124 | ||
@@ -422,6 +423,10 @@ cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb) | |||
422 | seq_puts(s, "strict"); | 423 | seq_puts(s, "strict"); |
423 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | 424 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) |
424 | seq_puts(s, "none"); | 425 | seq_puts(s, "none"); |
426 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE) | ||
427 | seq_puts(s, "singleclient"); /* assume only one client access */ | ||
428 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) | ||
429 | seq_puts(s, "ro"); /* read only caching assumed */ | ||
425 | else | 430 | else |
426 | seq_puts(s, "loose"); | 431 | seq_puts(s, "loose"); |
427 | } | 432 | } |
@@ -455,6 +460,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
455 | cifs_show_security(s, tcon->ses); | 460 | cifs_show_security(s, tcon->ses); |
456 | cifs_show_cache_flavor(s, cifs_sb); | 461 | cifs_show_cache_flavor(s, cifs_sb); |
457 | 462 | ||
463 | if (tcon->no_lease) | ||
464 | seq_puts(s, ",nolease"); | ||
458 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) | 465 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) |
459 | seq_puts(s, ",multiuser"); | 466 | seq_puts(s, ",multiuser"); |
460 | else if (tcon->ses->user_name) | 467 | else if (tcon->ses->user_name) |
@@ -576,6 +583,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
576 | seq_printf(s, ",rsize=%u", cifs_sb->rsize); | 583 | seq_printf(s, ",rsize=%u", cifs_sb->rsize); |
577 | seq_printf(s, ",wsize=%u", cifs_sb->wsize); | 584 | seq_printf(s, ",wsize=%u", cifs_sb->wsize); |
578 | seq_printf(s, ",bsize=%u", cifs_sb->bsize); | 585 | seq_printf(s, ",bsize=%u", cifs_sb->bsize); |
586 | if (tcon->ses->server->min_offload) | ||
587 | seq_printf(s, ",esize=%u", tcon->ses->server->min_offload); | ||
579 | seq_printf(s, ",echo_interval=%lu", | 588 | seq_printf(s, ",echo_interval=%lu", |
580 | tcon->ses->server->echo_interval / HZ); | 589 | tcon->ses->server->echo_interval / HZ); |
581 | 590 | ||
@@ -1517,11 +1526,25 @@ init_cifs(void) | |||
1517 | goto out_clean_proc; | 1526 | goto out_clean_proc; |
1518 | } | 1527 | } |
1519 | 1528 | ||
1529 | /* | ||
1530 | * Consider in future setting limit!=0 maybe to min(num_of_cores - 1, 3) | ||
1531 | * so that we don't launch too many worker threads but | ||
1532 | * Documentation/workqueue.txt recommends setting it to 0 | ||
1533 | */ | ||
1534 | |||
1535 | /* WQ_UNBOUND allows decrypt tasks to run on any CPU */ | ||
1536 | decrypt_wq = alloc_workqueue("smb3decryptd", | ||
1537 | WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); | ||
1538 | if (!decrypt_wq) { | ||
1539 | rc = -ENOMEM; | ||
1540 | goto out_destroy_cifsiod_wq; | ||
1541 | } | ||
1542 | |||
1520 | cifsoplockd_wq = alloc_workqueue("cifsoplockd", | 1543 | cifsoplockd_wq = alloc_workqueue("cifsoplockd", |
1521 | WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); | 1544 | WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); |
1522 | if (!cifsoplockd_wq) { | 1545 | if (!cifsoplockd_wq) { |
1523 | rc = -ENOMEM; | 1546 | rc = -ENOMEM; |
1524 | goto out_destroy_cifsiod_wq; | 1547 | goto out_destroy_decrypt_wq; |
1525 | } | 1548 | } |
1526 | 1549 | ||
1527 | rc = cifs_fscache_register(); | 1550 | rc = cifs_fscache_register(); |
@@ -1587,6 +1610,8 @@ out_unreg_fscache: | |||
1587 | cifs_fscache_unregister(); | 1610 | cifs_fscache_unregister(); |
1588 | out_destroy_cifsoplockd_wq: | 1611 | out_destroy_cifsoplockd_wq: |
1589 | destroy_workqueue(cifsoplockd_wq); | 1612 | destroy_workqueue(cifsoplockd_wq); |
1613 | out_destroy_decrypt_wq: | ||
1614 | destroy_workqueue(decrypt_wq); | ||
1590 | out_destroy_cifsiod_wq: | 1615 | out_destroy_cifsiod_wq: |
1591 | destroy_workqueue(cifsiod_wq); | 1616 | destroy_workqueue(cifsiod_wq); |
1592 | out_clean_proc: | 1617 | out_clean_proc: |
@@ -1613,6 +1638,7 @@ exit_cifs(void) | |||
1613 | cifs_destroy_inodecache(); | 1638 | cifs_destroy_inodecache(); |
1614 | cifs_fscache_unregister(); | 1639 | cifs_fscache_unregister(); |
1615 | destroy_workqueue(cifsoplockd_wq); | 1640 | destroy_workqueue(cifsoplockd_wq); |
1641 | destroy_workqueue(decrypt_wq); | ||
1616 | destroy_workqueue(cifsiod_wq); | 1642 | destroy_workqueue(cifsiod_wq); |
1617 | cifs_proc_clean(); | 1643 | cifs_proc_clean(); |
1618 | } | 1644 | } |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 99caf77df4a2..bc4ca94137f2 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -152,5 +152,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
152 | extern const struct export_operations cifs_export_ops; | 152 | extern const struct export_operations cifs_export_ops; |
153 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ | 153 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ |
154 | 154 | ||
155 | #define CIFS_VERSION "2.22" | 155 | #define CIFS_VERSION "2.23" |
156 | #endif /* _CIFSFS_H */ | 156 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index fe610e7e3670..54e204589cb9 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -542,6 +542,7 @@ struct smb_vol { | |||
542 | umode_t dir_mode; | 542 | umode_t dir_mode; |
543 | enum securityEnum sectype; /* sectype requested via mnt opts */ | 543 | enum securityEnum sectype; /* sectype requested via mnt opts */ |
544 | bool sign; /* was signing requested via mnt opts? */ | 544 | bool sign; /* was signing requested via mnt opts? */ |
545 | bool ignore_signature:1; | ||
545 | bool retry:1; | 546 | bool retry:1; |
546 | bool intr:1; | 547 | bool intr:1; |
547 | bool setuids:1; | 548 | bool setuids:1; |
@@ -559,6 +560,8 @@ struct smb_vol { | |||
559 | bool server_ino:1; /* use inode numbers from server ie UniqueId */ | 560 | bool server_ino:1; /* use inode numbers from server ie UniqueId */ |
560 | bool direct_io:1; | 561 | bool direct_io:1; |
561 | bool strict_io:1; /* strict cache behavior */ | 562 | bool strict_io:1; /* strict cache behavior */ |
563 | bool cache_ro:1; | ||
564 | bool cache_rw:1; | ||
562 | bool remap:1; /* set to remap seven reserved chars in filenames */ | 565 | bool remap:1; /* set to remap seven reserved chars in filenames */ |
563 | bool sfu_remap:1; /* remap seven reserved chars ala SFU */ | 566 | bool sfu_remap:1; /* remap seven reserved chars ala SFU */ |
564 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ | 567 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ |
@@ -576,6 +579,7 @@ struct smb_vol { | |||
576 | bool noblocksnd:1; | 579 | bool noblocksnd:1; |
577 | bool noautotune:1; | 580 | bool noautotune:1; |
578 | bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ | 581 | bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ |
582 | bool no_lease:1; /* disable requesting leases */ | ||
579 | bool fsc:1; /* enable fscache */ | 583 | bool fsc:1; /* enable fscache */ |
580 | bool mfsymlinks:1; /* use Minshall+French Symlinks */ | 584 | bool mfsymlinks:1; /* use Minshall+French Symlinks */ |
581 | bool multiuser:1; | 585 | bool multiuser:1; |
@@ -589,6 +593,7 @@ struct smb_vol { | |||
589 | unsigned int bsize; | 593 | unsigned int bsize; |
590 | unsigned int rsize; | 594 | unsigned int rsize; |
591 | unsigned int wsize; | 595 | unsigned int wsize; |
596 | unsigned int min_offload; | ||
592 | bool sockopt_tcp_nodelay:1; | 597 | bool sockopt_tcp_nodelay:1; |
593 | unsigned long actimeo; /* attribute cache timeout (jiffies) */ | 598 | unsigned long actimeo; /* attribute cache timeout (jiffies) */ |
594 | struct smb_version_operations *ops; | 599 | struct smb_version_operations *ops; |
@@ -602,6 +607,7 @@ struct smb_vol { | |||
602 | __u32 handle_timeout; /* persistent and durable handle timeout in ms */ | 607 | __u32 handle_timeout; /* persistent and durable handle timeout in ms */ |
603 | unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ | 608 | unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ |
604 | __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */ | 609 | __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */ |
610 | bool rootfs:1; /* if it's a SMB root file system */ | ||
605 | }; | 611 | }; |
606 | 612 | ||
607 | /** | 613 | /** |
@@ -620,7 +626,8 @@ struct smb_vol { | |||
620 | CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \ | 626 | CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \ |
621 | CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \ | 627 | CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \ |
622 | CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \ | 628 | CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \ |
623 | CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID) | 629 | CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID | \ |
630 | CIFS_MOUNT_RO_CACHE | CIFS_MOUNT_RW_CACHE) | ||
624 | 631 | ||
625 | /** | 632 | /** |
626 | * Generic VFS superblock mount flags (s_flags) to consider when | 633 | * Generic VFS superblock mount flags (s_flags) to consider when |
@@ -672,12 +679,14 @@ struct TCP_Server_Info { | |||
672 | unsigned int credits; /* send no more requests at once */ | 679 | unsigned int credits; /* send no more requests at once */ |
673 | unsigned int max_credits; /* can override large 32000 default at mnt */ | 680 | unsigned int max_credits; /* can override large 32000 default at mnt */ |
674 | unsigned int in_flight; /* number of requests on the wire to server */ | 681 | unsigned int in_flight; /* number of requests on the wire to server */ |
682 | unsigned int max_in_flight; /* max number of requests that were on wire */ | ||
675 | spinlock_t req_lock; /* protect the two values above */ | 683 | spinlock_t req_lock; /* protect the two values above */ |
676 | struct mutex srv_mutex; | 684 | struct mutex srv_mutex; |
677 | struct task_struct *tsk; | 685 | struct task_struct *tsk; |
678 | char server_GUID[16]; | 686 | char server_GUID[16]; |
679 | __u16 sec_mode; | 687 | __u16 sec_mode; |
680 | bool sign; /* is signing enabled on this connection? */ | 688 | bool sign; /* is signing enabled on this connection? */ |
689 | bool ignore_signature:1; /* skip validation of signatures in SMB2/3 rsp */ | ||
681 | bool session_estab; /* mark when very first sess is established */ | 690 | bool session_estab; /* mark when very first sess is established */ |
682 | int echo_credits; /* echo reserved slots */ | 691 | int echo_credits; /* echo reserved slots */ |
683 | int oplock_credits; /* oplock break reserved slots */ | 692 | int oplock_credits; /* oplock break reserved slots */ |
@@ -740,6 +749,7 @@ struct TCP_Server_Info { | |||
740 | #endif /* STATS2 */ | 749 | #endif /* STATS2 */ |
741 | unsigned int max_read; | 750 | unsigned int max_read; |
742 | unsigned int max_write; | 751 | unsigned int max_write; |
752 | unsigned int min_offload; | ||
743 | __le16 compress_algorithm; | 753 | __le16 compress_algorithm; |
744 | __le16 cipher_type; | 754 | __le16 cipher_type; |
745 | /* save initital negprot hash */ | 755 | /* save initital negprot hash */ |
@@ -755,6 +765,7 @@ struct TCP_Server_Info { | |||
755 | * reconnect. | 765 | * reconnect. |
756 | */ | 766 | */ |
757 | int nr_targets; | 767 | int nr_targets; |
768 | bool noblockcnt; /* use non-blocking connect() */ | ||
758 | }; | 769 | }; |
759 | 770 | ||
760 | struct cifs_credits { | 771 | struct cifs_credits { |
@@ -1082,6 +1093,7 @@ struct cifs_tcon { | |||
1082 | bool need_reopen_files:1; /* need to reopen tcon file handles */ | 1093 | bool need_reopen_files:1; /* need to reopen tcon file handles */ |
1083 | bool use_resilient:1; /* use resilient instead of durable handles */ | 1094 | bool use_resilient:1; /* use resilient instead of durable handles */ |
1084 | bool use_persistent:1; /* use persistent instead of durable handles */ | 1095 | bool use_persistent:1; /* use persistent instead of durable handles */ |
1096 | bool no_lease:1; /* Do not request leases on files or directories */ | ||
1085 | __le32 capabilities; | 1097 | __le32 capabilities; |
1086 | __u32 share_flags; | 1098 | __u32 share_flags; |
1087 | __u32 maximal_access; | 1099 | __u32 maximal_access; |
@@ -1366,9 +1378,9 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file); | |||
1366 | #define CIFS_CACHE_RW_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG) | 1378 | #define CIFS_CACHE_RW_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG) |
1367 | #define CIFS_CACHE_RHW_FLG (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG) | 1379 | #define CIFS_CACHE_RHW_FLG (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG) |
1368 | 1380 | ||
1369 | #define CIFS_CACHE_READ(cinode) (cinode->oplock & CIFS_CACHE_READ_FLG) | 1381 | #define CIFS_CACHE_READ(cinode) ((cinode->oplock & CIFS_CACHE_READ_FLG) || (CIFS_SB(cinode->vfs_inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)) |
1370 | #define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG) | 1382 | #define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG) |
1371 | #define CIFS_CACHE_WRITE(cinode) (cinode->oplock & CIFS_CACHE_WRITE_FLG) | 1383 | #define CIFS_CACHE_WRITE(cinode) ((cinode->oplock & CIFS_CACHE_WRITE_FLG) || (CIFS_SB(cinode->vfs_inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)) |
1372 | 1384 | ||
1373 | /* | 1385 | /* |
1374 | * One of these for each file inode | 1386 | * One of these for each file inode |
@@ -1887,6 +1899,7 @@ void cifs_queue_oplock_break(struct cifsFileInfo *cfile); | |||
1887 | 1899 | ||
1888 | extern const struct slow_work_ops cifs_oplock_break_ops; | 1900 | extern const struct slow_work_ops cifs_oplock_break_ops; |
1889 | extern struct workqueue_struct *cifsiod_wq; | 1901 | extern struct workqueue_struct *cifsiod_wq; |
1902 | extern struct workqueue_struct *decrypt_wq; | ||
1890 | extern struct workqueue_struct *cifsoplockd_wq; | 1903 | extern struct workqueue_struct *cifsoplockd_wq; |
1891 | extern __u32 cifs_lock_secret; | 1904 | extern __u32 cifs_lock_secret; |
1892 | 1905 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 592a6cea2b79..99b1b1ef558c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -137,7 +137,11 @@ extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); | |||
137 | extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, | 137 | extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, |
138 | bool fsuid_only, | 138 | bool fsuid_only, |
139 | struct cifsFileInfo **ret_file); | 139 | struct cifsFileInfo **ret_file); |
140 | extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, | ||
141 | struct cifsFileInfo **ret_file); | ||
140 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); | 142 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); |
143 | extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, | ||
144 | struct cifsFileInfo **ret_file); | ||
141 | extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server); | 145 | extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server); |
142 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 146 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
143 | struct TCP_Server_Info *server); | 147 | struct TCP_Server_Info *server); |
@@ -197,6 +201,7 @@ extern int cifs_rename_pending_delete(const char *full_path, | |||
197 | const unsigned int xid); | 201 | const unsigned int xid); |
198 | extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, | 202 | extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, |
199 | struct cifs_fattr *fattr, struct inode *inode, | 203 | struct cifs_fattr *fattr, struct inode *inode, |
204 | bool get_mode_from_special_sid, | ||
200 | const char *path, const struct cifs_fid *pfid); | 205 | const char *path, const struct cifs_fid *pfid); |
201 | extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, | 206 | extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, |
202 | kuid_t, kgid_t); | 207 | kuid_t, kgid_t); |
diff --git a/fs/cifs/cifsroot.c b/fs/cifs/cifsroot.c new file mode 100644 index 000000000000..37edbfb8e096 --- /dev/null +++ b/fs/cifs/cifsroot.c | |||
@@ -0,0 +1,94 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * SMB root file system support | ||
4 | * | ||
5 | * Copyright (c) 2019 Paulo Alcantara <palcantara@suse.de> | ||
6 | */ | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/fs.h> | ||
9 | #include <linux/types.h> | ||
10 | #include <linux/ctype.h> | ||
11 | #include <linux/string.h> | ||
12 | #include <linux/root_dev.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/in.h> | ||
15 | #include <linux/inet.h> | ||
16 | #include <net/ipconfig.h> | ||
17 | |||
18 | #define DEFAULT_MNT_OPTS \ | ||
19 | "vers=1.0,cifsacl,mfsymlinks,rsize=1048576,wsize=65536,uid=0,gid=0," \ | ||
20 | "hard,rootfs" | ||
21 | |||
22 | static char root_dev[2048] __initdata = ""; | ||
23 | static char root_opts[1024] __initdata = DEFAULT_MNT_OPTS; | ||
24 | |||
25 | static __be32 __init parse_srvaddr(char *start, char *end) | ||
26 | { | ||
27 | /* TODO: ipv6 support */ | ||
28 | char addr[sizeof("aaa.bbb.ccc.ddd")]; | ||
29 | int i = 0; | ||
30 | |||
31 | while (start < end && i < sizeof(addr) - 1) { | ||
32 | if (isdigit(*start) || *start == '.') | ||
33 | addr[i++] = *start; | ||
34 | start++; | ||
35 | } | ||
36 | addr[i] = '\0'; | ||
37 | return in_aton(addr); | ||
38 | } | ||
39 | |||
40 | /* cifsroot=//<server-ip>/<share>[,options] */ | ||
41 | static int __init cifs_root_setup(char *line) | ||
42 | { | ||
43 | char *s; | ||
44 | int len; | ||
45 | __be32 srvaddr = htonl(INADDR_NONE); | ||
46 | |||
47 | ROOT_DEV = Root_CIFS; | ||
48 | |||
49 | if (strlen(line) > 3 && line[0] == '/' && line[1] == '/') { | ||
50 | s = strchr(&line[2], '/'); | ||
51 | if (!s || s[1] == '\0') | ||
52 | return 1; | ||
53 | |||
54 | /* make s point to ',' or '\0' at end of line */ | ||
55 | s = strchrnul(s, ','); | ||
56 | /* len is strlen(unc) + '\0' */ | ||
57 | len = s - line + 1; | ||
58 | if (len > sizeof(root_dev)) { | ||
59 | printk(KERN_ERR "Root-CIFS: UNC path too long\n"); | ||
60 | return 1; | ||
61 | } | ||
62 | strlcpy(root_dev, line, len); | ||
63 | srvaddr = parse_srvaddr(&line[2], s); | ||
64 | if (*s) { | ||
65 | int n = snprintf(root_opts, | ||
66 | sizeof(root_opts), "%s,%s", | ||
67 | DEFAULT_MNT_OPTS, s + 1); | ||
68 | if (n >= sizeof(root_opts)) { | ||
69 | printk(KERN_ERR "Root-CIFS: mount options string too long\n"); | ||
70 | root_opts[sizeof(root_opts)-1] = '\0'; | ||
71 | return 1; | ||
72 | } | ||
73 | } | ||
74 | } | ||
75 | |||
76 | root_server_addr = srvaddr; | ||
77 | |||
78 | return 1; | ||
79 | } | ||
80 | |||
81 | __setup("cifsroot=", cifs_root_setup); | ||
82 | |||
83 | int __init cifs_root_data(char **dev, char **opts) | ||
84 | { | ||
85 | if (!root_dev[0] || root_server_addr == htonl(INADDR_NONE)) { | ||
86 | printk(KERN_ERR "Root-CIFS: no SMB server address\n"); | ||
87 | return -1; | ||
88 | } | ||
89 | |||
90 | *dev = root_dev; | ||
91 | *opts = root_opts; | ||
92 | |||
93 | return 0; | ||
94 | } | ||
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 3907653e63c7..dbee2132e419 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1393,7 +1393,7 @@ int | |||
1393 | CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, | 1393 | CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, |
1394 | FILE_ALL_INFO *buf) | 1394 | FILE_ALL_INFO *buf) |
1395 | { | 1395 | { |
1396 | int rc = -EACCES; | 1396 | int rc; |
1397 | OPEN_REQ *req = NULL; | 1397 | OPEN_REQ *req = NULL; |
1398 | OPEN_RSP *rsp = NULL; | 1398 | OPEN_RSP *rsp = NULL; |
1399 | int bytes_returned; | 1399 | int bytes_returned; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5299effa6f7d..2850c3ce4391 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -74,7 +74,7 @@ enum { | |||
74 | Opt_user_xattr, Opt_nouser_xattr, | 74 | Opt_user_xattr, Opt_nouser_xattr, |
75 | Opt_forceuid, Opt_noforceuid, | 75 | Opt_forceuid, Opt_noforceuid, |
76 | Opt_forcegid, Opt_noforcegid, | 76 | Opt_forcegid, Opt_noforcegid, |
77 | Opt_noblocksend, Opt_noautotune, | 77 | Opt_noblocksend, Opt_noautotune, Opt_nolease, |
78 | Opt_hard, Opt_soft, Opt_perm, Opt_noperm, | 78 | Opt_hard, Opt_soft, Opt_perm, Opt_noperm, |
79 | Opt_mapposix, Opt_nomapposix, | 79 | Opt_mapposix, Opt_nomapposix, |
80 | Opt_mapchars, Opt_nomapchars, Opt_sfu, | 80 | Opt_mapchars, Opt_nomapchars, Opt_sfu, |
@@ -91,18 +91,19 @@ enum { | |||
91 | Opt_serverino, Opt_noserverino, | 91 | Opt_serverino, Opt_noserverino, |
92 | Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl, | 92 | Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl, |
93 | Opt_acl, Opt_noacl, Opt_locallease, | 93 | Opt_acl, Opt_noacl, Opt_locallease, |
94 | Opt_sign, Opt_seal, Opt_noac, | 94 | Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac, |
95 | Opt_fsc, Opt_mfsymlinks, | 95 | Opt_fsc, Opt_mfsymlinks, |
96 | Opt_multiuser, Opt_sloppy, Opt_nosharesock, | 96 | Opt_multiuser, Opt_sloppy, Opt_nosharesock, |
97 | Opt_persistent, Opt_nopersistent, | 97 | Opt_persistent, Opt_nopersistent, |
98 | Opt_resilient, Opt_noresilient, | 98 | Opt_resilient, Opt_noresilient, |
99 | Opt_domainauto, Opt_rdma, Opt_modesid, | 99 | Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs, |
100 | Opt_compress, | 100 | Opt_compress, |
101 | 101 | ||
102 | /* Mount options which take numeric value */ | 102 | /* Mount options which take numeric value */ |
103 | Opt_backupuid, Opt_backupgid, Opt_uid, | 103 | Opt_backupuid, Opt_backupgid, Opt_uid, |
104 | Opt_cruid, Opt_gid, Opt_file_mode, | 104 | Opt_cruid, Opt_gid, Opt_file_mode, |
105 | Opt_dirmode, Opt_port, | 105 | Opt_dirmode, Opt_port, |
106 | Opt_min_enc_offload, | ||
106 | Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo, | 107 | Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo, |
107 | Opt_echo_interval, Opt_max_credits, Opt_handletimeout, | 108 | Opt_echo_interval, Opt_max_credits, Opt_handletimeout, |
108 | Opt_snapshot, | 109 | Opt_snapshot, |
@@ -134,6 +135,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
134 | { Opt_noforcegid, "noforcegid" }, | 135 | { Opt_noforcegid, "noforcegid" }, |
135 | { Opt_noblocksend, "noblocksend" }, | 136 | { Opt_noblocksend, "noblocksend" }, |
136 | { Opt_noautotune, "noautotune" }, | 137 | { Opt_noautotune, "noautotune" }, |
138 | { Opt_nolease, "nolease" }, | ||
137 | { Opt_hard, "hard" }, | 139 | { Opt_hard, "hard" }, |
138 | { Opt_soft, "soft" }, | 140 | { Opt_soft, "soft" }, |
139 | { Opt_perm, "perm" }, | 141 | { Opt_perm, "perm" }, |
@@ -183,6 +185,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
183 | { Opt_noacl, "noacl" }, | 185 | { Opt_noacl, "noacl" }, |
184 | { Opt_locallease, "locallease" }, | 186 | { Opt_locallease, "locallease" }, |
185 | { Opt_sign, "sign" }, | 187 | { Opt_sign, "sign" }, |
188 | { Opt_ignore_signature, "signloosely" }, | ||
186 | { Opt_seal, "seal" }, | 189 | { Opt_seal, "seal" }, |
187 | { Opt_noac, "noac" }, | 190 | { Opt_noac, "noac" }, |
188 | { Opt_fsc, "fsc" }, | 191 | { Opt_fsc, "fsc" }, |
@@ -206,6 +209,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
206 | { Opt_dirmode, "dirmode=%s" }, | 209 | { Opt_dirmode, "dirmode=%s" }, |
207 | { Opt_dirmode, "dir_mode=%s" }, | 210 | { Opt_dirmode, "dir_mode=%s" }, |
208 | { Opt_port, "port=%s" }, | 211 | { Opt_port, "port=%s" }, |
212 | { Opt_min_enc_offload, "esize=%s" }, | ||
209 | { Opt_blocksize, "bsize=%s" }, | 213 | { Opt_blocksize, "bsize=%s" }, |
210 | { Opt_rsize, "rsize=%s" }, | 214 | { Opt_rsize, "rsize=%s" }, |
211 | { Opt_wsize, "wsize=%s" }, | 215 | { Opt_wsize, "wsize=%s" }, |
@@ -262,6 +266,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
262 | { Opt_ignore, "nomand" }, | 266 | { Opt_ignore, "nomand" }, |
263 | { Opt_ignore, "relatime" }, | 267 | { Opt_ignore, "relatime" }, |
264 | { Opt_ignore, "_netdev" }, | 268 | { Opt_ignore, "_netdev" }, |
269 | { Opt_rootfs, "rootfs" }, | ||
265 | 270 | ||
266 | { Opt_err, NULL } | 271 | { Opt_err, NULL } |
267 | }; | 272 | }; |
@@ -298,6 +303,8 @@ enum { | |||
298 | Opt_cache_loose, | 303 | Opt_cache_loose, |
299 | Opt_cache_strict, | 304 | Opt_cache_strict, |
300 | Opt_cache_none, | 305 | Opt_cache_none, |
306 | Opt_cache_ro, | ||
307 | Opt_cache_rw, | ||
301 | Opt_cache_err | 308 | Opt_cache_err |
302 | }; | 309 | }; |
303 | 310 | ||
@@ -305,6 +312,8 @@ static const match_table_t cifs_cacheflavor_tokens = { | |||
305 | { Opt_cache_loose, "loose" }, | 312 | { Opt_cache_loose, "loose" }, |
306 | { Opt_cache_strict, "strict" }, | 313 | { Opt_cache_strict, "strict" }, |
307 | { Opt_cache_none, "none" }, | 314 | { Opt_cache_none, "none" }, |
315 | { Opt_cache_ro, "ro" }, | ||
316 | { Opt_cache_rw, "singleclient" }, | ||
308 | { Opt_cache_err, NULL } | 317 | { Opt_cache_err, NULL } |
309 | }; | 318 | }; |
310 | 319 | ||
@@ -489,7 +498,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
489 | } else { | 498 | } else { |
490 | rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it); | 499 | rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it); |
491 | if (rc && (rc != -EOPNOTSUPP)) { | 500 | if (rc && (rc != -EOPNOTSUPP)) { |
492 | cifs_dbg(VFS, "%s: no target servers for DFS failover\n", | 501 | cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n", |
493 | __func__); | 502 | __func__); |
494 | } else { | 503 | } else { |
495 | server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list); | 504 | server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list); |
@@ -617,12 +626,12 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
617 | rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1, | 626 | rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1, |
618 | tgt_it); | 627 | tgt_it); |
619 | if (rc) { | 628 | if (rc) { |
620 | cifs_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n", | 629 | cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n", |
621 | __func__, rc); | 630 | __func__, rc); |
622 | } | 631 | } |
623 | rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server); | 632 | rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server); |
624 | if (rc) { | 633 | if (rc) { |
625 | cifs_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n", | 634 | cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n", |
626 | __func__, rc); | 635 | __func__, rc); |
627 | } | 636 | } |
628 | dfs_cache_free_tgts(&tgt_list); | 637 | dfs_cache_free_tgts(&tgt_list); |
@@ -678,7 +687,7 @@ allocate_buffers(struct TCP_Server_Info *server) | |||
678 | if (!server->bigbuf) { | 687 | if (!server->bigbuf) { |
679 | server->bigbuf = (char *)cifs_buf_get(); | 688 | server->bigbuf = (char *)cifs_buf_get(); |
680 | if (!server->bigbuf) { | 689 | if (!server->bigbuf) { |
681 | cifs_dbg(VFS, "No memory for large SMB response\n"); | 690 | cifs_server_dbg(VFS, "No memory for large SMB response\n"); |
682 | msleep(3000); | 691 | msleep(3000); |
683 | /* retry will check if exiting */ | 692 | /* retry will check if exiting */ |
684 | return false; | 693 | return false; |
@@ -691,7 +700,7 @@ allocate_buffers(struct TCP_Server_Info *server) | |||
691 | if (!server->smallbuf) { | 700 | if (!server->smallbuf) { |
692 | server->smallbuf = (char *)cifs_small_buf_get(); | 701 | server->smallbuf = (char *)cifs_small_buf_get(); |
693 | if (!server->smallbuf) { | 702 | if (!server->smallbuf) { |
694 | cifs_dbg(VFS, "No memory for SMB response\n"); | 703 | cifs_server_dbg(VFS, "No memory for SMB response\n"); |
695 | msleep(1000); | 704 | msleep(1000); |
696 | /* retry will check if exiting */ | 705 | /* retry will check if exiting */ |
697 | return false; | 706 | return false; |
@@ -712,7 +721,7 @@ server_unresponsive(struct TCP_Server_Info *server) | |||
712 | * We need to wait 3 echo intervals to make sure we handle such | 721 | * We need to wait 3 echo intervals to make sure we handle such |
713 | * situations right: | 722 | * situations right: |
714 | * 1s client sends a normal SMB request | 723 | * 1s client sends a normal SMB request |
715 | * 3s client gets a response | 724 | * 2s client gets a response |
716 | * 30s echo workqueue job pops, and decides we got a response recently | 725 | * 30s echo workqueue job pops, and decides we got a response recently |
717 | * and don't need to send another | 726 | * and don't need to send another |
718 | * ... | 727 | * ... |
@@ -722,8 +731,8 @@ server_unresponsive(struct TCP_Server_Info *server) | |||
722 | if ((server->tcpStatus == CifsGood || | 731 | if ((server->tcpStatus == CifsGood || |
723 | server->tcpStatus == CifsNeedNegotiate) && | 732 | server->tcpStatus == CifsNeedNegotiate) && |
724 | time_after(jiffies, server->lstrp + 3 * server->echo_interval)) { | 733 | time_after(jiffies, server->lstrp + 3 * server->echo_interval)) { |
725 | cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n", | 734 | cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n", |
726 | server->hostname, (3 * server->echo_interval) / HZ); | 735 | (3 * server->echo_interval) / HZ); |
727 | cifs_reconnect(server); | 736 | cifs_reconnect(server); |
728 | wake_up(&server->response_q); | 737 | wake_up(&server->response_q); |
729 | return true; | 738 | return true; |
@@ -861,7 +870,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type) | |||
861 | wake_up(&server->response_q); | 870 | wake_up(&server->response_q); |
862 | break; | 871 | break; |
863 | default: | 872 | default: |
864 | cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type); | 873 | cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type); |
865 | cifs_reconnect(server); | 874 | cifs_reconnect(server); |
866 | } | 875 | } |
867 | 876 | ||
@@ -1008,7 +1017,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
1008 | /* make sure this will fit in a large buffer */ | 1017 | /* make sure this will fit in a large buffer */ |
1009 | if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - | 1018 | if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - |
1010 | server->vals->header_preamble_size) { | 1019 | server->vals->header_preamble_size) { |
1011 | cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length); | 1020 | cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length); |
1012 | cifs_reconnect(server); | 1021 | cifs_reconnect(server); |
1013 | wake_up(&server->response_q); | 1022 | wake_up(&server->response_q); |
1014 | return -ECONNABORTED; | 1023 | return -ECONNABORTED; |
@@ -1149,7 +1158,7 @@ next_pdu: | |||
1149 | /* make sure we have enough to get to the MID */ | 1158 | /* make sure we have enough to get to the MID */ |
1150 | if (server->pdu_size < HEADER_SIZE(server) - 1 - | 1159 | if (server->pdu_size < HEADER_SIZE(server) - 1 - |
1151 | server->vals->header_preamble_size) { | 1160 | server->vals->header_preamble_size) { |
1152 | cifs_dbg(VFS, "SMB response too short (%u bytes)\n", | 1161 | cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n", |
1153 | server->pdu_size); | 1162 | server->pdu_size); |
1154 | cifs_reconnect(server); | 1163 | cifs_reconnect(server); |
1155 | wake_up(&server->response_q); | 1164 | wake_up(&server->response_q); |
@@ -1222,7 +1231,7 @@ next_pdu: | |||
1222 | smb2_add_credits_from_hdr(bufs[i], server); | 1231 | smb2_add_credits_from_hdr(bufs[i], server); |
1223 | cifs_dbg(FYI, "Received oplock break\n"); | 1232 | cifs_dbg(FYI, "Received oplock break\n"); |
1224 | } else { | 1233 | } else { |
1225 | cifs_dbg(VFS, "No task to wake, unknown frame " | 1234 | cifs_server_dbg(VFS, "No task to wake, unknown frame " |
1226 | "received! NumMids %d\n", | 1235 | "received! NumMids %d\n", |
1227 | atomic_read(&midCount)); | 1236 | atomic_read(&midCount)); |
1228 | cifs_dump_mem("Received Data is: ", bufs[i], | 1237 | cifs_dump_mem("Received Data is: ", bufs[i], |
@@ -1418,14 +1427,32 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol) | |||
1418 | case Opt_cache_loose: | 1427 | case Opt_cache_loose: |
1419 | vol->direct_io = false; | 1428 | vol->direct_io = false; |
1420 | vol->strict_io = false; | 1429 | vol->strict_io = false; |
1430 | vol->cache_ro = false; | ||
1431 | vol->cache_rw = false; | ||
1421 | break; | 1432 | break; |
1422 | case Opt_cache_strict: | 1433 | case Opt_cache_strict: |
1423 | vol->direct_io = false; | 1434 | vol->direct_io = false; |
1424 | vol->strict_io = true; | 1435 | vol->strict_io = true; |
1436 | vol->cache_ro = false; | ||
1437 | vol->cache_rw = false; | ||
1425 | break; | 1438 | break; |
1426 | case Opt_cache_none: | 1439 | case Opt_cache_none: |
1427 | vol->direct_io = true; | 1440 | vol->direct_io = true; |
1428 | vol->strict_io = false; | 1441 | vol->strict_io = false; |
1442 | vol->cache_ro = false; | ||
1443 | vol->cache_rw = false; | ||
1444 | break; | ||
1445 | case Opt_cache_ro: | ||
1446 | vol->direct_io = false; | ||
1447 | vol->strict_io = false; | ||
1448 | vol->cache_ro = true; | ||
1449 | vol->cache_rw = false; | ||
1450 | break; | ||
1451 | case Opt_cache_rw: | ||
1452 | vol->direct_io = false; | ||
1453 | vol->strict_io = false; | ||
1454 | vol->cache_ro = false; | ||
1455 | vol->cache_rw = true; | ||
1429 | break; | 1456 | break; |
1430 | default: | 1457 | default: |
1431 | cifs_dbg(VFS, "bad cache= option: %s\n", value); | 1458 | cifs_dbg(VFS, "bad cache= option: %s\n", value); |
@@ -1713,6 +1740,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1713 | case Opt_noautotune: | 1740 | case Opt_noautotune: |
1714 | vol->noautotune = 1; | 1741 | vol->noautotune = 1; |
1715 | break; | 1742 | break; |
1743 | case Opt_nolease: | ||
1744 | vol->no_lease = 1; | ||
1745 | break; | ||
1716 | case Opt_hard: | 1746 | case Opt_hard: |
1717 | vol->retry = 1; | 1747 | vol->retry = 1; |
1718 | break; | 1748 | break; |
@@ -1748,6 +1778,11 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1748 | case Opt_nodfs: | 1778 | case Opt_nodfs: |
1749 | vol->nodfs = 1; | 1779 | vol->nodfs = 1; |
1750 | break; | 1780 | break; |
1781 | case Opt_rootfs: | ||
1782 | #ifdef CONFIG_CIFS_ROOT | ||
1783 | vol->rootfs = true; | ||
1784 | #endif | ||
1785 | break; | ||
1751 | case Opt_posixpaths: | 1786 | case Opt_posixpaths: |
1752 | vol->posix_paths = 1; | 1787 | vol->posix_paths = 1; |
1753 | break; | 1788 | break; |
@@ -1855,6 +1890,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1855 | case Opt_sign: | 1890 | case Opt_sign: |
1856 | vol->sign = true; | 1891 | vol->sign = true; |
1857 | break; | 1892 | break; |
1893 | case Opt_ignore_signature: | ||
1894 | vol->sign = true; | ||
1895 | vol->ignore_signature = true; | ||
1896 | break; | ||
1858 | case Opt_seal: | 1897 | case Opt_seal: |
1859 | /* we do not do the following in secFlags because seal | 1898 | /* we do not do the following in secFlags because seal |
1860 | * is a per tree connection (mount) not a per socket | 1899 | * is a per tree connection (mount) not a per socket |
@@ -1989,6 +2028,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1989 | } | 2028 | } |
1990 | port = (unsigned short)option; | 2029 | port = (unsigned short)option; |
1991 | break; | 2030 | break; |
2031 | case Opt_min_enc_offload: | ||
2032 | if (get_option_ul(args, &option)) { | ||
2033 | cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n"); | ||
2034 | goto cifs_parse_mount_err; | ||
2035 | } | ||
2036 | vol->min_offload = option; | ||
2037 | break; | ||
1992 | case Opt_blocksize: | 2038 | case Opt_blocksize: |
1993 | if (get_option_ul(args, &option)) { | 2039 | if (get_option_ul(args, &option)) { |
1994 | cifs_dbg(VFS, "%s: Invalid blocksize value\n", | 2040 | cifs_dbg(VFS, "%s: Invalid blocksize value\n", |
@@ -2586,6 +2632,12 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) | |||
2586 | if (server->rdma != vol->rdma) | 2632 | if (server->rdma != vol->rdma) |
2587 | return 0; | 2633 | return 0; |
2588 | 2634 | ||
2635 | if (server->ignore_signature != vol->ignore_signature) | ||
2636 | return 0; | ||
2637 | |||
2638 | if (server->min_offload != vol->min_offload) | ||
2639 | return 0; | ||
2640 | |||
2589 | return 1; | 2641 | return 1; |
2590 | } | 2642 | } |
2591 | 2643 | ||
@@ -2681,11 +2733,13 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
2681 | goto out_err_crypto_release; | 2733 | goto out_err_crypto_release; |
2682 | } | 2734 | } |
2683 | 2735 | ||
2684 | tcp_ses->noblocksnd = volume_info->noblocksnd; | 2736 | tcp_ses->noblockcnt = volume_info->rootfs; |
2737 | tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs; | ||
2685 | tcp_ses->noautotune = volume_info->noautotune; | 2738 | tcp_ses->noautotune = volume_info->noautotune; |
2686 | tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; | 2739 | tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; |
2687 | tcp_ses->rdma = volume_info->rdma; | 2740 | tcp_ses->rdma = volume_info->rdma; |
2688 | tcp_ses->in_flight = 0; | 2741 | tcp_ses->in_flight = 0; |
2742 | tcp_ses->max_in_flight = 0; | ||
2689 | tcp_ses->credits = 1; | 2743 | tcp_ses->credits = 1; |
2690 | init_waitqueue_head(&tcp_ses->response_q); | 2744 | init_waitqueue_head(&tcp_ses->response_q); |
2691 | init_waitqueue_head(&tcp_ses->request_q); | 2745 | init_waitqueue_head(&tcp_ses->request_q); |
@@ -2760,10 +2814,11 @@ smbd_connected: | |||
2760 | module_put(THIS_MODULE); | 2814 | module_put(THIS_MODULE); |
2761 | goto out_err_crypto_release; | 2815 | goto out_err_crypto_release; |
2762 | } | 2816 | } |
2817 | tcp_ses->min_offload = volume_info->min_offload; | ||
2763 | tcp_ses->tcpStatus = CifsNeedNegotiate; | 2818 | tcp_ses->tcpStatus = CifsNeedNegotiate; |
2764 | 2819 | ||
2765 | tcp_ses->nr_targets = 1; | 2820 | tcp_ses->nr_targets = 1; |
2766 | 2821 | tcp_ses->ignore_signature = volume_info->ignore_signature; | |
2767 | /* thread spawned, put it on the list */ | 2822 | /* thread spawned, put it on the list */ |
2768 | spin_lock(&cifs_tcp_ses_lock); | 2823 | spin_lock(&cifs_tcp_ses_lock); |
2769 | list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); | 2824 | list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); |
@@ -2840,16 +2895,17 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2840 | struct nls_table *nls_codepage; | 2895 | struct nls_table *nls_codepage; |
2841 | char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0}; | 2896 | char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0}; |
2842 | bool seal = false; | 2897 | bool seal = false; |
2898 | struct TCP_Server_Info *server = ses->server; | ||
2843 | 2899 | ||
2844 | /* | 2900 | /* |
2845 | * If the mount request that resulted in the creation of the | 2901 | * If the mount request that resulted in the creation of the |
2846 | * session requires encryption, force IPC to be encrypted too. | 2902 | * session requires encryption, force IPC to be encrypted too. |
2847 | */ | 2903 | */ |
2848 | if (volume_info->seal) { | 2904 | if (volume_info->seal) { |
2849 | if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) | 2905 | if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) |
2850 | seal = true; | 2906 | seal = true; |
2851 | else { | 2907 | else { |
2852 | cifs_dbg(VFS, | 2908 | cifs_server_dbg(VFS, |
2853 | "IPC: server doesn't support encryption\n"); | 2909 | "IPC: server doesn't support encryption\n"); |
2854 | return -EOPNOTSUPP; | 2910 | return -EOPNOTSUPP; |
2855 | } | 2911 | } |
@@ -2859,7 +2915,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2859 | if (tcon == NULL) | 2915 | if (tcon == NULL) |
2860 | return -ENOMEM; | 2916 | return -ENOMEM; |
2861 | 2917 | ||
2862 | scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname); | 2918 | scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname); |
2863 | 2919 | ||
2864 | /* cannot fail */ | 2920 | /* cannot fail */ |
2865 | nls_codepage = load_nls_default(); | 2921 | nls_codepage = load_nls_default(); |
@@ -2868,11 +2924,11 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2868 | tcon->ses = ses; | 2924 | tcon->ses = ses; |
2869 | tcon->ipc = true; | 2925 | tcon->ipc = true; |
2870 | tcon->seal = seal; | 2926 | tcon->seal = seal; |
2871 | rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage); | 2927 | rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage); |
2872 | free_xid(xid); | 2928 | free_xid(xid); |
2873 | 2929 | ||
2874 | if (rc) { | 2930 | if (rc) { |
2875 | cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc); | 2931 | cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc); |
2876 | tconInfoFree(tcon); | 2932 | tconInfoFree(tcon); |
2877 | goto out; | 2933 | goto out; |
2878 | } | 2934 | } |
@@ -2958,7 +3014,7 @@ void cifs_put_smb_ses(struct cifs_ses *ses) | |||
2958 | xid = get_xid(); | 3014 | xid = get_xid(); |
2959 | rc = server->ops->logoff(xid, ses); | 3015 | rc = server->ops->logoff(xid, ses); |
2960 | if (rc) | 3016 | if (rc) |
2961 | cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n", | 3017 | cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n", |
2962 | __func__, rc); | 3018 | __func__, rc); |
2963 | _free_xid(xid); | 3019 | _free_xid(xid); |
2964 | } | 3020 | } |
@@ -3212,7 +3268,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
3212 | 3268 | ||
3213 | ses->sectype = volume_info->sectype; | 3269 | ses->sectype = volume_info->sectype; |
3214 | ses->sign = volume_info->sign; | 3270 | ses->sign = volume_info->sign; |
3215 | |||
3216 | mutex_lock(&ses->session_mutex); | 3271 | mutex_lock(&ses->session_mutex); |
3217 | rc = cifs_negotiate_protocol(xid, ses); | 3272 | rc = cifs_negotiate_protocol(xid, ses); |
3218 | if (!rc) | 3273 | if (!rc) |
@@ -3250,6 +3305,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info) | |||
3250 | return 0; | 3305 | return 0; |
3251 | if (tcon->handle_timeout != volume_info->handle_timeout) | 3306 | if (tcon->handle_timeout != volume_info->handle_timeout) |
3252 | return 0; | 3307 | return 0; |
3308 | if (tcon->no_lease != volume_info->no_lease) | ||
3309 | return 0; | ||
3253 | return 1; | 3310 | return 1; |
3254 | } | 3311 | } |
3255 | 3312 | ||
@@ -3455,6 +3512,14 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
3455 | tcon->use_resilient = true; | 3512 | tcon->use_resilient = true; |
3456 | } | 3513 | } |
3457 | 3514 | ||
3515 | /* If the user really knows what they are doing they can override */ | ||
3516 | if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) { | ||
3517 | if (volume_info->cache_ro) | ||
3518 | cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n"); | ||
3519 | else if (volume_info->cache_rw) | ||
3520 | cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n"); | ||
3521 | } | ||
3522 | |||
3458 | /* | 3523 | /* |
3459 | * We can have only one retry value for a connection to a share so for | 3524 | * We can have only one retry value for a connection to a share so for |
3460 | * resources mounted more than once to the same server share the last | 3525 | * resources mounted more than once to the same server share the last |
@@ -3464,6 +3529,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
3464 | tcon->nocase = volume_info->nocase; | 3529 | tcon->nocase = volume_info->nocase; |
3465 | tcon->nohandlecache = volume_info->nohandlecache; | 3530 | tcon->nohandlecache = volume_info->nohandlecache; |
3466 | tcon->local_lease = volume_info->local_lease; | 3531 | tcon->local_lease = volume_info->local_lease; |
3532 | tcon->no_lease = volume_info->no_lease; | ||
3467 | INIT_LIST_HEAD(&tcon->pending_opens); | 3533 | INIT_LIST_HEAD(&tcon->pending_opens); |
3468 | 3534 | ||
3469 | spin_lock(&cifs_tcp_ses_lock); | 3535 | spin_lock(&cifs_tcp_ses_lock); |
@@ -3659,10 +3725,10 @@ bind_socket(struct TCP_Server_Info *server) | |||
3659 | saddr4 = (struct sockaddr_in *)&server->srcaddr; | 3725 | saddr4 = (struct sockaddr_in *)&server->srcaddr; |
3660 | saddr6 = (struct sockaddr_in6 *)&server->srcaddr; | 3726 | saddr6 = (struct sockaddr_in6 *)&server->srcaddr; |
3661 | if (saddr6->sin6_family == AF_INET6) | 3727 | if (saddr6->sin6_family == AF_INET6) |
3662 | cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n", | 3728 | cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n", |
3663 | &saddr6->sin6_addr, rc); | 3729 | &saddr6->sin6_addr, rc); |
3664 | else | 3730 | else |
3665 | cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n", | 3731 | cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n", |
3666 | &saddr4->sin_addr.s_addr, rc); | 3732 | &saddr4->sin_addr.s_addr, rc); |
3667 | } | 3733 | } |
3668 | } | 3734 | } |
@@ -3766,7 +3832,7 @@ generic_ip_connect(struct TCP_Server_Info *server) | |||
3766 | rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM, | 3832 | rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM, |
3767 | IPPROTO_TCP, &socket, 1); | 3833 | IPPROTO_TCP, &socket, 1); |
3768 | if (rc < 0) { | 3834 | if (rc < 0) { |
3769 | cifs_dbg(VFS, "Error %d creating socket\n", rc); | 3835 | cifs_server_dbg(VFS, "Error %d creating socket\n", rc); |
3770 | server->ssocket = NULL; | 3836 | server->ssocket = NULL; |
3771 | return rc; | 3837 | return rc; |
3772 | } | 3838 | } |
@@ -3814,7 +3880,11 @@ generic_ip_connect(struct TCP_Server_Info *server) | |||
3814 | socket->sk->sk_sndbuf, | 3880 | socket->sk->sk_sndbuf, |
3815 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); | 3881 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); |
3816 | 3882 | ||
3817 | rc = socket->ops->connect(socket, saddr, slen, 0); | 3883 | rc = socket->ops->connect(socket, saddr, slen, |
3884 | server->noblockcnt ? O_NONBLOCK : 0); | ||
3885 | |||
3886 | if (rc == -EINPROGRESS) | ||
3887 | rc = 0; | ||
3818 | if (rc < 0) { | 3888 | if (rc < 0) { |
3819 | cifs_dbg(FYI, "Error %d connecting to server\n", rc); | 3889 | cifs_dbg(FYI, "Error %d connecting to server\n", rc); |
3820 | sock_release(socket); | 3890 | sock_release(socket); |
@@ -4040,6 +4110,14 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
4040 | cifs_dbg(FYI, "mounting share using direct i/o\n"); | 4110 | cifs_dbg(FYI, "mounting share using direct i/o\n"); |
4041 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 4111 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
4042 | } | 4112 | } |
4113 | if (pvolume_info->cache_ro) { | ||
4114 | cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n"); | ||
4115 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE; | ||
4116 | } else if (pvolume_info->cache_rw) { | ||
4117 | cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n"); | ||
4118 | cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE | | ||
4119 | CIFS_MOUNT_RW_CACHE); | ||
4120 | } | ||
4043 | if (pvolume_info->mfsymlinks) { | 4121 | if (pvolume_info->mfsymlinks) { |
4044 | if (pvolume_info->sfu_emul) { | 4122 | if (pvolume_info->sfu_emul) { |
4045 | /* | 4123 | /* |
@@ -4150,7 +4228,7 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, | |||
4150 | 4228 | ||
4151 | if ((vol->persistent == true) && (!(ses->server->capabilities & | 4229 | if ((vol->persistent == true) && (!(ses->server->capabilities & |
4152 | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) { | 4230 | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) { |
4153 | cifs_dbg(VFS, "persistent handles not supported by server\n"); | 4231 | cifs_server_dbg(VFS, "persistent handles not supported by server\n"); |
4154 | return -EOPNOTSUPP; | 4232 | return -EOPNOTSUPP; |
4155 | } | 4233 | } |
4156 | 4234 | ||
@@ -4182,8 +4260,18 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, | |||
4182 | tcon->unix_ext = 0; /* server does not support them */ | 4260 | tcon->unix_ext = 0; /* server does not support them */ |
4183 | 4261 | ||
4184 | /* do not care if a following call succeed - informational */ | 4262 | /* do not care if a following call succeed - informational */ |
4185 | if (!tcon->pipe && server->ops->qfs_tcon) | 4263 | if (!tcon->pipe && server->ops->qfs_tcon) { |
4186 | server->ops->qfs_tcon(*xid, tcon); | 4264 | server->ops->qfs_tcon(*xid, tcon); |
4265 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { | ||
4266 | if (tcon->fsDevInfo.DeviceCharacteristics & | ||
4267 | FILE_READ_ONLY_DEVICE) | ||
4268 | cifs_dbg(VFS, "mounted to read only share\n"); | ||
4269 | else if ((cifs_sb->mnt_cifs_flags & | ||
4270 | CIFS_MOUNT_RW_CACHE) == 0) | ||
4271 | cifs_dbg(VFS, "read only mount of RW share\n"); | ||
4272 | /* no need to log a RW mount of a typical RW share */ | ||
4273 | } | ||
4274 | } | ||
4187 | 4275 | ||
4188 | cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol); | 4276 | cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol); |
4189 | cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol); | 4277 | cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol); |
@@ -4588,7 +4676,7 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, | |||
4588 | rc = cifs_are_all_path_components_accessible(server, xid, tcon, | 4676 | rc = cifs_are_all_path_components_accessible(server, xid, tcon, |
4589 | cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS); | 4677 | cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS); |
4590 | if (rc != 0) { | 4678 | if (rc != 0) { |
4591 | cifs_dbg(VFS, "cannot query dirs between root and final path, " | 4679 | cifs_server_dbg(VFS, "cannot query dirs between root and final path, " |
4592 | "enabling CIFS_MOUNT_USE_PREFIX_PATH\n"); | 4680 | "enabling CIFS_MOUNT_USE_PREFIX_PATH\n"); |
4593 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; | 4681 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; |
4594 | rc = 0; | 4682 | rc = 0; |
@@ -5090,7 +5178,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, | |||
5090 | rc = server->ops->sess_setup(xid, ses, nls_info); | 5178 | rc = server->ops->sess_setup(xid, ses, nls_info); |
5091 | 5179 | ||
5092 | if (rc) | 5180 | if (rc) |
5093 | cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc); | 5181 | cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); |
5094 | 5182 | ||
5095 | return rc; | 5183 | return rc; |
5096 | } | 5184 | } |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index be424e81e3ad..dd5ac841aefa 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -125,7 +125,7 @@ cifs_bp_rename_retry: | |||
125 | } | 125 | } |
126 | rcu_read_unlock(); | 126 | rcu_read_unlock(); |
127 | 127 | ||
128 | full_path = kmalloc(namelen+1, GFP_KERNEL); | 128 | full_path = kmalloc(namelen+1, GFP_ATOMIC); |
129 | if (full_path == NULL) | 129 | if (full_path == NULL) |
130 | return full_path; | 130 | return full_path; |
131 | full_path[namelen] = 0; /* trailing null */ | 131 | full_path[namelen] = 0; /* trailing null */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 97090693d182..4b95700c507c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1693,9 +1693,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) | |||
1693 | bool posix_lck = false; | 1693 | bool posix_lck = false; |
1694 | struct cifs_sb_info *cifs_sb; | 1694 | struct cifs_sb_info *cifs_sb; |
1695 | struct cifs_tcon *tcon; | 1695 | struct cifs_tcon *tcon; |
1696 | struct cifsInodeInfo *cinode; | ||
1697 | struct cifsFileInfo *cfile; | 1696 | struct cifsFileInfo *cfile; |
1698 | __u16 netfid; | ||
1699 | __u32 type; | 1697 | __u32 type; |
1700 | 1698 | ||
1701 | rc = -EACCES; | 1699 | rc = -EACCES; |
@@ -1711,8 +1709,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) | |||
1711 | cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag, | 1709 | cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag, |
1712 | tcon->ses->server); | 1710 | tcon->ses->server); |
1713 | cifs_sb = CIFS_FILE_SB(file); | 1711 | cifs_sb = CIFS_FILE_SB(file); |
1714 | netfid = cfile->fid.netfid; | ||
1715 | cinode = CIFS_I(file_inode(file)); | ||
1716 | 1712 | ||
1717 | if (cap_unix(tcon->ses) && | 1713 | if (cap_unix(tcon->ses) && |
1718 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && | 1714 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && |
@@ -1764,7 +1760,6 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, | |||
1764 | int rc = 0; | 1760 | int rc = 0; |
1765 | unsigned int bytes_written = 0; | 1761 | unsigned int bytes_written = 0; |
1766 | unsigned int total_written; | 1762 | unsigned int total_written; |
1767 | struct cifs_sb_info *cifs_sb; | ||
1768 | struct cifs_tcon *tcon; | 1763 | struct cifs_tcon *tcon; |
1769 | struct TCP_Server_Info *server; | 1764 | struct TCP_Server_Info *server; |
1770 | unsigned int xid; | 1765 | unsigned int xid; |
@@ -1772,8 +1767,6 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, | |||
1772 | struct cifsInodeInfo *cifsi = CIFS_I(d_inode(dentry)); | 1767 | struct cifsInodeInfo *cifsi = CIFS_I(d_inode(dentry)); |
1773 | struct cifs_io_parms io_parms; | 1768 | struct cifs_io_parms io_parms; |
1774 | 1769 | ||
1775 | cifs_sb = CIFS_SB(dentry->d_sb); | ||
1776 | |||
1777 | cifs_dbg(FYI, "write %zd bytes to offset %lld of %pd\n", | 1770 | cifs_dbg(FYI, "write %zd bytes to offset %lld of %pd\n", |
1778 | write_size, *offset, dentry); | 1771 | write_size, *offset, dentry); |
1779 | 1772 | ||
@@ -1980,6 +1973,77 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) | |||
1980 | return cfile; | 1973 | return cfile; |
1981 | } | 1974 | } |
1982 | 1975 | ||
1976 | int | ||
1977 | cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, | ||
1978 | struct cifsFileInfo **ret_file) | ||
1979 | { | ||
1980 | struct list_head *tmp; | ||
1981 | struct cifsFileInfo *cfile; | ||
1982 | struct cifsInodeInfo *cinode; | ||
1983 | char *full_path; | ||
1984 | |||
1985 | *ret_file = NULL; | ||
1986 | |||
1987 | spin_lock(&tcon->open_file_lock); | ||
1988 | list_for_each(tmp, &tcon->openFileList) { | ||
1989 | cfile = list_entry(tmp, struct cifsFileInfo, | ||
1990 | tlist); | ||
1991 | full_path = build_path_from_dentry(cfile->dentry); | ||
1992 | if (full_path == NULL) { | ||
1993 | spin_unlock(&tcon->open_file_lock); | ||
1994 | return -ENOMEM; | ||
1995 | } | ||
1996 | if (strcmp(full_path, name)) { | ||
1997 | kfree(full_path); | ||
1998 | continue; | ||
1999 | } | ||
2000 | |||
2001 | kfree(full_path); | ||
2002 | cinode = CIFS_I(d_inode(cfile->dentry)); | ||
2003 | spin_unlock(&tcon->open_file_lock); | ||
2004 | return cifs_get_writable_file(cinode, 0, ret_file); | ||
2005 | } | ||
2006 | |||
2007 | spin_unlock(&tcon->open_file_lock); | ||
2008 | return -ENOENT; | ||
2009 | } | ||
2010 | |||
2011 | int | ||
2012 | cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, | ||
2013 | struct cifsFileInfo **ret_file) | ||
2014 | { | ||
2015 | struct list_head *tmp; | ||
2016 | struct cifsFileInfo *cfile; | ||
2017 | struct cifsInodeInfo *cinode; | ||
2018 | char *full_path; | ||
2019 | |||
2020 | *ret_file = NULL; | ||
2021 | |||
2022 | spin_lock(&tcon->open_file_lock); | ||
2023 | list_for_each(tmp, &tcon->openFileList) { | ||
2024 | cfile = list_entry(tmp, struct cifsFileInfo, | ||
2025 | tlist); | ||
2026 | full_path = build_path_from_dentry(cfile->dentry); | ||
2027 | if (full_path == NULL) { | ||
2028 | spin_unlock(&tcon->open_file_lock); | ||
2029 | return -ENOMEM; | ||
2030 | } | ||
2031 | if (strcmp(full_path, name)) { | ||
2032 | kfree(full_path); | ||
2033 | continue; | ||
2034 | } | ||
2035 | |||
2036 | kfree(full_path); | ||
2037 | cinode = CIFS_I(d_inode(cfile->dentry)); | ||
2038 | spin_unlock(&tcon->open_file_lock); | ||
2039 | *ret_file = find_readable_file(cinode, 0); | ||
2040 | return *ret_file ? 0 : -ENOENT; | ||
2041 | } | ||
2042 | |||
2043 | spin_unlock(&tcon->open_file_lock); | ||
2044 | return -ENOENT; | ||
2045 | } | ||
2046 | |||
1983 | static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | 2047 | static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) |
1984 | { | 2048 | { |
1985 | struct address_space *mapping = page->mapping; | 2049 | struct address_space *mapping = page->mapping; |
@@ -3577,10 +3641,8 @@ collect_uncached_read_data(struct cifs_aio_ctx *ctx) | |||
3577 | struct cifs_readdata *rdata, *tmp; | 3641 | struct cifs_readdata *rdata, *tmp; |
3578 | struct iov_iter *to = &ctx->iter; | 3642 | struct iov_iter *to = &ctx->iter; |
3579 | struct cifs_sb_info *cifs_sb; | 3643 | struct cifs_sb_info *cifs_sb; |
3580 | struct cifs_tcon *tcon; | ||
3581 | int rc; | 3644 | int rc; |
3582 | 3645 | ||
3583 | tcon = tlink_tcon(ctx->cfile->tlink); | ||
3584 | cifs_sb = CIFS_SB(ctx->cfile->dentry->d_sb); | 3646 | cifs_sb = CIFS_SB(ctx->cfile->dentry->d_sb); |
3585 | 3647 | ||
3586 | mutex_lock(&ctx->aio_mutex); | 3648 | mutex_lock(&ctx->aio_mutex); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 56ca4b8ccaba..26cdfbf1e164 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -893,8 +893,17 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
893 | } | 893 | } |
894 | 894 | ||
895 | /* fill in 0777 bits from ACL */ | 895 | /* fill in 0777 bits from ACL */ |
896 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 896 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) { |
897 | rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid); | 897 | rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true, |
898 | full_path, fid); | ||
899 | if (rc) { | ||
900 | cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n", | ||
901 | __func__, rc); | ||
902 | goto cgii_exit; | ||
903 | } | ||
904 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
905 | rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false, | ||
906 | full_path, fid); | ||
898 | if (rc) { | 907 | if (rc) { |
899 | cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n", | 908 | cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n", |
900 | __func__, rc); | 909 | __func__, rc); |
@@ -2480,7 +2489,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
2480 | if (attrs->ia_valid & ATTR_GID) | 2489 | if (attrs->ia_valid & ATTR_GID) |
2481 | gid = attrs->ia_gid; | 2490 | gid = attrs->ia_gid; |
2482 | 2491 | ||
2483 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 2492 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) || |
2493 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) { | ||
2484 | if (uid_valid(uid) || gid_valid(gid)) { | 2494 | if (uid_valid(uid) || gid_valid(gid)) { |
2485 | rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64, | 2495 | rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64, |
2486 | uid, gid); | 2496 | uid, gid); |
@@ -2501,7 +2511,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
2501 | if (attrs->ia_valid & ATTR_MODE) { | 2511 | if (attrs->ia_valid & ATTR_MODE) { |
2502 | mode = attrs->ia_mode; | 2512 | mode = attrs->ia_mode; |
2503 | rc = 0; | 2513 | rc = 0; |
2504 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 2514 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) || |
2515 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) { | ||
2505 | rc = id_mode_to_cifs_acl(inode, full_path, mode, | 2516 | rc = id_mode_to_cifs_acl(inode, full_path, mode, |
2506 | INVALID_UID, INVALID_GID); | 2517 | INVALID_UID, INVALID_GID); |
2507 | if (rc) { | 2518 | if (rc) { |
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index d8d9cdfa30b6..d2a3fb7e5c8d 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c | |||
@@ -51,7 +51,8 @@ static int | |||
51 | smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, | 51 | smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, |
52 | struct cifs_sb_info *cifs_sb, const char *full_path, | 52 | struct cifs_sb_info *cifs_sb, const char *full_path, |
53 | __u32 desired_access, __u32 create_disposition, | 53 | __u32 desired_access, __u32 create_disposition, |
54 | __u32 create_options, void *ptr, int command) | 54 | __u32 create_options, void *ptr, int command, |
55 | struct cifsFileInfo *cfile) | ||
55 | { | 56 | { |
56 | int rc; | 57 | int rc; |
57 | __le16 *utf16_path = NULL; | 58 | __le16 *utf16_path = NULL; |
@@ -83,10 +84,16 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, | |||
83 | resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; | 84 | resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; |
84 | memset(rsp_iov, 0, sizeof(rsp_iov)); | 85 | memset(rsp_iov, 0, sizeof(rsp_iov)); |
85 | 86 | ||
87 | /* We already have a handle so we can skip the open */ | ||
88 | if (cfile) | ||
89 | goto after_open; | ||
90 | |||
86 | /* Open */ | 91 | /* Open */ |
87 | utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); | 92 | utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); |
88 | if (!utf16_path) | 93 | if (!utf16_path) { |
89 | return -ENOMEM; | 94 | rc = -ENOMEM; |
95 | goto finished; | ||
96 | } | ||
90 | 97 | ||
91 | oparms.tcon = tcon; | 98 | oparms.tcon = tcon; |
92 | oparms.desired_access = desired_access; | 99 | oparms.desired_access = desired_access; |
@@ -106,7 +113,10 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, | |||
106 | if (rc) | 113 | if (rc) |
107 | goto finished; | 114 | goto finished; |
108 | 115 | ||
109 | smb2_set_next_command(tcon, &rqst[num_rqst++]); | 116 | smb2_set_next_command(tcon, &rqst[num_rqst]); |
117 | after_open: | ||
118 | num_rqst++; | ||
119 | rc = 0; | ||
110 | 120 | ||
111 | /* Operation */ | 121 | /* Operation */ |
112 | switch (command) { | 122 | switch (command) { |
@@ -115,15 +125,31 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, | |||
115 | rqst[num_rqst].rq_iov = qi_iov; | 125 | rqst[num_rqst].rq_iov = qi_iov; |
116 | rqst[num_rqst].rq_nvec = 1; | 126 | rqst[num_rqst].rq_nvec = 1; |
117 | 127 | ||
118 | rc = SMB2_query_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, | 128 | if (cfile) |
119 | COMPOUND_FID, FILE_ALL_INFORMATION, | 129 | rc = SMB2_query_info_init(tcon, &rqst[num_rqst], |
130 | cfile->fid.persistent_fid, | ||
131 | cfile->fid.volatile_fid, | ||
132 | FILE_ALL_INFORMATION, | ||
133 | SMB2_O_INFO_FILE, 0, | ||
134 | sizeof(struct smb2_file_all_info) + | ||
135 | PATH_MAX * 2, 0, NULL); | ||
136 | else { | ||
137 | rc = SMB2_query_info_init(tcon, &rqst[num_rqst], | ||
138 | COMPOUND_FID, | ||
139 | COMPOUND_FID, | ||
140 | FILE_ALL_INFORMATION, | ||
120 | SMB2_O_INFO_FILE, 0, | 141 | SMB2_O_INFO_FILE, 0, |
121 | sizeof(struct smb2_file_all_info) + | 142 | sizeof(struct smb2_file_all_info) + |
122 | PATH_MAX * 2, 0, NULL); | 143 | PATH_MAX * 2, 0, NULL); |
144 | if (!rc) { | ||
145 | smb2_set_next_command(tcon, &rqst[num_rqst]); | ||
146 | smb2_set_related(&rqst[num_rqst]); | ||
147 | } | ||
148 | } | ||
149 | |||
123 | if (rc) | 150 | if (rc) |
124 | goto finished; | 151 | goto finished; |
125 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 152 | num_rqst++; |
126 | smb2_set_related(&rqst[num_rqst++]); | ||
127 | trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid, | 153 | trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid, |
128 | full_path); | 154 | full_path); |
129 | break; | 155 | break; |
@@ -182,14 +208,27 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, | |||
182 | size[0] = sizeof(FILE_BASIC_INFO); | 208 | size[0] = sizeof(FILE_BASIC_INFO); |
183 | data[0] = ptr; | 209 | data[0] = ptr; |
184 | 210 | ||
185 | rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, | 211 | if (cfile) |
186 | COMPOUND_FID, current->tgid, | 212 | rc = SMB2_set_info_init(tcon, &rqst[num_rqst], |
187 | FILE_BASIC_INFORMATION, | 213 | cfile->fid.persistent_fid, |
188 | SMB2_O_INFO_FILE, 0, data, size); | 214 | cfile->fid.volatile_fid, current->tgid, |
215 | FILE_BASIC_INFORMATION, | ||
216 | SMB2_O_INFO_FILE, 0, data, size); | ||
217 | else { | ||
218 | rc = SMB2_set_info_init(tcon, &rqst[num_rqst], | ||
219 | COMPOUND_FID, | ||
220 | COMPOUND_FID, current->tgid, | ||
221 | FILE_BASIC_INFORMATION, | ||
222 | SMB2_O_INFO_FILE, 0, data, size); | ||
223 | if (!rc) { | ||
224 | smb2_set_next_command(tcon, &rqst[num_rqst]); | ||
225 | smb2_set_related(&rqst[num_rqst]); | ||
226 | } | ||
227 | } | ||
228 | |||
189 | if (rc) | 229 | if (rc) |
190 | goto finished; | 230 | goto finished; |
191 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 231 | num_rqst++; |
192 | smb2_set_related(&rqst[num_rqst++]); | ||
193 | trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid, | 232 | trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid, |
194 | full_path); | 233 | full_path); |
195 | break; | 234 | break; |
@@ -210,14 +249,25 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, | |||
210 | size[1] = len + 2 /* null */; | 249 | size[1] = len + 2 /* null */; |
211 | data[1] = (__le16 *)ptr; | 250 | data[1] = (__le16 *)ptr; |
212 | 251 | ||
213 | rc = SMB2_set_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, | 252 | if (cfile) |
214 | COMPOUND_FID, current->tgid, | 253 | rc = SMB2_set_info_init(tcon, &rqst[num_rqst], |
215 | FILE_RENAME_INFORMATION, | 254 | cfile->fid.persistent_fid, |
255 | cfile->fid.volatile_fid, | ||
256 | current->tgid, FILE_RENAME_INFORMATION, | ||
257 | SMB2_O_INFO_FILE, 0, data, size); | ||
258 | else { | ||
259 | rc = SMB2_set_info_init(tcon, &rqst[num_rqst], | ||
260 | COMPOUND_FID, COMPOUND_FID, | ||
261 | current->tgid, FILE_RENAME_INFORMATION, | ||
216 | SMB2_O_INFO_FILE, 0, data, size); | 262 | SMB2_O_INFO_FILE, 0, data, size); |
263 | if (!rc) { | ||
264 | smb2_set_next_command(tcon, &rqst[num_rqst]); | ||
265 | smb2_set_related(&rqst[num_rqst]); | ||
266 | } | ||
267 | } | ||
217 | if (rc) | 268 | if (rc) |
218 | goto finished; | 269 | goto finished; |
219 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 270 | num_rqst++; |
220 | smb2_set_related(&rqst[num_rqst++]); | ||
221 | trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path); | 271 | trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path); |
222 | break; | 272 | break; |
223 | case SMB2_OP_HARDLINK: | 273 | case SMB2_OP_HARDLINK: |
@@ -254,21 +304,43 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, | |||
254 | if (rc) | 304 | if (rc) |
255 | goto finished; | 305 | goto finished; |
256 | 306 | ||
307 | /* We already have a handle so we can skip the close */ | ||
308 | if (cfile) | ||
309 | goto after_close; | ||
257 | /* Close */ | 310 | /* Close */ |
258 | memset(&close_iov, 0, sizeof(close_iov)); | 311 | memset(&close_iov, 0, sizeof(close_iov)); |
259 | rqst[num_rqst].rq_iov = close_iov; | 312 | rqst[num_rqst].rq_iov = close_iov; |
260 | rqst[num_rqst].rq_nvec = 1; | 313 | rqst[num_rqst].rq_nvec = 1; |
261 | rc = SMB2_close_init(tcon, &rqst[num_rqst], COMPOUND_FID, | 314 | rc = SMB2_close_init(tcon, &rqst[num_rqst], COMPOUND_FID, |
262 | COMPOUND_FID); | 315 | COMPOUND_FID); |
263 | smb2_set_related(&rqst[num_rqst++]); | 316 | smb2_set_related(&rqst[num_rqst]); |
264 | if (rc) | 317 | if (rc) |
265 | goto finished; | 318 | goto finished; |
266 | 319 | after_close: | |
267 | rc = compound_send_recv(xid, ses, flags, num_rqst, rqst, | 320 | num_rqst++; |
268 | resp_buftype, rsp_iov); | 321 | |
322 | if (cfile) { | ||
323 | cifsFileInfo_put(cfile); | ||
324 | cfile = NULL; | ||
325 | rc = compound_send_recv(xid, ses, flags, num_rqst - 2, | ||
326 | &rqst[1], &resp_buftype[1], | ||
327 | &rsp_iov[1]); | ||
328 | } else | ||
329 | rc = compound_send_recv(xid, ses, flags, num_rqst, | ||
330 | rqst, resp_buftype, | ||
331 | rsp_iov); | ||
269 | 332 | ||
270 | finished: | 333 | finished: |
334 | if (cfile) | ||
335 | cifsFileInfo_put(cfile); | ||
336 | |||
271 | SMB2_open_free(&rqst[0]); | 337 | SMB2_open_free(&rqst[0]); |
338 | if (rc == -EREMCHG) { | ||
339 | printk_once(KERN_WARNING "server share %s deleted\n", | ||
340 | tcon->treeName); | ||
341 | tcon->need_reconnect = true; | ||
342 | } | ||
343 | |||
272 | switch (command) { | 344 | switch (command) { |
273 | case SMB2_OP_QUERY_INFO: | 345 | case SMB2_OP_QUERY_INFO: |
274 | if (rc == 0) { | 346 | if (rc == 0) { |
@@ -371,6 +443,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
371 | __u32 create_options = 0; | 443 | __u32 create_options = 0; |
372 | struct cifs_fid fid; | 444 | struct cifs_fid fid; |
373 | bool no_cached_open = tcon->nohandlecache; | 445 | bool no_cached_open = tcon->nohandlecache; |
446 | struct cifsFileInfo *cfile; | ||
374 | 447 | ||
375 | *adjust_tz = false; | 448 | *adjust_tz = false; |
376 | *symlink = false; | 449 | *symlink = false; |
@@ -402,9 +475,10 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
402 | if (backup_cred(cifs_sb)) | 475 | if (backup_cred(cifs_sb)) |
403 | create_options |= CREATE_OPEN_BACKUP_INTENT; | 476 | create_options |= CREATE_OPEN_BACKUP_INTENT; |
404 | 477 | ||
478 | cifs_get_readable_path(tcon, full_path, &cfile); | ||
405 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, | 479 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, |
406 | FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, | 480 | FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, |
407 | smb2_data, SMB2_OP_QUERY_INFO); | 481 | smb2_data, SMB2_OP_QUERY_INFO, cfile); |
408 | if (rc == -EOPNOTSUPP) { | 482 | if (rc == -EOPNOTSUPP) { |
409 | *symlink = true; | 483 | *symlink = true; |
410 | create_options |= OPEN_REPARSE_POINT; | 484 | create_options |= OPEN_REPARSE_POINT; |
@@ -413,7 +487,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
413 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, | 487 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, |
414 | FILE_READ_ATTRIBUTES, FILE_OPEN, | 488 | FILE_READ_ATTRIBUTES, FILE_OPEN, |
415 | create_options, smb2_data, | 489 | create_options, smb2_data, |
416 | SMB2_OP_QUERY_INFO); | 490 | SMB2_OP_QUERY_INFO, NULL); |
417 | } | 491 | } |
418 | if (rc) | 492 | if (rc) |
419 | goto out; | 493 | goto out; |
@@ -430,7 +504,7 @@ smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, | |||
430 | { | 504 | { |
431 | return smb2_compound_op(xid, tcon, cifs_sb, name, | 505 | return smb2_compound_op(xid, tcon, cifs_sb, name, |
432 | FILE_WRITE_ATTRIBUTES, FILE_CREATE, | 506 | FILE_WRITE_ATTRIBUTES, FILE_CREATE, |
433 | CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR); | 507 | CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR, NULL); |
434 | } | 508 | } |
435 | 509 | ||
436 | void | 510 | void |
@@ -440,6 +514,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name, | |||
440 | { | 514 | { |
441 | FILE_BASIC_INFO data; | 515 | FILE_BASIC_INFO data; |
442 | struct cifsInodeInfo *cifs_i; | 516 | struct cifsInodeInfo *cifs_i; |
517 | struct cifsFileInfo *cfile; | ||
443 | u32 dosattrs; | 518 | u32 dosattrs; |
444 | int tmprc; | 519 | int tmprc; |
445 | 520 | ||
@@ -447,9 +522,11 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name, | |||
447 | cifs_i = CIFS_I(inode); | 522 | cifs_i = CIFS_I(inode); |
448 | dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; | 523 | dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; |
449 | data.Attributes = cpu_to_le32(dosattrs); | 524 | data.Attributes = cpu_to_le32(dosattrs); |
525 | cifs_get_writable_path(tcon, name, &cfile); | ||
450 | tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, | 526 | tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, |
451 | FILE_WRITE_ATTRIBUTES, FILE_CREATE, | 527 | FILE_WRITE_ATTRIBUTES, FILE_CREATE, |
452 | CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO); | 528 | CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO, |
529 | cfile); | ||
453 | if (tmprc == 0) | 530 | if (tmprc == 0) |
454 | cifs_i->cifsAttrs = dosattrs; | 531 | cifs_i->cifsAttrs = dosattrs; |
455 | } | 532 | } |
@@ -460,7 +537,7 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, | |||
460 | { | 537 | { |
461 | return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, | 538 | return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, |
462 | CREATE_NOT_FILE, | 539 | CREATE_NOT_FILE, |
463 | NULL, SMB2_OP_RMDIR); | 540 | NULL, SMB2_OP_RMDIR, NULL); |
464 | } | 541 | } |
465 | 542 | ||
466 | int | 543 | int |
@@ -469,13 +546,14 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name, | |||
469 | { | 546 | { |
470 | return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, | 547 | return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, |
471 | CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, | 548 | CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, |
472 | NULL, SMB2_OP_DELETE); | 549 | NULL, SMB2_OP_DELETE, NULL); |
473 | } | 550 | } |
474 | 551 | ||
475 | static int | 552 | static int |
476 | smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon, | 553 | smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon, |
477 | const char *from_name, const char *to_name, | 554 | const char *from_name, const char *to_name, |
478 | struct cifs_sb_info *cifs_sb, __u32 access, int command) | 555 | struct cifs_sb_info *cifs_sb, __u32 access, int command, |
556 | struct cifsFileInfo *cfile) | ||
479 | { | 557 | { |
480 | __le16 *smb2_to_name = NULL; | 558 | __le16 *smb2_to_name = NULL; |
481 | int rc; | 559 | int rc; |
@@ -486,7 +564,7 @@ smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon, | |||
486 | goto smb2_rename_path; | 564 | goto smb2_rename_path; |
487 | } | 565 | } |
488 | rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access, | 566 | rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access, |
489 | FILE_OPEN, 0, smb2_to_name, command); | 567 | FILE_OPEN, 0, smb2_to_name, command, cfile); |
490 | smb2_rename_path: | 568 | smb2_rename_path: |
491 | kfree(smb2_to_name); | 569 | kfree(smb2_to_name); |
492 | return rc; | 570 | return rc; |
@@ -497,8 +575,12 @@ smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon, | |||
497 | const char *from_name, const char *to_name, | 575 | const char *from_name, const char *to_name, |
498 | struct cifs_sb_info *cifs_sb) | 576 | struct cifs_sb_info *cifs_sb) |
499 | { | 577 | { |
500 | return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, | 578 | struct cifsFileInfo *cfile; |
501 | DELETE, SMB2_OP_RENAME); | 579 | |
580 | cifs_get_writable_path(tcon, from_name, &cfile); | ||
581 | |||
582 | return smb2_set_path_attr(xid, tcon, from_name, to_name, | ||
583 | cifs_sb, DELETE, SMB2_OP_RENAME, cfile); | ||
502 | } | 584 | } |
503 | 585 | ||
504 | int | 586 | int |
@@ -507,7 +589,8 @@ smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon, | |||
507 | struct cifs_sb_info *cifs_sb) | 589 | struct cifs_sb_info *cifs_sb) |
508 | { | 590 | { |
509 | return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, | 591 | return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, |
510 | FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK); | 592 | FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK, |
593 | NULL); | ||
511 | } | 594 | } |
512 | 595 | ||
513 | int | 596 | int |
@@ -519,7 +602,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, | |||
519 | 602 | ||
520 | return smb2_compound_op(xid, tcon, cifs_sb, full_path, | 603 | return smb2_compound_op(xid, tcon, cifs_sb, full_path, |
521 | FILE_WRITE_DATA, FILE_OPEN, 0, &eof, | 604 | FILE_WRITE_DATA, FILE_OPEN, 0, &eof, |
522 | SMB2_OP_SET_EOF); | 605 | SMB2_OP_SET_EOF, NULL); |
523 | } | 606 | } |
524 | 607 | ||
525 | int | 608 | int |
@@ -541,7 +624,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path, | |||
541 | 624 | ||
542 | rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path, | 625 | rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path, |
543 | FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf, | 626 | FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf, |
544 | SMB2_OP_SET_INFO); | 627 | SMB2_OP_SET_INFO, NULL); |
545 | cifs_put_tlink(tlink); | 628 | cifs_put_tlink(tlink); |
546 | return rc; | 629 | return rc; |
547 | } | 630 | } |
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c index 82ade16c9501..7fde3775cb57 100644 --- a/fs/cifs/smb2maperror.c +++ b/fs/cifs/smb2maperror.c | |||
@@ -511,7 +511,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { | |||
511 | {STATUS_PRINT_QUEUE_FULL, -EIO, "STATUS_PRINT_QUEUE_FULL"}, | 511 | {STATUS_PRINT_QUEUE_FULL, -EIO, "STATUS_PRINT_QUEUE_FULL"}, |
512 | {STATUS_NO_SPOOL_SPACE, -EIO, "STATUS_NO_SPOOL_SPACE"}, | 512 | {STATUS_NO_SPOOL_SPACE, -EIO, "STATUS_NO_SPOOL_SPACE"}, |
513 | {STATUS_PRINT_CANCELLED, -EIO, "STATUS_PRINT_CANCELLED"}, | 513 | {STATUS_PRINT_CANCELLED, -EIO, "STATUS_PRINT_CANCELLED"}, |
514 | {STATUS_NETWORK_NAME_DELETED, -EIO, "STATUS_NETWORK_NAME_DELETED"}, | 514 | {STATUS_NETWORK_NAME_DELETED, -EREMCHG, "STATUS_NETWORK_NAME_DELETED"}, |
515 | {STATUS_NETWORK_ACCESS_DENIED, -EACCES, "STATUS_NETWORK_ACCESS_DENIED"}, | 515 | {STATUS_NETWORK_ACCESS_DENIED, -EACCES, "STATUS_NETWORK_ACCESS_DENIED"}, |
516 | {STATUS_BAD_DEVICE_TYPE, -EIO, "STATUS_BAD_DEVICE_TYPE"}, | 516 | {STATUS_BAD_DEVICE_TYPE, -EIO, "STATUS_BAD_DEVICE_TYPE"}, |
517 | {STATUS_BAD_NETWORK_NAME, -ENOENT, "STATUS_BAD_NETWORK_NAME"}, | 517 | {STATUS_BAD_NETWORK_NAME, -ENOENT, "STATUS_BAD_NETWORK_NAME"}, |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 64a5864127be..eaed18061314 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -109,10 +109,10 @@ smb2_add_credits(struct TCP_Server_Info *server, | |||
109 | /* change_conf hasn't been executed */ | 109 | /* change_conf hasn't been executed */ |
110 | break; | 110 | break; |
111 | case 0: | 111 | case 0: |
112 | cifs_dbg(VFS, "Possible client or server bug - zero credits\n"); | 112 | cifs_server_dbg(VFS, "Possible client or server bug - zero credits\n"); |
113 | break; | 113 | break; |
114 | case 1: | 114 | case 1: |
115 | cifs_dbg(VFS, "disabling echoes and oplocks\n"); | 115 | cifs_server_dbg(VFS, "disabling echoes and oplocks\n"); |
116 | break; | 116 | break; |
117 | case 2: | 117 | case 2: |
118 | cifs_dbg(FYI, "disabling oplocks\n"); | 118 | cifs_dbg(FYI, "disabling oplocks\n"); |
@@ -203,6 +203,8 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size, | |||
203 | credits->instance = server->reconnect_instance; | 203 | credits->instance = server->reconnect_instance; |
204 | server->credits -= credits->value; | 204 | server->credits -= credits->value; |
205 | server->in_flight++; | 205 | server->in_flight++; |
206 | if (server->in_flight > server->max_in_flight) | ||
207 | server->max_in_flight = server->in_flight; | ||
206 | break; | 208 | break; |
207 | } | 209 | } |
208 | } | 210 | } |
@@ -230,7 +232,7 @@ smb2_adjust_credits(struct TCP_Server_Info *server, | |||
230 | 232 | ||
231 | if (server->reconnect_instance != credits->instance) { | 233 | if (server->reconnect_instance != credits->instance) { |
232 | spin_unlock(&server->req_lock); | 234 | spin_unlock(&server->req_lock); |
233 | cifs_dbg(VFS, "trying to return %d credits to old session\n", | 235 | cifs_server_dbg(VFS, "trying to return %d credits to old session\n", |
234 | credits->value - new_val); | 236 | credits->value - new_val); |
235 | return -EAGAIN; | 237 | return -EAGAIN; |
236 | } | 238 | } |
@@ -270,7 +272,7 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |||
270 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); | 272 | __u64 wire_mid = le64_to_cpu(shdr->MessageId); |
271 | 273 | ||
272 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { | 274 | if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { |
273 | cifs_dbg(VFS, "Encrypted frame parsing not supported yet\n"); | 275 | cifs_server_dbg(VFS, "Encrypted frame parsing not supported yet\n"); |
274 | return NULL; | 276 | return NULL; |
275 | } | 277 | } |
276 | 278 | ||
@@ -294,10 +296,10 @@ smb2_dump_detail(void *buf, struct TCP_Server_Info *server) | |||
294 | #ifdef CONFIG_CIFS_DEBUG2 | 296 | #ifdef CONFIG_CIFS_DEBUG2 |
295 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; | 297 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
296 | 298 | ||
297 | cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", | 299 | cifs_server_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", |
298 | shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, | 300 | shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, |
299 | shdr->ProcessId); | 301 | shdr->ProcessId); |
300 | cifs_dbg(VFS, "smb buf %p len %u\n", buf, | 302 | cifs_server_dbg(VFS, "smb buf %p len %u\n", buf, |
301 | server->ops->calc_smb_size(buf, server)); | 303 | server->ops->calc_smb_size(buf, server)); |
302 | #endif | 304 | #endif |
303 | } | 305 | } |
@@ -576,7 +578,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon) | |||
576 | "server does not support query network interfaces\n"); | 578 | "server does not support query network interfaces\n"); |
577 | goto out; | 579 | goto out; |
578 | } else if (rc != 0) { | 580 | } else if (rc != 0) { |
579 | cifs_dbg(VFS, "error %d on ioctl to get interface list\n", rc); | 581 | cifs_tcon_dbg(VFS, "error %d on ioctl to get interface list\n", rc); |
580 | goto out; | 582 | goto out; |
581 | } | 583 | } |
582 | 584 | ||
@@ -656,6 +658,15 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) | |||
656 | return 0; | 658 | return 0; |
657 | } | 659 | } |
658 | 660 | ||
661 | /* | ||
662 | * We do not hold the lock for the open because in case | ||
663 | * SMB2_open needs to reconnect, it will end up calling | ||
664 | * cifs_mark_open_files_invalid() which takes the lock again | ||
665 | * thus causing a deadlock | ||
666 | */ | ||
667 | |||
668 | mutex_unlock(&tcon->crfid.fid_mutex); | ||
669 | |||
659 | if (smb3_encryption_required(tcon)) | 670 | if (smb3_encryption_required(tcon)) |
660 | flags |= CIFS_TRANSFORM_REQ; | 671 | flags |= CIFS_TRANSFORM_REQ; |
661 | 672 | ||
@@ -677,7 +688,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) | |||
677 | 688 | ||
678 | rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, &utf16_path); | 689 | rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, &utf16_path); |
679 | if (rc) | 690 | if (rc) |
680 | goto oshr_exit; | 691 | goto oshr_free; |
681 | smb2_set_next_command(tcon, &rqst[0]); | 692 | smb2_set_next_command(tcon, &rqst[0]); |
682 | 693 | ||
683 | memset(&qi_iov, 0, sizeof(qi_iov)); | 694 | memset(&qi_iov, 0, sizeof(qi_iov)); |
@@ -690,18 +701,10 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) | |||
690 | sizeof(struct smb2_file_all_info) + | 701 | sizeof(struct smb2_file_all_info) + |
691 | PATH_MAX * 2, 0, NULL); | 702 | PATH_MAX * 2, 0, NULL); |
692 | if (rc) | 703 | if (rc) |
693 | goto oshr_exit; | 704 | goto oshr_free; |
694 | 705 | ||
695 | smb2_set_related(&rqst[1]); | 706 | smb2_set_related(&rqst[1]); |
696 | 707 | ||
697 | /* | ||
698 | * We do not hold the lock for the open because in case | ||
699 | * SMB2_open needs to reconnect, it will end up calling | ||
700 | * cifs_mark_open_files_invalid() which takes the lock again | ||
701 | * thus causing a deadlock | ||
702 | */ | ||
703 | |||
704 | mutex_unlock(&tcon->crfid.fid_mutex); | ||
705 | rc = compound_send_recv(xid, ses, flags, 2, rqst, | 708 | rc = compound_send_recv(xid, ses, flags, 2, rqst, |
706 | resp_buftype, rsp_iov); | 709 | resp_buftype, rsp_iov); |
707 | mutex_lock(&tcon->crfid.fid_mutex); | 710 | mutex_lock(&tcon->crfid.fid_mutex); |
@@ -739,8 +742,14 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) | |||
739 | 742 | ||
740 | /* Cached root is still invalid, continue normaly */ | 743 | /* Cached root is still invalid, continue normaly */ |
741 | 744 | ||
742 | if (rc) | 745 | if (rc) { |
746 | if (rc == -EREMCHG) { | ||
747 | tcon->need_reconnect = true; | ||
748 | printk_once(KERN_WARNING "server share %s deleted\n", | ||
749 | tcon->treeName); | ||
750 | } | ||
743 | goto oshr_exit; | 751 | goto oshr_exit; |
752 | } | ||
744 | 753 | ||
745 | o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base; | 754 | o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base; |
746 | oparms.fid->persistent_fid = o_rsp->PersistentFileId; | 755 | oparms.fid->persistent_fid = o_rsp->PersistentFileId; |
@@ -1330,11 +1339,11 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon, | |||
1330 | (char **)&res_key, &ret_data_len); | 1339 | (char **)&res_key, &ret_data_len); |
1331 | 1340 | ||
1332 | if (rc) { | 1341 | if (rc) { |
1333 | cifs_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc); | 1342 | cifs_tcon_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc); |
1334 | goto req_res_key_exit; | 1343 | goto req_res_key_exit; |
1335 | } | 1344 | } |
1336 | if (ret_data_len < sizeof(struct resume_key_req)) { | 1345 | if (ret_data_len < sizeof(struct resume_key_req)) { |
1337 | cifs_dbg(VFS, "Invalid refcopy resume key length\n"); | 1346 | cifs_tcon_dbg(VFS, "Invalid refcopy resume key length\n"); |
1338 | rc = -EINVAL; | 1347 | rc = -EINVAL; |
1339 | goto req_res_key_exit; | 1348 | goto req_res_key_exit; |
1340 | } | 1349 | } |
@@ -1369,7 +1378,10 @@ smb2_ioctl_query_info(const unsigned int xid, | |||
1369 | struct cifs_fid fid; | 1378 | struct cifs_fid fid; |
1370 | struct kvec qi_iov[1]; | 1379 | struct kvec qi_iov[1]; |
1371 | struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; | 1380 | struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; |
1381 | struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; | ||
1372 | struct kvec close_iov[1]; | 1382 | struct kvec close_iov[1]; |
1383 | unsigned int size[2]; | ||
1384 | void *data[2]; | ||
1373 | 1385 | ||
1374 | memset(rqst, 0, sizeof(rqst)); | 1386 | memset(rqst, 0, sizeof(rqst)); |
1375 | resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; | 1387 | resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; |
@@ -1404,7 +1416,6 @@ smb2_ioctl_query_info(const unsigned int xid, | |||
1404 | 1416 | ||
1405 | memset(&oparms, 0, sizeof(oparms)); | 1417 | memset(&oparms, 0, sizeof(oparms)); |
1406 | oparms.tcon = tcon; | 1418 | oparms.tcon = tcon; |
1407 | oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL; | ||
1408 | oparms.disposition = FILE_OPEN; | 1419 | oparms.disposition = FILE_OPEN; |
1409 | if (is_dir) | 1420 | if (is_dir) |
1410 | oparms.create_options = CREATE_NOT_FILE; | 1421 | oparms.create_options = CREATE_NOT_FILE; |
@@ -1413,9 +1424,6 @@ smb2_ioctl_query_info(const unsigned int xid, | |||
1413 | oparms.fid = &fid; | 1424 | oparms.fid = &fid; |
1414 | oparms.reconnect = false; | 1425 | oparms.reconnect = false; |
1415 | 1426 | ||
1416 | /* | ||
1417 | * FSCTL codes encode the special access they need in the fsctl code. | ||
1418 | */ | ||
1419 | if (qi.flags & PASSTHRU_FSCTL) { | 1427 | if (qi.flags & PASSTHRU_FSCTL) { |
1420 | switch (qi.info_type & FSCTL_DEVICE_ACCESS_MASK) { | 1428 | switch (qi.info_type & FSCTL_DEVICE_ACCESS_MASK) { |
1421 | case FSCTL_DEVICE_ACCESS_FILE_READ_WRITE_ACCESS: | 1429 | case FSCTL_DEVICE_ACCESS_FILE_READ_WRITE_ACCESS: |
@@ -1431,6 +1439,10 @@ smb2_ioctl_query_info(const unsigned int xid, | |||
1431 | oparms.desired_access = GENERIC_WRITE; | 1439 | oparms.desired_access = GENERIC_WRITE; |
1432 | break; | 1440 | break; |
1433 | } | 1441 | } |
1442 | } else if (qi.flags & PASSTHRU_SET_INFO) { | ||
1443 | oparms.desired_access = GENERIC_WRITE; | ||
1444 | } else { | ||
1445 | oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL; | ||
1434 | } | 1446 | } |
1435 | 1447 | ||
1436 | rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path); | 1448 | rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path); |
@@ -1454,6 +1466,24 @@ smb2_ioctl_query_info(const unsigned int xid, | |||
1454 | qi.output_buffer_length, | 1466 | qi.output_buffer_length, |
1455 | CIFSMaxBufSize); | 1467 | CIFSMaxBufSize); |
1456 | } | 1468 | } |
1469 | } else if (qi.flags == PASSTHRU_SET_INFO) { | ||
1470 | /* Can eventually relax perm check since server enforces too */ | ||
1471 | if (!capable(CAP_SYS_ADMIN)) | ||
1472 | rc = -EPERM; | ||
1473 | else { | ||
1474 | memset(&si_iov, 0, sizeof(si_iov)); | ||
1475 | rqst[1].rq_iov = si_iov; | ||
1476 | rqst[1].rq_nvec = 1; | ||
1477 | |||
1478 | size[0] = 8; | ||
1479 | data[0] = buffer; | ||
1480 | |||
1481 | rc = SMB2_set_info_init(tcon, &rqst[1], | ||
1482 | COMPOUND_FID, COMPOUND_FID, | ||
1483 | current->tgid, | ||
1484 | FILE_END_OF_FILE_INFORMATION, | ||
1485 | SMB2_O_INFO_FILE, 0, data, size); | ||
1486 | } | ||
1457 | } else if (qi.flags == PASSTHRU_QUERY_INFO) { | 1487 | } else if (qi.flags == PASSTHRU_QUERY_INFO) { |
1458 | memset(&qi_iov, 0, sizeof(qi_iov)); | 1488 | memset(&qi_iov, 0, sizeof(qi_iov)); |
1459 | rqst[1].rq_iov = qi_iov; | 1489 | rqst[1].rq_iov = qi_iov; |
@@ -1465,7 +1495,7 @@ smb2_ioctl_query_info(const unsigned int xid, | |||
1465 | qi.input_buffer_length, | 1495 | qi.input_buffer_length, |
1466 | qi.output_buffer_length, buffer); | 1496 | qi.output_buffer_length, buffer); |
1467 | } else { /* unknown flags */ | 1497 | } else { /* unknown flags */ |
1468 | cifs_dbg(VFS, "invalid passthru query flags: 0x%x\n", qi.flags); | 1498 | cifs_tcon_dbg(VFS, "invalid passthru query flags: 0x%x\n", qi.flags); |
1469 | rc = -EINVAL; | 1499 | rc = -EINVAL; |
1470 | } | 1500 | } |
1471 | 1501 | ||
@@ -1592,7 +1622,7 @@ smb2_copychunk_range(const unsigned int xid, | |||
1592 | if (rc == 0) { | 1622 | if (rc == 0) { |
1593 | if (ret_data_len != | 1623 | if (ret_data_len != |
1594 | sizeof(struct copychunk_ioctl_rsp)) { | 1624 | sizeof(struct copychunk_ioctl_rsp)) { |
1595 | cifs_dbg(VFS, "invalid cchunk response size\n"); | 1625 | cifs_tcon_dbg(VFS, "invalid cchunk response size\n"); |
1596 | rc = -EIO; | 1626 | rc = -EIO; |
1597 | goto cchunk_out; | 1627 | goto cchunk_out; |
1598 | } | 1628 | } |
@@ -1606,12 +1636,12 @@ smb2_copychunk_range(const unsigned int xid, | |||
1606 | */ | 1636 | */ |
1607 | if (le32_to_cpu(retbuf->TotalBytesWritten) > | 1637 | if (le32_to_cpu(retbuf->TotalBytesWritten) > |
1608 | le32_to_cpu(pcchunk->Length)) { | 1638 | le32_to_cpu(pcchunk->Length)) { |
1609 | cifs_dbg(VFS, "invalid copy chunk response\n"); | 1639 | cifs_tcon_dbg(VFS, "invalid copy chunk response\n"); |
1610 | rc = -EIO; | 1640 | rc = -EIO; |
1611 | goto cchunk_out; | 1641 | goto cchunk_out; |
1612 | } | 1642 | } |
1613 | if (le32_to_cpu(retbuf->ChunksWritten) != 1) { | 1643 | if (le32_to_cpu(retbuf->ChunksWritten) != 1) { |
1614 | cifs_dbg(VFS, "invalid num chunks written\n"); | 1644 | cifs_tcon_dbg(VFS, "invalid num chunks written\n"); |
1615 | rc = -EIO; | 1645 | rc = -EIO; |
1616 | goto cchunk_out; | 1646 | goto cchunk_out; |
1617 | } | 1647 | } |
@@ -2214,6 +2244,11 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, | |||
2214 | resp_buftype, rsp_iov); | 2244 | resp_buftype, rsp_iov); |
2215 | if (rc) { | 2245 | if (rc) { |
2216 | free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); | 2246 | free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); |
2247 | if (rc == -EREMCHG) { | ||
2248 | tcon->need_reconnect = true; | ||
2249 | printk_once(KERN_WARNING "server share %s deleted\n", | ||
2250 | tcon->treeName); | ||
2251 | } | ||
2217 | goto qic_exit; | 2252 | goto qic_exit; |
2218 | } | 2253 | } |
2219 | *rsp = rsp_iov[1]; | 2254 | *rsp = rsp_iov[1]; |
@@ -2401,7 +2436,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, | |||
2401 | 2436 | ||
2402 | if (rc) { | 2437 | if (rc) { |
2403 | if ((rc != -ENOENT) && (rc != -EOPNOTSUPP)) | 2438 | if ((rc != -ENOENT) && (rc != -EOPNOTSUPP)) |
2404 | cifs_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc); | 2439 | cifs_tcon_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc); |
2405 | goto out; | 2440 | goto out; |
2406 | } | 2441 | } |
2407 | 2442 | ||
@@ -2410,7 +2445,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, | |||
2410 | nls_codepage, remap, search_name, | 2445 | nls_codepage, remap, search_name, |
2411 | true /* is_unicode */); | 2446 | true /* is_unicode */); |
2412 | if (rc) { | 2447 | if (rc) { |
2413 | cifs_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc); | 2448 | cifs_tcon_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc); |
2414 | goto out; | 2449 | goto out; |
2415 | } | 2450 | } |
2416 | 2451 | ||
@@ -2640,7 +2675,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, | |||
2640 | 2675 | ||
2641 | if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) > | 2676 | if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) > |
2642 | rsp_iov[1].iov_len) { | 2677 | rsp_iov[1].iov_len) { |
2643 | cifs_dbg(VFS, "srv returned invalid ioctl len: %d\n", | 2678 | cifs_tcon_dbg(VFS, "srv returned invalid ioctl len: %d\n", |
2644 | plen); | 2679 | plen); |
2645 | rc = -EIO; | 2680 | rc = -EIO; |
2646 | goto querty_exit; | 2681 | goto querty_exit; |
@@ -2939,7 +2974,6 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, | |||
2939 | loff_t offset, loff_t len) | 2974 | loff_t offset, loff_t len) |
2940 | { | 2975 | { |
2941 | struct inode *inode; | 2976 | struct inode *inode; |
2942 | struct cifsInodeInfo *cifsi; | ||
2943 | struct cifsFileInfo *cfile = file->private_data; | 2977 | struct cifsFileInfo *cfile = file->private_data; |
2944 | struct file_zero_data_information fsctl_buf; | 2978 | struct file_zero_data_information fsctl_buf; |
2945 | long rc; | 2979 | long rc; |
@@ -2949,7 +2983,6 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, | |||
2949 | xid = get_xid(); | 2983 | xid = get_xid(); |
2950 | 2984 | ||
2951 | inode = d_inode(cfile->dentry); | 2985 | inode = d_inode(cfile->dentry); |
2952 | cifsi = CIFS_I(inode); | ||
2953 | 2986 | ||
2954 | /* Need to make file sparse, if not already, before freeing range. */ | 2987 | /* Need to make file sparse, if not already, before freeing range. */ |
2955 | /* Consider adding equivalent for compressed since it could also work */ | 2988 | /* Consider adding equivalent for compressed since it could also work */ |
@@ -3595,14 +3628,14 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
3595 | 3628 | ||
3596 | rc = smb2_get_enc_key(server, tr_hdr->SessionId, enc, key); | 3629 | rc = smb2_get_enc_key(server, tr_hdr->SessionId, enc, key); |
3597 | if (rc) { | 3630 | if (rc) { |
3598 | cifs_dbg(VFS, "%s: Could not get %scryption key\n", __func__, | 3631 | cifs_server_dbg(VFS, "%s: Could not get %scryption key\n", __func__, |
3599 | enc ? "en" : "de"); | 3632 | enc ? "en" : "de"); |
3600 | return 0; | 3633 | return 0; |
3601 | } | 3634 | } |
3602 | 3635 | ||
3603 | rc = smb3_crypto_aead_allocate(server); | 3636 | rc = smb3_crypto_aead_allocate(server); |
3604 | if (rc) { | 3637 | if (rc) { |
3605 | cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); | 3638 | cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__); |
3606 | return rc; | 3639 | return rc; |
3607 | } | 3640 | } |
3608 | 3641 | ||
@@ -3610,19 +3643,19 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
3610 | server->secmech.ccmaesdecrypt; | 3643 | server->secmech.ccmaesdecrypt; |
3611 | rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE); | 3644 | rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE); |
3612 | if (rc) { | 3645 | if (rc) { |
3613 | cifs_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc); | 3646 | cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc); |
3614 | return rc; | 3647 | return rc; |
3615 | } | 3648 | } |
3616 | 3649 | ||
3617 | rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE); | 3650 | rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE); |
3618 | if (rc) { | 3651 | if (rc) { |
3619 | cifs_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc); | 3652 | cifs_server_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc); |
3620 | return rc; | 3653 | return rc; |
3621 | } | 3654 | } |
3622 | 3655 | ||
3623 | req = aead_request_alloc(tfm, GFP_KERNEL); | 3656 | req = aead_request_alloc(tfm, GFP_KERNEL); |
3624 | if (!req) { | 3657 | if (!req) { |
3625 | cifs_dbg(VFS, "%s: Failed to alloc aead request\n", __func__); | 3658 | cifs_server_dbg(VFS, "%s: Failed to alloc aead request\n", __func__); |
3626 | return -ENOMEM; | 3659 | return -ENOMEM; |
3627 | } | 3660 | } |
3628 | 3661 | ||
@@ -3633,7 +3666,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
3633 | 3666 | ||
3634 | sg = init_sg(num_rqst, rqst, sign); | 3667 | sg = init_sg(num_rqst, rqst, sign); |
3635 | if (!sg) { | 3668 | if (!sg) { |
3636 | cifs_dbg(VFS, "%s: Failed to init sg\n", __func__); | 3669 | cifs_server_dbg(VFS, "%s: Failed to init sg\n", __func__); |
3637 | rc = -ENOMEM; | 3670 | rc = -ENOMEM; |
3638 | goto free_req; | 3671 | goto free_req; |
3639 | } | 3672 | } |
@@ -3641,7 +3674,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, | |||
3641 | iv_len = crypto_aead_ivsize(tfm); | 3674 | iv_len = crypto_aead_ivsize(tfm); |
3642 | iv = kzalloc(iv_len, GFP_KERNEL); | 3675 | iv = kzalloc(iv_len, GFP_KERNEL); |
3643 | if (!iv) { | 3676 | if (!iv) { |
3644 | cifs_dbg(VFS, "%s: Failed to alloc iv\n", __func__); | 3677 | cifs_server_dbg(VFS, "%s: Failed to alloc iv\n", __func__); |
3645 | rc = -ENOMEM; | 3678 | rc = -ENOMEM; |
3646 | goto free_sg; | 3679 | goto free_sg; |
3647 | } | 3680 | } |
@@ -3883,7 +3916,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, | |||
3883 | bool use_rdma_mr = false; | 3916 | bool use_rdma_mr = false; |
3884 | 3917 | ||
3885 | if (shdr->Command != SMB2_READ) { | 3918 | if (shdr->Command != SMB2_READ) { |
3886 | cifs_dbg(VFS, "only big read responses are supported\n"); | 3919 | cifs_server_dbg(VFS, "only big read responses are supported\n"); |
3887 | return -ENOTSUPP; | 3920 | return -ENOTSUPP; |
3888 | } | 3921 | } |
3889 | 3922 | ||
@@ -3998,8 +4031,55 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, | |||
3998 | return length; | 4031 | return length; |
3999 | } | 4032 | } |
4000 | 4033 | ||
4034 | struct smb2_decrypt_work { | ||
4035 | struct work_struct decrypt; | ||
4036 | struct TCP_Server_Info *server; | ||
4037 | struct page **ppages; | ||
4038 | char *buf; | ||
4039 | unsigned int npages; | ||
4040 | unsigned int len; | ||
4041 | }; | ||
4042 | |||
4043 | |||
4044 | static void smb2_decrypt_offload(struct work_struct *work) | ||
4045 | { | ||
4046 | struct smb2_decrypt_work *dw = container_of(work, | ||
4047 | struct smb2_decrypt_work, decrypt); | ||
4048 | int i, rc; | ||
4049 | struct mid_q_entry *mid; | ||
4050 | |||
4051 | rc = decrypt_raw_data(dw->server, dw->buf, dw->server->vals->read_rsp_size, | ||
4052 | dw->ppages, dw->npages, dw->len); | ||
4053 | if (rc) { | ||
4054 | cifs_dbg(VFS, "error decrypting rc=%d\n", rc); | ||
4055 | goto free_pages; | ||
4056 | } | ||
4057 | |||
4058 | dw->server->lstrp = jiffies; | ||
4059 | mid = smb2_find_mid(dw->server, dw->buf); | ||
4060 | if (mid == NULL) | ||
4061 | cifs_dbg(FYI, "mid not found\n"); | ||
4062 | else { | ||
4063 | mid->decrypted = true; | ||
4064 | rc = handle_read_data(dw->server, mid, dw->buf, | ||
4065 | dw->server->vals->read_rsp_size, | ||
4066 | dw->ppages, dw->npages, dw->len); | ||
4067 | mid->callback(mid); | ||
4068 | cifs_mid_q_entry_release(mid); | ||
4069 | } | ||
4070 | |||
4071 | free_pages: | ||
4072 | for (i = dw->npages-1; i >= 0; i--) | ||
4073 | put_page(dw->ppages[i]); | ||
4074 | |||
4075 | kfree(dw->ppages); | ||
4076 | cifs_small_buf_release(dw->buf); | ||
4077 | } | ||
4078 | |||
4079 | |||
4001 | static int | 4080 | static int |
4002 | receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) | 4081 | receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, |
4082 | int *num_mids) | ||
4003 | { | 4083 | { |
4004 | char *buf = server->smallbuf; | 4084 | char *buf = server->smallbuf; |
4005 | struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; | 4085 | struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; |
@@ -4009,7 +4089,9 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) | |||
4009 | unsigned int buflen = server->pdu_size; | 4089 | unsigned int buflen = server->pdu_size; |
4010 | int rc; | 4090 | int rc; |
4011 | int i = 0; | 4091 | int i = 0; |
4092 | struct smb2_decrypt_work *dw; | ||
4012 | 4093 | ||
4094 | *num_mids = 1; | ||
4013 | len = min_t(unsigned int, buflen, server->vals->read_rsp_size + | 4095 | len = min_t(unsigned int, buflen, server->vals->read_rsp_size + |
4014 | sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; | 4096 | sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; |
4015 | 4097 | ||
@@ -4045,6 +4127,32 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) | |||
4045 | if (rc) | 4127 | if (rc) |
4046 | goto free_pages; | 4128 | goto free_pages; |
4047 | 4129 | ||
4130 | /* | ||
4131 | * For large reads, offload to different thread for better performance, | ||
4132 | * use more cores decrypting which can be expensive | ||
4133 | */ | ||
4134 | |||
4135 | if ((server->min_offload) && (server->in_flight > 1) && | ||
4136 | (server->pdu_size >= server->min_offload)) { | ||
4137 | dw = kmalloc(sizeof(struct smb2_decrypt_work), GFP_KERNEL); | ||
4138 | if (dw == NULL) | ||
4139 | goto non_offloaded_decrypt; | ||
4140 | |||
4141 | dw->buf = server->smallbuf; | ||
4142 | server->smallbuf = (char *)cifs_small_buf_get(); | ||
4143 | |||
4144 | INIT_WORK(&dw->decrypt, smb2_decrypt_offload); | ||
4145 | |||
4146 | dw->npages = npages; | ||
4147 | dw->server = server; | ||
4148 | dw->ppages = pages; | ||
4149 | dw->len = len; | ||
4150 | queue_work(cifsiod_wq, &dw->decrypt); | ||
4151 | *num_mids = 0; /* worker thread takes care of finding mid */ | ||
4152 | return -1; | ||
4153 | } | ||
4154 | |||
4155 | non_offloaded_decrypt: | ||
4048 | rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size, | 4156 | rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size, |
4049 | pages, npages, len); | 4157 | pages, npages, len); |
4050 | if (rc) | 4158 | if (rc) |
@@ -4129,7 +4237,7 @@ one_more: | |||
4129 | } | 4237 | } |
4130 | 4238 | ||
4131 | if (*num_mids >= MAX_COMPOUND) { | 4239 | if (*num_mids >= MAX_COMPOUND) { |
4132 | cifs_dbg(VFS, "too many PDUs in compound\n"); | 4240 | cifs_server_dbg(VFS, "too many PDUs in compound\n"); |
4133 | return -1; | 4241 | return -1; |
4134 | } | 4242 | } |
4135 | bufs[*num_mids] = buf; | 4243 | bufs[*num_mids] = buf; |
@@ -4175,7 +4283,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, | |||
4175 | 4283 | ||
4176 | if (pdu_length < sizeof(struct smb2_transform_hdr) + | 4284 | if (pdu_length < sizeof(struct smb2_transform_hdr) + |
4177 | sizeof(struct smb2_sync_hdr)) { | 4285 | sizeof(struct smb2_sync_hdr)) { |
4178 | cifs_dbg(VFS, "Transform message is too small (%u)\n", | 4286 | cifs_server_dbg(VFS, "Transform message is too small (%u)\n", |
4179 | pdu_length); | 4287 | pdu_length); |
4180 | cifs_reconnect(server); | 4288 | cifs_reconnect(server); |
4181 | wake_up(&server->response_q); | 4289 | wake_up(&server->response_q); |
@@ -4183,7 +4291,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, | |||
4183 | } | 4291 | } |
4184 | 4292 | ||
4185 | if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) { | 4293 | if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) { |
4186 | cifs_dbg(VFS, "Transform message is broken\n"); | 4294 | cifs_server_dbg(VFS, "Transform message is broken\n"); |
4187 | cifs_reconnect(server); | 4295 | cifs_reconnect(server); |
4188 | wake_up(&server->response_q); | 4296 | wake_up(&server->response_q); |
4189 | return -ECONNABORTED; | 4297 | return -ECONNABORTED; |
@@ -4191,8 +4299,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, | |||
4191 | 4299 | ||
4192 | /* TODO: add support for compounds containing READ. */ | 4300 | /* TODO: add support for compounds containing READ. */ |
4193 | if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) { | 4301 | if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) { |
4194 | *num_mids = 1; | 4302 | return receive_encrypted_read(server, &mids[0], num_mids); |
4195 | return receive_encrypted_read(server, &mids[0]); | ||
4196 | } | 4303 | } |
4197 | 4304 | ||
4198 | return receive_encrypted_standard(server, mids, bufs, num_mids); | 4305 | return receive_encrypted_standard(server, mids, bufs, num_mids); |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 31e4a1b0b170..87066f1af12c 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -503,8 +503,7 @@ build_netname_ctxt(struct smb2_netname_neg_context *pneg_ctxt, char *hostname) | |||
503 | pneg_ctxt->ContextType = SMB2_NETNAME_NEGOTIATE_CONTEXT_ID; | 503 | pneg_ctxt->ContextType = SMB2_NETNAME_NEGOTIATE_CONTEXT_ID; |
504 | 504 | ||
505 | /* copy up to max of first 100 bytes of server name to NetName field */ | 505 | /* copy up to max of first 100 bytes of server name to NetName field */ |
506 | pneg_ctxt->DataLength = cpu_to_le16(2 + | 506 | pneg_ctxt->DataLength = cpu_to_le16(2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp)); |
507 | (2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp))); | ||
508 | /* context size is DataLength + minimal smb2_neg_context */ | 507 | /* context size is DataLength + minimal smb2_neg_context */ |
509 | return DIV_ROUND_UP(le16_to_cpu(pneg_ctxt->DataLength) + | 508 | return DIV_ROUND_UP(le16_to_cpu(pneg_ctxt->DataLength) + |
510 | sizeof(struct smb2_neg_context), 8) * 8; | 509 | sizeof(struct smb2_neg_context), 8) * 8; |
@@ -543,7 +542,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, | |||
543 | 542 | ||
544 | if (*total_len > 200) { | 543 | if (*total_len > 200) { |
545 | /* In case length corrupted don't want to overrun smb buffer */ | 544 | /* In case length corrupted don't want to overrun smb buffer */ |
546 | cifs_dbg(VFS, "Bad frame length assembling neg contexts\n"); | 545 | cifs_server_dbg(VFS, "Bad frame length assembling neg contexts\n"); |
547 | return; | 546 | return; |
548 | } | 547 | } |
549 | 548 | ||
@@ -661,7 +660,7 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, | |||
661 | 660 | ||
662 | cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt); | 661 | cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt); |
663 | if (len_of_smb <= offset) { | 662 | if (len_of_smb <= offset) { |
664 | cifs_dbg(VFS, "Invalid response: negotiate context offset\n"); | 663 | cifs_server_dbg(VFS, "Invalid response: negotiate context offset\n"); |
665 | return -EINVAL; | 664 | return -EINVAL; |
666 | } | 665 | } |
667 | 666 | ||
@@ -693,7 +692,7 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, | |||
693 | else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) | 692 | else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) |
694 | server->posix_ext_supported = true; | 693 | server->posix_ext_supported = true; |
695 | else | 694 | else |
696 | cifs_dbg(VFS, "unknown negcontext of type %d ignored\n", | 695 | cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n", |
697 | le16_to_cpu(pctx->ContextType)); | 696 | le16_to_cpu(pctx->ContextType)); |
698 | 697 | ||
699 | if (rc) | 698 | if (rc) |
@@ -818,7 +817,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
818 | req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); | 817 | req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); |
819 | req->DialectCount = cpu_to_le16(2); | 818 | req->DialectCount = cpu_to_le16(2); |
820 | total_len += 4; | 819 | total_len += 4; |
821 | } else if (strcmp(ses->server->vals->version_string, | 820 | } else if (strcmp(server->vals->version_string, |
822 | SMBDEFAULT_VERSION_STRING) == 0) { | 821 | SMBDEFAULT_VERSION_STRING) == 0) { |
823 | req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); | 822 | req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); |
824 | req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); | 823 | req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); |
@@ -841,16 +840,16 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
841 | else | 840 | else |
842 | req->SecurityMode = 0; | 841 | req->SecurityMode = 0; |
843 | 842 | ||
844 | req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities); | 843 | req->Capabilities = cpu_to_le32(server->vals->req_capabilities); |
845 | 844 | ||
846 | /* ClientGUID must be zero for SMB2.02 dialect */ | 845 | /* ClientGUID must be zero for SMB2.02 dialect */ |
847 | if (ses->server->vals->protocol_id == SMB20_PROT_ID) | 846 | if (server->vals->protocol_id == SMB20_PROT_ID) |
848 | memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE); | 847 | memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE); |
849 | else { | 848 | else { |
850 | memcpy(req->ClientGUID, server->client_guid, | 849 | memcpy(req->ClientGUID, server->client_guid, |
851 | SMB2_CLIENT_GUID_SIZE); | 850 | SMB2_CLIENT_GUID_SIZE); |
852 | if ((ses->server->vals->protocol_id == SMB311_PROT_ID) || | 851 | if ((server->vals->protocol_id == SMB311_PROT_ID) || |
853 | (strcmp(ses->server->vals->version_string, | 852 | (strcmp(server->vals->version_string, |
854 | SMBDEFAULT_VERSION_STRING) == 0)) | 853 | SMBDEFAULT_VERSION_STRING) == 0)) |
855 | assemble_neg_contexts(req, server, &total_len); | 854 | assemble_neg_contexts(req, server, &total_len); |
856 | } | 855 | } |
@@ -869,42 +868,42 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
869 | * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); | 868 | * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); |
870 | */ | 869 | */ |
871 | if (rc == -EOPNOTSUPP) { | 870 | if (rc == -EOPNOTSUPP) { |
872 | cifs_dbg(VFS, "Dialect not supported by server. Consider " | 871 | cifs_server_dbg(VFS, "Dialect not supported by server. Consider " |
873 | "specifying vers=1.0 or vers=2.0 on mount for accessing" | 872 | "specifying vers=1.0 or vers=2.0 on mount for accessing" |
874 | " older servers\n"); | 873 | " older servers\n"); |
875 | goto neg_exit; | 874 | goto neg_exit; |
876 | } else if (rc != 0) | 875 | } else if (rc != 0) |
877 | goto neg_exit; | 876 | goto neg_exit; |
878 | 877 | ||
879 | if (strcmp(ses->server->vals->version_string, | 878 | if (strcmp(server->vals->version_string, |
880 | SMB3ANY_VERSION_STRING) == 0) { | 879 | SMB3ANY_VERSION_STRING) == 0) { |
881 | if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { | 880 | if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { |
882 | cifs_dbg(VFS, | 881 | cifs_server_dbg(VFS, |
883 | "SMB2 dialect returned but not requested\n"); | 882 | "SMB2 dialect returned but not requested\n"); |
884 | return -EIO; | 883 | return -EIO; |
885 | } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { | 884 | } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { |
886 | cifs_dbg(VFS, | 885 | cifs_server_dbg(VFS, |
887 | "SMB2.1 dialect returned but not requested\n"); | 886 | "SMB2.1 dialect returned but not requested\n"); |
888 | return -EIO; | 887 | return -EIO; |
889 | } | 888 | } |
890 | } else if (strcmp(ses->server->vals->version_string, | 889 | } else if (strcmp(server->vals->version_string, |
891 | SMBDEFAULT_VERSION_STRING) == 0) { | 890 | SMBDEFAULT_VERSION_STRING) == 0) { |
892 | if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { | 891 | if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { |
893 | cifs_dbg(VFS, | 892 | cifs_server_dbg(VFS, |
894 | "SMB2 dialect returned but not requested\n"); | 893 | "SMB2 dialect returned but not requested\n"); |
895 | return -EIO; | 894 | return -EIO; |
896 | } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { | 895 | } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { |
897 | /* ops set to 3.0 by default for default so update */ | 896 | /* ops set to 3.0 by default for default so update */ |
898 | ses->server->ops = &smb21_operations; | 897 | server->ops = &smb21_operations; |
899 | ses->server->vals = &smb21_values; | 898 | server->vals = &smb21_values; |
900 | } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) { | 899 | } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) { |
901 | ses->server->ops = &smb311_operations; | 900 | server->ops = &smb311_operations; |
902 | ses->server->vals = &smb311_values; | 901 | server->vals = &smb311_values; |
903 | } | 902 | } |
904 | } else if (le16_to_cpu(rsp->DialectRevision) != | 903 | } else if (le16_to_cpu(rsp->DialectRevision) != |
905 | ses->server->vals->protocol_id) { | 904 | server->vals->protocol_id) { |
906 | /* if requested single dialect ensure returned dialect matched */ | 905 | /* if requested single dialect ensure returned dialect matched */ |
907 | cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n", | 906 | cifs_server_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n", |
908 | le16_to_cpu(rsp->DialectRevision)); | 907 | le16_to_cpu(rsp->DialectRevision)); |
909 | return -EIO; | 908 | return -EIO; |
910 | } | 909 | } |
@@ -922,7 +921,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
922 | else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) | 921 | else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) |
923 | cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n"); | 922 | cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n"); |
924 | else { | 923 | else { |
925 | cifs_dbg(VFS, "Illegal dialect returned by server 0x%x\n", | 924 | cifs_server_dbg(VFS, "Illegal dialect returned by server 0x%x\n", |
926 | le16_to_cpu(rsp->DialectRevision)); | 925 | le16_to_cpu(rsp->DialectRevision)); |
927 | rc = -EIO; | 926 | rc = -EIO; |
928 | goto neg_exit; | 927 | goto neg_exit; |
@@ -982,7 +981,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
982 | rc = smb311_decode_neg_context(rsp, server, | 981 | rc = smb311_decode_neg_context(rsp, server, |
983 | rsp_iov.iov_len); | 982 | rsp_iov.iov_len); |
984 | else | 983 | else |
985 | cifs_dbg(VFS, "Missing expected negotiate contexts\n"); | 984 | cifs_server_dbg(VFS, "Missing expected negotiate contexts\n"); |
986 | } | 985 | } |
987 | neg_exit: | 986 | neg_exit: |
988 | free_rsp_buf(resp_buftype, rsp); | 987 | free_rsp_buf(resp_buftype, rsp); |
@@ -996,11 +995,12 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
996 | struct validate_negotiate_info_rsp *pneg_rsp = NULL; | 995 | struct validate_negotiate_info_rsp *pneg_rsp = NULL; |
997 | u32 rsplen; | 996 | u32 rsplen; |
998 | u32 inbuflen; /* max of 4 dialects */ | 997 | u32 inbuflen; /* max of 4 dialects */ |
998 | struct TCP_Server_Info *server = tcon->ses->server; | ||
999 | 999 | ||
1000 | cifs_dbg(FYI, "validate negotiate\n"); | 1000 | cifs_dbg(FYI, "validate negotiate\n"); |
1001 | 1001 | ||
1002 | /* In SMB3.11 preauth integrity supersedes validate negotiate */ | 1002 | /* In SMB3.11 preauth integrity supersedes validate negotiate */ |
1003 | if (tcon->ses->server->dialect == SMB311_PROT_ID) | 1003 | if (server->dialect == SMB311_PROT_ID) |
1004 | return 0; | 1004 | return 0; |
1005 | 1005 | ||
1006 | /* | 1006 | /* |
@@ -1019,15 +1019,15 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) | 1021 | if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) |
1022 | cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); | 1022 | cifs_tcon_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); |
1023 | 1023 | ||
1024 | pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS); | 1024 | pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS); |
1025 | if (!pneg_inbuf) | 1025 | if (!pneg_inbuf) |
1026 | return -ENOMEM; | 1026 | return -ENOMEM; |
1027 | 1027 | ||
1028 | pneg_inbuf->Capabilities = | 1028 | pneg_inbuf->Capabilities = |
1029 | cpu_to_le32(tcon->ses->server->vals->req_capabilities); | 1029 | cpu_to_le32(server->vals->req_capabilities); |
1030 | memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid, | 1030 | memcpy(pneg_inbuf->Guid, server->client_guid, |
1031 | SMB2_CLIENT_GUID_SIZE); | 1031 | SMB2_CLIENT_GUID_SIZE); |
1032 | 1032 | ||
1033 | if (tcon->ses->sign) | 1033 | if (tcon->ses->sign) |
@@ -1040,7 +1040,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
1040 | pneg_inbuf->SecurityMode = 0; | 1040 | pneg_inbuf->SecurityMode = 0; |
1041 | 1041 | ||
1042 | 1042 | ||
1043 | if (strcmp(tcon->ses->server->vals->version_string, | 1043 | if (strcmp(server->vals->version_string, |
1044 | SMB3ANY_VERSION_STRING) == 0) { | 1044 | SMB3ANY_VERSION_STRING) == 0) { |
1045 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID); | 1045 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID); |
1046 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); | 1046 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); |
@@ -1048,7 +1048,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
1048 | /* structure is big enough for 3 dialects, sending only 2 */ | 1048 | /* structure is big enough for 3 dialects, sending only 2 */ |
1049 | inbuflen = sizeof(*pneg_inbuf) - | 1049 | inbuflen = sizeof(*pneg_inbuf) - |
1050 | (2 * sizeof(pneg_inbuf->Dialects[0])); | 1050 | (2 * sizeof(pneg_inbuf->Dialects[0])); |
1051 | } else if (strcmp(tcon->ses->server->vals->version_string, | 1051 | } else if (strcmp(server->vals->version_string, |
1052 | SMBDEFAULT_VERSION_STRING) == 0) { | 1052 | SMBDEFAULT_VERSION_STRING) == 0) { |
1053 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); | 1053 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); |
1054 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); | 1054 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); |
@@ -1060,7 +1060,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
1060 | } else { | 1060 | } else { |
1061 | /* otherwise specific dialect was requested */ | 1061 | /* otherwise specific dialect was requested */ |
1062 | pneg_inbuf->Dialects[0] = | 1062 | pneg_inbuf->Dialects[0] = |
1063 | cpu_to_le16(tcon->ses->server->vals->protocol_id); | 1063 | cpu_to_le16(server->vals->protocol_id); |
1064 | pneg_inbuf->DialectCount = cpu_to_le16(1); | 1064 | pneg_inbuf->DialectCount = cpu_to_le16(1); |
1065 | /* structure is big enough for 3 dialects, sending only 1 */ | 1065 | /* structure is big enough for 3 dialects, sending only 1 */ |
1066 | inbuflen = sizeof(*pneg_inbuf) - | 1066 | inbuflen = sizeof(*pneg_inbuf) - |
@@ -1076,18 +1076,18 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
1076 | * Old Windows versions or Netapp SMB server can return | 1076 | * Old Windows versions or Netapp SMB server can return |
1077 | * not supported error. Client should accept it. | 1077 | * not supported error. Client should accept it. |
1078 | */ | 1078 | */ |
1079 | cifs_dbg(VFS, "Server does not support validate negotiate\n"); | 1079 | cifs_tcon_dbg(VFS, "Server does not support validate negotiate\n"); |
1080 | rc = 0; | 1080 | rc = 0; |
1081 | goto out_free_inbuf; | 1081 | goto out_free_inbuf; |
1082 | } else if (rc != 0) { | 1082 | } else if (rc != 0) { |
1083 | cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); | 1083 | cifs_tcon_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); |
1084 | rc = -EIO; | 1084 | rc = -EIO; |
1085 | goto out_free_inbuf; | 1085 | goto out_free_inbuf; |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | rc = -EIO; | 1088 | rc = -EIO; |
1089 | if (rsplen != sizeof(*pneg_rsp)) { | 1089 | if (rsplen != sizeof(*pneg_rsp)) { |
1090 | cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n", | 1090 | cifs_tcon_dbg(VFS, "invalid protocol negotiate response size: %d\n", |
1091 | rsplen); | 1091 | rsplen); |
1092 | 1092 | ||
1093 | /* relax check since Mac returns max bufsize allowed on ioctl */ | 1093 | /* relax check since Mac returns max bufsize allowed on ioctl */ |
@@ -1096,16 +1096,16 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | /* check validate negotiate info response matches what we got earlier */ | 1098 | /* check validate negotiate info response matches what we got earlier */ |
1099 | if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect)) | 1099 | if (pneg_rsp->Dialect != cpu_to_le16(server->dialect)) |
1100 | goto vneg_out; | 1100 | goto vneg_out; |
1101 | 1101 | ||
1102 | if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode)) | 1102 | if (pneg_rsp->SecurityMode != cpu_to_le16(server->sec_mode)) |
1103 | goto vneg_out; | 1103 | goto vneg_out; |
1104 | 1104 | ||
1105 | /* do not validate server guid because not saved at negprot time yet */ | 1105 | /* do not validate server guid because not saved at negprot time yet */ |
1106 | 1106 | ||
1107 | if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND | | 1107 | if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND | |
1108 | SMB2_LARGE_FILES) != tcon->ses->server->capabilities) | 1108 | SMB2_LARGE_FILES) != server->capabilities) |
1109 | goto vneg_out; | 1109 | goto vneg_out; |
1110 | 1110 | ||
1111 | /* validate negotiate successful */ | 1111 | /* validate negotiate successful */ |
@@ -1114,7 +1114,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
1114 | goto out_free_rsp; | 1114 | goto out_free_rsp; |
1115 | 1115 | ||
1116 | vneg_out: | 1116 | vneg_out: |
1117 | cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); | 1117 | cifs_tcon_dbg(VFS, "protocol revalidation - security settings mismatch\n"); |
1118 | out_free_rsp: | 1118 | out_free_rsp: |
1119 | kfree(pneg_rsp); | 1119 | kfree(pneg_rsp); |
1120 | out_free_inbuf: | 1120 | out_free_inbuf: |
@@ -1568,7 +1568,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, | |||
1568 | sess_data->func(sess_data); | 1568 | sess_data->func(sess_data); |
1569 | 1569 | ||
1570 | if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign)) | 1570 | if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign)) |
1571 | cifs_dbg(VFS, "signing requested but authenticated as guest\n"); | 1571 | cifs_server_dbg(VFS, "signing requested but authenticated as guest\n"); |
1572 | rc = sess_data->result; | 1572 | rc = sess_data->result; |
1573 | out: | 1573 | out: |
1574 | kfree(sess_data); | 1574 | kfree(sess_data); |
@@ -1661,10 +1661,11 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1661 | __le16 *unc_path = NULL; | 1661 | __le16 *unc_path = NULL; |
1662 | int flags = 0; | 1662 | int flags = 0; |
1663 | unsigned int total_len; | 1663 | unsigned int total_len; |
1664 | struct TCP_Server_Info *server = ses->server; | ||
1664 | 1665 | ||
1665 | cifs_dbg(FYI, "TCON\n"); | 1666 | cifs_dbg(FYI, "TCON\n"); |
1666 | 1667 | ||
1667 | if (!(ses->server) || !tree) | 1668 | if (!server || !tree) |
1668 | return -EIO; | 1669 | return -EIO; |
1669 | 1670 | ||
1670 | unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); | 1671 | unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); |
@@ -1707,7 +1708,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1707 | * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1 | 1708 | * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1 |
1708 | * (Samba servers don't always set the flag so also check if null user) | 1709 | * (Samba servers don't always set the flag so also check if null user) |
1709 | */ | 1710 | */ |
1710 | if ((ses->server->dialect == SMB311_PROT_ID) && | 1711 | if ((server->dialect == SMB311_PROT_ID) && |
1711 | !smb3_encryption_required(tcon) && | 1712 | !smb3_encryption_required(tcon) && |
1712 | !(ses->session_flags & | 1713 | !(ses->session_flags & |
1713 | (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) && | 1714 | (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) && |
@@ -1746,7 +1747,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1746 | cifs_dbg(FYI, "connection to printer\n"); | 1747 | cifs_dbg(FYI, "connection to printer\n"); |
1747 | break; | 1748 | break; |
1748 | default: | 1749 | default: |
1749 | cifs_dbg(VFS, "unknown share type %d\n", rsp->ShareType); | 1750 | cifs_server_dbg(VFS, "unknown share type %d\n", rsp->ShareType); |
1750 | rc = -EOPNOTSUPP; | 1751 | rc = -EOPNOTSUPP; |
1751 | goto tcon_error_exit; | 1752 | goto tcon_error_exit; |
1752 | } | 1753 | } |
@@ -1761,15 +1762,15 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1761 | 1762 | ||
1762 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && | 1763 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && |
1763 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) | 1764 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) |
1764 | cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); | 1765 | cifs_tcon_dbg(VFS, "DFS capability contradicts DFS flag\n"); |
1765 | 1766 | ||
1766 | if (tcon->seal && | 1767 | if (tcon->seal && |
1767 | !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) | 1768 | !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) |
1768 | cifs_dbg(VFS, "Encryption is requested but not supported\n"); | 1769 | cifs_tcon_dbg(VFS, "Encryption is requested but not supported\n"); |
1769 | 1770 | ||
1770 | init_copy_chunk_defaults(tcon); | 1771 | init_copy_chunk_defaults(tcon); |
1771 | if (tcon->ses->server->ops->validate_negotiate) | 1772 | if (server->ops->validate_negotiate) |
1772 | rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); | 1773 | rc = server->ops->validate_negotiate(xid, tcon); |
1773 | tcon_exit: | 1774 | tcon_exit: |
1774 | 1775 | ||
1775 | free_rsp_buf(resp_buftype, rsp); | 1776 | free_rsp_buf(resp_buftype, rsp); |
@@ -1778,7 +1779,7 @@ tcon_exit: | |||
1778 | 1779 | ||
1779 | tcon_error_exit: | 1780 | tcon_error_exit: |
1780 | if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { | 1781 | if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { |
1781 | cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); | 1782 | cifs_tcon_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); |
1782 | } | 1783 | } |
1783 | goto tcon_exit; | 1784 | goto tcon_exit; |
1784 | } | 1785 | } |
@@ -2458,7 +2459,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, | |||
2458 | iov[1].iov_len = uni_path_len; | 2459 | iov[1].iov_len = uni_path_len; |
2459 | iov[1].iov_base = path; | 2460 | iov[1].iov_base = path; |
2460 | 2461 | ||
2461 | if (!server->oplocks) | 2462 | if ((!server->oplocks) || (tcon->no_lease)) |
2462 | *oplock = SMB2_OPLOCK_LEVEL_NONE; | 2463 | *oplock = SMB2_OPLOCK_LEVEL_NONE; |
2463 | 2464 | ||
2464 | if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) || | 2465 | if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) || |
@@ -2594,6 +2595,11 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
2594 | } | 2595 | } |
2595 | trace_smb3_open_err(xid, tcon->tid, ses->Suid, | 2596 | trace_smb3_open_err(xid, tcon->tid, ses->Suid, |
2596 | oparms->create_options, oparms->desired_access, rc); | 2597 | oparms->create_options, oparms->desired_access, rc); |
2598 | if (rc == -EREMCHG) { | ||
2599 | printk_once(KERN_WARNING "server share %s deleted\n", | ||
2600 | tcon->treeName); | ||
2601 | tcon->need_reconnect = true; | ||
2602 | } | ||
2597 | goto creat_exit; | 2603 | goto creat_exit; |
2598 | } else | 2604 | } else |
2599 | trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, | 2605 | trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, |
@@ -2742,6 +2748,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
2742 | int resp_buftype = CIFS_NO_BUFFER; | 2748 | int resp_buftype = CIFS_NO_BUFFER; |
2743 | int rc = 0; | 2749 | int rc = 0; |
2744 | int flags = 0; | 2750 | int flags = 0; |
2751 | struct TCP_Server_Info *server; | ||
2745 | 2752 | ||
2746 | cifs_dbg(FYI, "SMB2 IOCTL\n"); | 2753 | cifs_dbg(FYI, "SMB2 IOCTL\n"); |
2747 | 2754 | ||
@@ -2757,7 +2764,10 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
2757 | else | 2764 | else |
2758 | return -EIO; | 2765 | return -EIO; |
2759 | 2766 | ||
2760 | if (!ses || !(ses->server)) | 2767 | if (!ses) |
2768 | return -EIO; | ||
2769 | server = ses->server; | ||
2770 | if (!server) | ||
2761 | return -EIO; | 2771 | return -EIO; |
2762 | 2772 | ||
2763 | if (smb3_encryption_required(tcon)) | 2773 | if (smb3_encryption_required(tcon)) |
@@ -2807,14 +2817,14 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
2807 | if (*plen == 0) | 2817 | if (*plen == 0) |
2808 | goto ioctl_exit; /* server returned no data */ | 2818 | goto ioctl_exit; /* server returned no data */ |
2809 | else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) { | 2819 | else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) { |
2810 | cifs_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen); | 2820 | cifs_tcon_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen); |
2811 | *plen = 0; | 2821 | *plen = 0; |
2812 | rc = -EIO; | 2822 | rc = -EIO; |
2813 | goto ioctl_exit; | 2823 | goto ioctl_exit; |
2814 | } | 2824 | } |
2815 | 2825 | ||
2816 | if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) { | 2826 | if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) { |
2817 | cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, | 2827 | cifs_tcon_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, |
2818 | le32_to_cpu(rsp->OutputOffset)); | 2828 | le32_to_cpu(rsp->OutputOffset)); |
2819 | *plen = 0; | 2829 | *plen = 0; |
2820 | rc = -EIO; | 2830 | rc = -EIO; |
@@ -2913,6 +2923,7 @@ SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, | |||
2913 | rqst.rq_iov = iov; | 2923 | rqst.rq_iov = iov; |
2914 | rqst.rq_nvec = 1; | 2924 | rqst.rq_nvec = 1; |
2915 | 2925 | ||
2926 | trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid); | ||
2916 | rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid); | 2927 | rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid); |
2917 | if (rc) | 2928 | if (rc) |
2918 | goto close_exit; | 2929 | goto close_exit; |
@@ -2925,7 +2936,9 @@ SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, | |||
2925 | trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid, | 2936 | trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid, |
2926 | rc); | 2937 | rc); |
2927 | goto close_exit; | 2938 | goto close_exit; |
2928 | } | 2939 | } else |
2940 | trace_smb3_close_done(xid, persistent_fid, tcon->tid, | ||
2941 | ses->Suid); | ||
2929 | 2942 | ||
2930 | atomic_dec(&tcon->num_remote_opens); | 2943 | atomic_dec(&tcon->num_remote_opens); |
2931 | 2944 | ||
@@ -3055,12 +3068,16 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
3055 | int rc = 0; | 3068 | int rc = 0; |
3056 | int resp_buftype = CIFS_NO_BUFFER; | 3069 | int resp_buftype = CIFS_NO_BUFFER; |
3057 | struct cifs_ses *ses = tcon->ses; | 3070 | struct cifs_ses *ses = tcon->ses; |
3071 | struct TCP_Server_Info *server; | ||
3058 | int flags = 0; | 3072 | int flags = 0; |
3059 | bool allocated = false; | 3073 | bool allocated = false; |
3060 | 3074 | ||
3061 | cifs_dbg(FYI, "Query Info\n"); | 3075 | cifs_dbg(FYI, "Query Info\n"); |
3062 | 3076 | ||
3063 | if (!ses || !(ses->server)) | 3077 | if (!ses) |
3078 | return -EIO; | ||
3079 | server = ses->server; | ||
3080 | if (!server) | ||
3064 | return -EIO; | 3081 | return -EIO; |
3065 | 3082 | ||
3066 | if (smb3_encryption_required(tcon)) | 3083 | if (smb3_encryption_required(tcon)) |
@@ -3098,7 +3115,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
3098 | if (!*data) { | 3115 | if (!*data) { |
3099 | *data = kmalloc(*dlen, GFP_KERNEL); | 3116 | *data = kmalloc(*dlen, GFP_KERNEL); |
3100 | if (!*data) { | 3117 | if (!*data) { |
3101 | cifs_dbg(VFS, | 3118 | cifs_tcon_dbg(VFS, |
3102 | "Error %d allocating memory for acl\n", | 3119 | "Error %d allocating memory for acl\n", |
3103 | rc); | 3120 | rc); |
3104 | *dlen = 0; | 3121 | *dlen = 0; |
@@ -3159,6 +3176,91 @@ SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, | |||
3159 | } | 3176 | } |
3160 | 3177 | ||
3161 | /* | 3178 | /* |
3179 | * CHANGE_NOTIFY Request is sent to get notifications on changes to a directory | ||
3180 | * See MS-SMB2 2.2.35 and 2.2.36 | ||
3181 | */ | ||
3182 | |||
3183 | int | ||
3184 | SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst, | ||
3185 | struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, | ||
3186 | u32 completion_filter, bool watch_tree) | ||
3187 | { | ||
3188 | struct smb2_change_notify_req *req; | ||
3189 | struct kvec *iov = rqst->rq_iov; | ||
3190 | unsigned int total_len; | ||
3191 | int rc; | ||
3192 | |||
3193 | rc = smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, (void **) &req, &total_len); | ||
3194 | if (rc) | ||
3195 | return rc; | ||
3196 | |||
3197 | req->PersistentFileId = persistent_fid; | ||
3198 | req->VolatileFileId = volatile_fid; | ||
3199 | req->OutputBufferLength = SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE; | ||
3200 | req->CompletionFilter = cpu_to_le32(completion_filter); | ||
3201 | if (watch_tree) | ||
3202 | req->Flags = cpu_to_le16(SMB2_WATCH_TREE); | ||
3203 | else | ||
3204 | req->Flags = 0; | ||
3205 | |||
3206 | iov[0].iov_base = (char *)req; | ||
3207 | iov[0].iov_len = total_len; | ||
3208 | |||
3209 | return 0; | ||
3210 | } | ||
3211 | |||
3212 | int | ||
3213 | SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, | ||
3214 | u64 persistent_fid, u64 volatile_fid, bool watch_tree, | ||
3215 | u32 completion_filter) | ||
3216 | { | ||
3217 | struct cifs_ses *ses = tcon->ses; | ||
3218 | struct smb_rqst rqst; | ||
3219 | struct kvec iov[1]; | ||
3220 | struct kvec rsp_iov = {NULL, 0}; | ||
3221 | int resp_buftype = CIFS_NO_BUFFER; | ||
3222 | int flags = 0; | ||
3223 | int rc = 0; | ||
3224 | |||
3225 | cifs_dbg(FYI, "change notify\n"); | ||
3226 | if (!ses || !(ses->server)) | ||
3227 | return -EIO; | ||
3228 | |||
3229 | if (smb3_encryption_required(tcon)) | ||
3230 | flags |= CIFS_TRANSFORM_REQ; | ||
3231 | |||
3232 | memset(&rqst, 0, sizeof(struct smb_rqst)); | ||
3233 | memset(&iov, 0, sizeof(iov)); | ||
3234 | rqst.rq_iov = iov; | ||
3235 | rqst.rq_nvec = 1; | ||
3236 | |||
3237 | rc = SMB2_notify_init(xid, &rqst, tcon, persistent_fid, volatile_fid, | ||
3238 | completion_filter, watch_tree); | ||
3239 | if (rc) | ||
3240 | goto cnotify_exit; | ||
3241 | |||
3242 | trace_smb3_notify_enter(xid, persistent_fid, tcon->tid, ses->Suid, | ||
3243 | (u8)watch_tree, completion_filter); | ||
3244 | rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); | ||
3245 | |||
3246 | if (rc != 0) { | ||
3247 | cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE); | ||
3248 | trace_smb3_notify_err(xid, persistent_fid, tcon->tid, ses->Suid, | ||
3249 | (u8)watch_tree, completion_filter, rc); | ||
3250 | } else | ||
3251 | trace_smb3_notify_done(xid, persistent_fid, tcon->tid, | ||
3252 | ses->Suid, (u8)watch_tree, completion_filter); | ||
3253 | |||
3254 | cnotify_exit: | ||
3255 | if (rqst.rq_iov) | ||
3256 | cifs_small_buf_release(rqst.rq_iov[0].iov_base); /* request */ | ||
3257 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); | ||
3258 | return rc; | ||
3259 | } | ||
3260 | |||
3261 | |||
3262 | |||
3263 | /* | ||
3162 | * This is a no-op for now. We're not really interested in the reply, but | 3264 | * This is a no-op for now. We're not really interested in the reply, but |
3163 | * rather in the fact that the server sent one and that server->lstrp | 3265 | * rather in the fact that the server sent one and that server->lstrp |
3164 | * gets updated. | 3266 | * gets updated. |
@@ -3287,51 +3389,76 @@ SMB2_echo(struct TCP_Server_Info *server) | |||
3287 | return rc; | 3389 | return rc; |
3288 | } | 3390 | } |
3289 | 3391 | ||
3392 | void | ||
3393 | SMB2_flush_free(struct smb_rqst *rqst) | ||
3394 | { | ||
3395 | if (rqst && rqst->rq_iov) | ||
3396 | cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ | ||
3397 | } | ||
3398 | |||
3290 | int | 3399 | int |
3291 | SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | 3400 | SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst, |
3292 | u64 volatile_fid) | 3401 | struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid) |
3293 | { | 3402 | { |
3294 | struct smb_rqst rqst; | ||
3295 | struct smb2_flush_req *req; | 3403 | struct smb2_flush_req *req; |
3296 | struct cifs_ses *ses = tcon->ses; | 3404 | struct kvec *iov = rqst->rq_iov; |
3297 | struct kvec iov[1]; | ||
3298 | struct kvec rsp_iov; | ||
3299 | int resp_buftype; | ||
3300 | int rc = 0; | ||
3301 | int flags = 0; | ||
3302 | unsigned int total_len; | 3405 | unsigned int total_len; |
3303 | 3406 | int rc; | |
3304 | cifs_dbg(FYI, "Flush\n"); | ||
3305 | |||
3306 | if (!ses || !(ses->server)) | ||
3307 | return -EIO; | ||
3308 | 3407 | ||
3309 | rc = smb2_plain_req_init(SMB2_FLUSH, tcon, (void **) &req, &total_len); | 3408 | rc = smb2_plain_req_init(SMB2_FLUSH, tcon, (void **) &req, &total_len); |
3310 | if (rc) | 3409 | if (rc) |
3311 | return rc; | 3410 | return rc; |
3312 | 3411 | ||
3313 | if (smb3_encryption_required(tcon)) | ||
3314 | flags |= CIFS_TRANSFORM_REQ; | ||
3315 | |||
3316 | req->PersistentFileId = persistent_fid; | 3412 | req->PersistentFileId = persistent_fid; |
3317 | req->VolatileFileId = volatile_fid; | 3413 | req->VolatileFileId = volatile_fid; |
3318 | 3414 | ||
3319 | iov[0].iov_base = (char *)req; | 3415 | iov[0].iov_base = (char *)req; |
3320 | iov[0].iov_len = total_len; | 3416 | iov[0].iov_len = total_len; |
3321 | 3417 | ||
3418 | return 0; | ||
3419 | } | ||
3420 | |||
3421 | int | ||
3422 | SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | ||
3423 | u64 volatile_fid) | ||
3424 | { | ||
3425 | struct cifs_ses *ses = tcon->ses; | ||
3426 | struct smb_rqst rqst; | ||
3427 | struct kvec iov[1]; | ||
3428 | struct kvec rsp_iov = {NULL, 0}; | ||
3429 | int resp_buftype = CIFS_NO_BUFFER; | ||
3430 | int flags = 0; | ||
3431 | int rc = 0; | ||
3432 | |||
3433 | cifs_dbg(FYI, "flush\n"); | ||
3434 | if (!ses || !(ses->server)) | ||
3435 | return -EIO; | ||
3436 | |||
3437 | if (smb3_encryption_required(tcon)) | ||
3438 | flags |= CIFS_TRANSFORM_REQ; | ||
3439 | |||
3322 | memset(&rqst, 0, sizeof(struct smb_rqst)); | 3440 | memset(&rqst, 0, sizeof(struct smb_rqst)); |
3441 | memset(&iov, 0, sizeof(iov)); | ||
3323 | rqst.rq_iov = iov; | 3442 | rqst.rq_iov = iov; |
3324 | rqst.rq_nvec = 1; | 3443 | rqst.rq_nvec = 1; |
3325 | 3444 | ||
3445 | rc = SMB2_flush_init(xid, &rqst, tcon, persistent_fid, volatile_fid); | ||
3446 | if (rc) | ||
3447 | goto flush_exit; | ||
3448 | |||
3449 | trace_smb3_flush_enter(xid, persistent_fid, tcon->tid, ses->Suid); | ||
3326 | rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); | 3450 | rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
3327 | cifs_small_buf_release(req); | ||
3328 | 3451 | ||
3329 | if (rc != 0) { | 3452 | if (rc != 0) { |
3330 | cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); | 3453 | cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); |
3331 | trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid, | 3454 | trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid, |
3332 | rc); | 3455 | rc); |
3333 | } | 3456 | } else |
3457 | trace_smb3_flush_done(xid, persistent_fid, tcon->tid, | ||
3458 | ses->Suid); | ||
3334 | 3459 | ||
3460 | flush_exit: | ||
3461 | SMB2_flush_free(&rqst); | ||
3335 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); | 3462 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
3336 | return rc; | 3463 | return rc; |
3337 | } | 3464 | } |
@@ -3446,8 +3573,8 @@ smb2_readv_callback(struct mid_q_entry *mid) | |||
3446 | struct smb2_sync_hdr *shdr = | 3573 | struct smb2_sync_hdr *shdr = |
3447 | (struct smb2_sync_hdr *)rdata->iov[0].iov_base; | 3574 | (struct smb2_sync_hdr *)rdata->iov[0].iov_base; |
3448 | struct cifs_credits credits = { .value = 0, .instance = 0 }; | 3575 | struct cifs_credits credits = { .value = 0, .instance = 0 }; |
3449 | struct smb_rqst rqst = { .rq_iov = rdata->iov, | 3576 | struct smb_rqst rqst = { .rq_iov = &rdata->iov[1], |
3450 | .rq_nvec = 2, | 3577 | .rq_nvec = 1, |
3451 | .rq_pages = rdata->pages, | 3578 | .rq_pages = rdata->pages, |
3452 | .rq_offset = rdata->page_offset, | 3579 | .rq_offset = rdata->page_offset, |
3453 | .rq_npages = rdata->nr_pages, | 3580 | .rq_npages = rdata->nr_pages, |
@@ -3468,7 +3595,7 @@ smb2_readv_callback(struct mid_q_entry *mid) | |||
3468 | 3595 | ||
3469 | rc = smb2_verify_signature(&rqst, server); | 3596 | rc = smb2_verify_signature(&rqst, server); |
3470 | if (rc) | 3597 | if (rc) |
3471 | cifs_dbg(VFS, "SMB signature verification returned error = %d\n", | 3598 | cifs_tcon_dbg(VFS, "SMB signature verification returned error = %d\n", |
3472 | rc); | 3599 | rc); |
3473 | } | 3600 | } |
3474 | /* FIXME: should this be counted toward the initiating task? */ | 3601 | /* FIXME: should this be counted toward the initiating task? */ |
@@ -3595,7 +3722,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | |||
3595 | unsigned int *nbytes, char **buf, int *buf_type) | 3722 | unsigned int *nbytes, char **buf, int *buf_type) |
3596 | { | 3723 | { |
3597 | struct smb_rqst rqst; | 3724 | struct smb_rqst rqst; |
3598 | int resp_buftype, rc = -EACCES; | 3725 | int resp_buftype, rc; |
3599 | struct smb2_read_plain_req *req = NULL; | 3726 | struct smb2_read_plain_req *req = NULL; |
3600 | struct smb2_read_rsp *rsp = NULL; | 3727 | struct smb2_read_rsp *rsp = NULL; |
3601 | struct kvec iov[1]; | 3728 | struct kvec iov[1]; |
@@ -4058,7 +4185,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
4058 | info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; | 4185 | info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; |
4059 | break; | 4186 | break; |
4060 | default: | 4187 | default: |
4061 | cifs_dbg(VFS, "info level %u isn't supported\n", | 4188 | cifs_tcon_dbg(VFS, "info level %u isn't supported\n", |
4062 | srch_inf->info_level); | 4189 | srch_inf->info_level); |
4063 | rc = -EINVAL; | 4190 | rc = -EINVAL; |
4064 | goto qdir_exit; | 4191 | goto qdir_exit; |
@@ -4149,7 +4276,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
4149 | else if (resp_buftype == CIFS_SMALL_BUFFER) | 4276 | else if (resp_buftype == CIFS_SMALL_BUFFER) |
4150 | srch_inf->smallBuf = true; | 4277 | srch_inf->smallBuf = true; |
4151 | else | 4278 | else |
4152 | cifs_dbg(VFS, "illegal search buffer type\n"); | 4279 | cifs_tcon_dbg(VFS, "illegal search buffer type\n"); |
4153 | 4280 | ||
4154 | trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid, | 4281 | trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid, |
4155 | tcon->ses->Suid, index, srch_inf->entries_in_buffer); | 4282 | tcon->ses->Suid, index, srch_inf->entries_in_buffer); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 747de9317659..ea735d59c36e 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -143,7 +143,9 @@ struct smb2_transform_hdr { | |||
143 | #define SMB2_FLAGS_ASYNC_COMMAND cpu_to_le32(0x00000002) | 143 | #define SMB2_FLAGS_ASYNC_COMMAND cpu_to_le32(0x00000002) |
144 | #define SMB2_FLAGS_RELATED_OPERATIONS cpu_to_le32(0x00000004) | 144 | #define SMB2_FLAGS_RELATED_OPERATIONS cpu_to_le32(0x00000004) |
145 | #define SMB2_FLAGS_SIGNED cpu_to_le32(0x00000008) | 145 | #define SMB2_FLAGS_SIGNED cpu_to_le32(0x00000008) |
146 | #define SMB2_FLAGS_PRIORITY_MASK cpu_to_le32(0x00000070) /* SMB3.1.1 */ | ||
146 | #define SMB2_FLAGS_DFS_OPERATIONS cpu_to_le32(0x10000000) | 147 | #define SMB2_FLAGS_DFS_OPERATIONS cpu_to_le32(0x10000000) |
148 | #define SMB2_FLAGS_REPLAY_OPERATION cpu_to_le32(0x20000000) /* SMB3 & up */ | ||
147 | 149 | ||
148 | /* | 150 | /* |
149 | * Definitions for SMB2 Protocol Data Units (network frames) | 151 | * Definitions for SMB2 Protocol Data Units (network frames) |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 07ca72486cfa..67a91b11fd59 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -158,6 +158,10 @@ extern int SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, | |||
158 | extern void SMB2_close_free(struct smb_rqst *rqst); | 158 | extern void SMB2_close_free(struct smb_rqst *rqst); |
159 | extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, | 159 | extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, |
160 | u64 persistent_file_id, u64 volatile_file_id); | 160 | u64 persistent_file_id, u64 volatile_file_id); |
161 | extern int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst, | ||
162 | struct cifs_tcon *tcon, | ||
163 | u64 persistent_file_id, u64 volatile_file_id); | ||
164 | extern void SMB2_flush_free(struct smb_rqst *rqst); | ||
161 | extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, | 165 | extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, |
162 | u64 persistent_file_id, u64 volatile_file_id, | 166 | u64 persistent_file_id, u64 volatile_file_id, |
163 | struct smb2_file_all_info *data); | 167 | struct smb2_file_all_info *data); |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 1ccbcf9c2c3b..148d7942c796 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
@@ -176,7 +176,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
176 | 176 | ||
177 | ses = smb2_find_smb_ses(server, shdr->SessionId); | 177 | ses = smb2_find_smb_ses(server, shdr->SessionId); |
178 | if (!ses) { | 178 | if (!ses) { |
179 | cifs_dbg(VFS, "%s: Could not find session\n", __func__); | 179 | cifs_server_dbg(VFS, "%s: Could not find session\n", __func__); |
180 | return 0; | 180 | return 0; |
181 | } | 181 | } |
182 | 182 | ||
@@ -185,21 +185,21 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
185 | 185 | ||
186 | rc = smb2_crypto_shash_allocate(server); | 186 | rc = smb2_crypto_shash_allocate(server); |
187 | if (rc) { | 187 | if (rc) { |
188 | cifs_dbg(VFS, "%s: sha256 alloc failed\n", __func__); | 188 | cifs_server_dbg(VFS, "%s: sha256 alloc failed\n", __func__); |
189 | return rc; | 189 | return rc; |
190 | } | 190 | } |
191 | 191 | ||
192 | rc = crypto_shash_setkey(server->secmech.hmacsha256, | 192 | rc = crypto_shash_setkey(server->secmech.hmacsha256, |
193 | ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); | 193 | ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); |
194 | if (rc) { | 194 | if (rc) { |
195 | cifs_dbg(VFS, "%s: Could not update with response\n", __func__); | 195 | cifs_server_dbg(VFS, "%s: Could not update with response\n", __func__); |
196 | return rc; | 196 | return rc; |
197 | } | 197 | } |
198 | 198 | ||
199 | shash = &server->secmech.sdeschmacsha256->shash; | 199 | shash = &server->secmech.sdeschmacsha256->shash; |
200 | rc = crypto_shash_init(shash); | 200 | rc = crypto_shash_init(shash); |
201 | if (rc) { | 201 | if (rc) { |
202 | cifs_dbg(VFS, "%s: Could not init sha256", __func__); | 202 | cifs_server_dbg(VFS, "%s: Could not init sha256", __func__); |
203 | return rc; | 203 | return rc; |
204 | } | 204 | } |
205 | 205 | ||
@@ -215,7 +215,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
215 | rc = crypto_shash_update(shash, iov[0].iov_base, | 215 | rc = crypto_shash_update(shash, iov[0].iov_base, |
216 | iov[0].iov_len); | 216 | iov[0].iov_len); |
217 | if (rc) { | 217 | if (rc) { |
218 | cifs_dbg(VFS, "%s: Could not update with payload\n", | 218 | cifs_server_dbg(VFS, "%s: Could not update with payload\n", |
219 | __func__); | 219 | __func__); |
220 | return rc; | 220 | return rc; |
221 | } | 221 | } |
@@ -239,68 +239,69 @@ static int generate_key(struct cifs_ses *ses, struct kvec label, | |||
239 | int rc = 0; | 239 | int rc = 0; |
240 | unsigned char prfhash[SMB2_HMACSHA256_SIZE]; | 240 | unsigned char prfhash[SMB2_HMACSHA256_SIZE]; |
241 | unsigned char *hashptr = prfhash; | 241 | unsigned char *hashptr = prfhash; |
242 | struct TCP_Server_Info *server = ses->server; | ||
242 | 243 | ||
243 | memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); | 244 | memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); |
244 | memset(key, 0x0, key_size); | 245 | memset(key, 0x0, key_size); |
245 | 246 | ||
246 | rc = smb3_crypto_shash_allocate(ses->server); | 247 | rc = smb3_crypto_shash_allocate(server); |
247 | if (rc) { | 248 | if (rc) { |
248 | cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); | 249 | cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__); |
249 | goto smb3signkey_ret; | 250 | goto smb3signkey_ret; |
250 | } | 251 | } |
251 | 252 | ||
252 | rc = crypto_shash_setkey(ses->server->secmech.hmacsha256, | 253 | rc = crypto_shash_setkey(server->secmech.hmacsha256, |
253 | ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); | 254 | ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); |
254 | if (rc) { | 255 | if (rc) { |
255 | cifs_dbg(VFS, "%s: Could not set with session key\n", __func__); | 256 | cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__); |
256 | goto smb3signkey_ret; | 257 | goto smb3signkey_ret; |
257 | } | 258 | } |
258 | 259 | ||
259 | rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash); | 260 | rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash); |
260 | if (rc) { | 261 | if (rc) { |
261 | cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__); | 262 | cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__); |
262 | goto smb3signkey_ret; | 263 | goto smb3signkey_ret; |
263 | } | 264 | } |
264 | 265 | ||
265 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, | 266 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, |
266 | i, 4); | 267 | i, 4); |
267 | if (rc) { | 268 | if (rc) { |
268 | cifs_dbg(VFS, "%s: Could not update with n\n", __func__); | 269 | cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__); |
269 | goto smb3signkey_ret; | 270 | goto smb3signkey_ret; |
270 | } | 271 | } |
271 | 272 | ||
272 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, | 273 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, |
273 | label.iov_base, label.iov_len); | 274 | label.iov_base, label.iov_len); |
274 | if (rc) { | 275 | if (rc) { |
275 | cifs_dbg(VFS, "%s: Could not update with label\n", __func__); | 276 | cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__); |
276 | goto smb3signkey_ret; | 277 | goto smb3signkey_ret; |
277 | } | 278 | } |
278 | 279 | ||
279 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, | 280 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, |
280 | &zero, 1); | 281 | &zero, 1); |
281 | if (rc) { | 282 | if (rc) { |
282 | cifs_dbg(VFS, "%s: Could not update with zero\n", __func__); | 283 | cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__); |
283 | goto smb3signkey_ret; | 284 | goto smb3signkey_ret; |
284 | } | 285 | } |
285 | 286 | ||
286 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, | 287 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, |
287 | context.iov_base, context.iov_len); | 288 | context.iov_base, context.iov_len); |
288 | if (rc) { | 289 | if (rc) { |
289 | cifs_dbg(VFS, "%s: Could not update with context\n", __func__); | 290 | cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__); |
290 | goto smb3signkey_ret; | 291 | goto smb3signkey_ret; |
291 | } | 292 | } |
292 | 293 | ||
293 | rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, | 294 | rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, |
294 | L, 4); | 295 | L, 4); |
295 | if (rc) { | 296 | if (rc) { |
296 | cifs_dbg(VFS, "%s: Could not update with L\n", __func__); | 297 | cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__); |
297 | goto smb3signkey_ret; | 298 | goto smb3signkey_ret; |
298 | } | 299 | } |
299 | 300 | ||
300 | rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash, | 301 | rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash, |
301 | hashptr); | 302 | hashptr); |
302 | if (rc) { | 303 | if (rc) { |
303 | cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); | 304 | cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); |
304 | goto smb3signkey_ret; | 305 | goto smb3signkey_ret; |
305 | } | 306 | } |
306 | 307 | ||
@@ -436,7 +437,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
436 | 437 | ||
437 | ses = smb2_find_smb_ses(server, shdr->SessionId); | 438 | ses = smb2_find_smb_ses(server, shdr->SessionId); |
438 | if (!ses) { | 439 | if (!ses) { |
439 | cifs_dbg(VFS, "%s: Could not find session\n", __func__); | 440 | cifs_server_dbg(VFS, "%s: Could not find session\n", __func__); |
440 | return 0; | 441 | return 0; |
441 | } | 442 | } |
442 | 443 | ||
@@ -446,7 +447,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
446 | rc = crypto_shash_setkey(server->secmech.cmacaes, | 447 | rc = crypto_shash_setkey(server->secmech.cmacaes, |
447 | ses->smb3signingkey, SMB2_CMACAES_SIZE); | 448 | ses->smb3signingkey, SMB2_CMACAES_SIZE); |
448 | if (rc) { | 449 | if (rc) { |
449 | cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); | 450 | cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); |
450 | return rc; | 451 | return rc; |
451 | } | 452 | } |
452 | 453 | ||
@@ -457,7 +458,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
457 | */ | 458 | */ |
458 | rc = crypto_shash_init(shash); | 459 | rc = crypto_shash_init(shash); |
459 | if (rc) { | 460 | if (rc) { |
460 | cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__); | 461 | cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__); |
461 | return rc; | 462 | return rc; |
462 | } | 463 | } |
463 | 464 | ||
@@ -473,7 +474,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
473 | rc = crypto_shash_update(shash, iov[0].iov_base, | 474 | rc = crypto_shash_update(shash, iov[0].iov_base, |
474 | iov[0].iov_len); | 475 | iov[0].iov_len); |
475 | if (rc) { | 476 | if (rc) { |
476 | cifs_dbg(VFS, "%s: Could not update with payload\n", | 477 | cifs_server_dbg(VFS, "%s: Could not update with payload\n", |
477 | __func__); | 478 | __func__); |
478 | return rc; | 479 | return rc; |
479 | } | 480 | } |
@@ -521,6 +522,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | |||
521 | if ((shdr->Command == SMB2_NEGOTIATE) || | 522 | if ((shdr->Command == SMB2_NEGOTIATE) || |
522 | (shdr->Command == SMB2_SESSION_SETUP) || | 523 | (shdr->Command == SMB2_SESSION_SETUP) || |
523 | (shdr->Command == SMB2_OPLOCK_BREAK) || | 524 | (shdr->Command == SMB2_OPLOCK_BREAK) || |
525 | server->ignore_signature || | ||
524 | (!server->session_estab)) | 526 | (!server->session_estab)) |
525 | return 0; | 527 | return 0; |
526 | 528 | ||
@@ -665,7 +667,7 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
665 | 667 | ||
666 | rc = smb2_verify_signature(&rqst, server); | 668 | rc = smb2_verify_signature(&rqst, server); |
667 | if (rc) | 669 | if (rc) |
668 | cifs_dbg(VFS, "SMB signature verification returned error = %d\n", | 670 | cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n", |
669 | rc); | 671 | rc); |
670 | } | 672 | } |
671 | 673 | ||
@@ -739,7 +741,7 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server) | |||
739 | else | 741 | else |
740 | tfm = crypto_alloc_aead("ccm(aes)", 0, 0); | 742 | tfm = crypto_alloc_aead("ccm(aes)", 0, 0); |
741 | if (IS_ERR(tfm)) { | 743 | if (IS_ERR(tfm)) { |
742 | cifs_dbg(VFS, "%s: Failed to alloc encrypt aead\n", | 744 | cifs_server_dbg(VFS, "%s: Failed to alloc encrypt aead\n", |
743 | __func__); | 745 | __func__); |
744 | return PTR_ERR(tfm); | 746 | return PTR_ERR(tfm); |
745 | } | 747 | } |
@@ -754,7 +756,7 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server) | |||
754 | if (IS_ERR(tfm)) { | 756 | if (IS_ERR(tfm)) { |
755 | crypto_free_aead(server->secmech.ccmaesencrypt); | 757 | crypto_free_aead(server->secmech.ccmaesencrypt); |
756 | server->secmech.ccmaesencrypt = NULL; | 758 | server->secmech.ccmaesencrypt = NULL; |
757 | cifs_dbg(VFS, "%s: Failed to alloc decrypt aead\n", | 759 | cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n", |
758 | __func__); | 760 | __func__); |
759 | return PTR_ERR(tfm); | 761 | return PTR_ERR(tfm); |
760 | } | 762 | } |
diff --git a/fs/cifs/trace.h b/fs/cifs/trace.h index 99c4d799c24b..e7e350b13d6a 100644 --- a/fs/cifs/trace.h +++ b/fs/cifs/trace.h | |||
@@ -117,6 +117,41 @@ DEFINE_SMB3_RW_DONE_EVENT(falloc_done); | |||
117 | /* | 117 | /* |
118 | * For handle based calls other than read and write, and get/set info | 118 | * For handle based calls other than read and write, and get/set info |
119 | */ | 119 | */ |
120 | DECLARE_EVENT_CLASS(smb3_fd_class, | ||
121 | TP_PROTO(unsigned int xid, | ||
122 | __u64 fid, | ||
123 | __u32 tid, | ||
124 | __u64 sesid), | ||
125 | TP_ARGS(xid, fid, tid, sesid), | ||
126 | TP_STRUCT__entry( | ||
127 | __field(unsigned int, xid) | ||
128 | __field(__u64, fid) | ||
129 | __field(__u32, tid) | ||
130 | __field(__u64, sesid) | ||
131 | ), | ||
132 | TP_fast_assign( | ||
133 | __entry->xid = xid; | ||
134 | __entry->fid = fid; | ||
135 | __entry->tid = tid; | ||
136 | __entry->sesid = sesid; | ||
137 | ), | ||
138 | TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx", | ||
139 | __entry->xid, __entry->sesid, __entry->tid, __entry->fid) | ||
140 | ) | ||
141 | |||
142 | #define DEFINE_SMB3_FD_EVENT(name) \ | ||
143 | DEFINE_EVENT(smb3_fd_class, smb3_##name, \ | ||
144 | TP_PROTO(unsigned int xid, \ | ||
145 | __u64 fid, \ | ||
146 | __u32 tid, \ | ||
147 | __u64 sesid), \ | ||
148 | TP_ARGS(xid, fid, tid, sesid)) | ||
149 | |||
150 | DEFINE_SMB3_FD_EVENT(flush_enter); | ||
151 | DEFINE_SMB3_FD_EVENT(flush_done); | ||
152 | DEFINE_SMB3_FD_EVENT(close_enter); | ||
153 | DEFINE_SMB3_FD_EVENT(close_done); | ||
154 | |||
120 | DECLARE_EVENT_CLASS(smb3_fd_err_class, | 155 | DECLARE_EVENT_CLASS(smb3_fd_err_class, |
121 | TP_PROTO(unsigned int xid, | 156 | TP_PROTO(unsigned int xid, |
122 | __u64 fid, | 157 | __u64 fid, |
@@ -200,6 +235,8 @@ DEFINE_EVENT(smb3_inf_enter_class, smb3_##name, \ | |||
200 | 235 | ||
201 | DEFINE_SMB3_INF_ENTER_EVENT(query_info_enter); | 236 | DEFINE_SMB3_INF_ENTER_EVENT(query_info_enter); |
202 | DEFINE_SMB3_INF_ENTER_EVENT(query_info_done); | 237 | DEFINE_SMB3_INF_ENTER_EVENT(query_info_done); |
238 | DEFINE_SMB3_INF_ENTER_EVENT(notify_enter); | ||
239 | DEFINE_SMB3_INF_ENTER_EVENT(notify_done); | ||
203 | 240 | ||
204 | DECLARE_EVENT_CLASS(smb3_inf_err_class, | 241 | DECLARE_EVENT_CLASS(smb3_inf_err_class, |
205 | TP_PROTO(unsigned int xid, | 242 | TP_PROTO(unsigned int xid, |
@@ -246,6 +283,7 @@ DEFINE_EVENT(smb3_inf_err_class, smb3_##name, \ | |||
246 | 283 | ||
247 | DEFINE_SMB3_INF_ERR_EVENT(query_info_err); | 284 | DEFINE_SMB3_INF_ERR_EVENT(query_info_err); |
248 | DEFINE_SMB3_INF_ERR_EVENT(set_info_err); | 285 | DEFINE_SMB3_INF_ERR_EVENT(set_info_err); |
286 | DEFINE_SMB3_INF_ERR_EVENT(notify_err); | ||
249 | DEFINE_SMB3_INF_ERR_EVENT(fsctl_err); | 287 | DEFINE_SMB3_INF_ERR_EVENT(fsctl_err); |
250 | 288 | ||
251 | DECLARE_EVENT_CLASS(smb3_inf_compound_enter_class, | 289 | DECLARE_EVENT_CLASS(smb3_inf_compound_enter_class, |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 5d6d44bfe10a..308ad0f495e1 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -118,7 +118,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) | |||
118 | #ifdef CONFIG_CIFS_STATS2 | 118 | #ifdef CONFIG_CIFS_STATS2 |
119 | now = jiffies; | 119 | now = jiffies; |
120 | if (now < midEntry->when_alloc) | 120 | if (now < midEntry->when_alloc) |
121 | cifs_dbg(VFS, "invalid mid allocation time\n"); | 121 | cifs_server_dbg(VFS, "invalid mid allocation time\n"); |
122 | roundtrip_time = now - midEntry->when_alloc; | 122 | roundtrip_time = now - midEntry->when_alloc; |
123 | 123 | ||
124 | if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) { | 124 | if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) { |
@@ -232,7 +232,7 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, | |||
232 | retries++; | 232 | retries++; |
233 | if (retries >= 14 || | 233 | if (retries >= 14 || |
234 | (!server->noblocksnd && (retries > 2))) { | 234 | (!server->noblocksnd && (retries > 2))) { |
235 | cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n", | 235 | cifs_server_dbg(VFS, "sends on sock %p stuck for 15 seconds\n", |
236 | ssocket); | 236 | ssocket); |
237 | return -EAGAIN; | 237 | return -EAGAIN; |
238 | } | 238 | } |
@@ -246,7 +246,7 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, | |||
246 | if (rc == 0) { | 246 | if (rc == 0) { |
247 | /* should never happen, letting socket clear before | 247 | /* should never happen, letting socket clear before |
248 | retrying is our only obvious option here */ | 248 | retrying is our only obvious option here */ |
249 | cifs_dbg(VFS, "tcp sent no data\n"); | 249 | cifs_server_dbg(VFS, "tcp sent no data\n"); |
250 | msleep(500); | 250 | msleep(500); |
251 | continue; | 251 | continue; |
252 | } | 252 | } |
@@ -440,7 +440,7 @@ unmask: | |||
440 | } | 440 | } |
441 | smbd_done: | 441 | smbd_done: |
442 | if (rc < 0 && rc != -EINTR) | 442 | if (rc < 0 && rc != -EINTR) |
443 | cifs_dbg(VFS, "Error %d sending data on socket to server\n", | 443 | cifs_server_dbg(VFS, "Error %d sending data on socket to server\n", |
444 | rc); | 444 | rc); |
445 | else if (rc > 0) | 445 | else if (rc > 0) |
446 | rc = 0; | 446 | rc = 0; |
@@ -473,8 +473,8 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, | |||
473 | cur_rqst[0].rq_nvec = 1; | 473 | cur_rqst[0].rq_nvec = 1; |
474 | 474 | ||
475 | if (!server->ops->init_transform_rq) { | 475 | if (!server->ops->init_transform_rq) { |
476 | cifs_dbg(VFS, "Encryption requested but transform callback " | 476 | cifs_server_dbg(VFS, "Encryption requested but transform " |
477 | "is missing\n"); | 477 | "callback is missing\n"); |
478 | return -EIO; | 478 | return -EIO; |
479 | } | 479 | } |
480 | 480 | ||
@@ -532,6 +532,8 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, | |||
532 | if ((flags & CIFS_TIMEOUT_MASK) == CIFS_NON_BLOCKING) { | 532 | if ((flags & CIFS_TIMEOUT_MASK) == CIFS_NON_BLOCKING) { |
533 | /* oplock breaks must not be held up */ | 533 | /* oplock breaks must not be held up */ |
534 | server->in_flight++; | 534 | server->in_flight++; |
535 | if (server->in_flight > server->max_in_flight) | ||
536 | server->max_in_flight = server->in_flight; | ||
535 | *credits -= 1; | 537 | *credits -= 1; |
536 | *instance = server->reconnect_instance; | 538 | *instance = server->reconnect_instance; |
537 | spin_unlock(&server->req_lock); | 539 | spin_unlock(&server->req_lock); |
@@ -548,7 +550,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, | |||
548 | if (!rc) { | 550 | if (!rc) { |
549 | trace_smb3_credit_timeout(server->CurrentMid, | 551 | trace_smb3_credit_timeout(server->CurrentMid, |
550 | server->hostname, num_credits); | 552 | server->hostname, num_credits); |
551 | cifs_dbg(VFS, "wait timed out after %d ms\n", | 553 | cifs_server_dbg(VFS, "wait timed out after %d ms\n", |
552 | timeout); | 554 | timeout); |
553 | return -ENOTSUPP; | 555 | return -ENOTSUPP; |
554 | } | 556 | } |
@@ -589,7 +591,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, | |||
589 | trace_smb3_credit_timeout( | 591 | trace_smb3_credit_timeout( |
590 | server->CurrentMid, | 592 | server->CurrentMid, |
591 | server->hostname, num_credits); | 593 | server->hostname, num_credits); |
592 | cifs_dbg(VFS, "wait timed out after %d ms\n", | 594 | cifs_server_dbg(VFS, "wait timed out after %d ms\n", |
593 | timeout); | 595 | timeout); |
594 | return -ENOTSUPP; | 596 | return -ENOTSUPP; |
595 | } | 597 | } |
@@ -608,6 +610,8 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, | |||
608 | if ((flags & CIFS_TIMEOUT_MASK) != CIFS_BLOCKING_OP) { | 610 | if ((flags & CIFS_TIMEOUT_MASK) != CIFS_BLOCKING_OP) { |
609 | *credits -= num_credits; | 611 | *credits -= num_credits; |
610 | server->in_flight += num_credits; | 612 | server->in_flight += num_credits; |
613 | if (server->in_flight > server->max_in_flight) | ||
614 | server->max_in_flight = server->in_flight; | ||
611 | *instance = server->reconnect_instance; | 615 | *instance = server->reconnect_instance; |
612 | } | 616 | } |
613 | spin_unlock(&server->req_lock); | 617 | spin_unlock(&server->req_lock); |
@@ -869,7 +873,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) | |||
869 | break; | 873 | break; |
870 | default: | 874 | default: |
871 | list_del_init(&mid->qhead); | 875 | list_del_init(&mid->qhead); |
872 | cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n", | 876 | cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n", |
873 | __func__, mid->mid, mid->mid_state); | 877 | __func__, mid->mid, mid->mid_state); |
874 | rc = -EIO; | 878 | rc = -EIO; |
875 | } | 879 | } |
@@ -910,7 +914,7 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
910 | rc = cifs_verify_signature(&rqst, server, | 914 | rc = cifs_verify_signature(&rqst, server, |
911 | mid->sequence_number); | 915 | mid->sequence_number); |
912 | if (rc) | 916 | if (rc) |
913 | cifs_dbg(VFS, "SMB signature verification returned error = %d\n", | 917 | cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n", |
914 | rc); | 918 | rc); |
915 | } | 919 | } |
916 | 920 | ||
@@ -1107,7 +1111,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, | |||
1107 | } | 1111 | } |
1108 | if (rc != 0) { | 1112 | if (rc != 0) { |
1109 | for (; i < num_rqst; i++) { | 1113 | for (; i < num_rqst; i++) { |
1110 | cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n", | 1114 | cifs_server_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n", |
1111 | midQ[i]->mid, le16_to_cpu(midQ[i]->command)); | 1115 | midQ[i]->mid, le16_to_cpu(midQ[i]->command)); |
1112 | send_cancel(server, &rqst[i], midQ[i]); | 1116 | send_cancel(server, &rqst[i], midQ[i]); |
1113 | spin_lock(&GlobalMid_Lock); | 1117 | spin_lock(&GlobalMid_Lock); |
@@ -1242,17 +1246,19 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, | |||
1242 | struct kvec iov = { .iov_base = in_buf, .iov_len = len }; | 1246 | struct kvec iov = { .iov_base = in_buf, .iov_len = len }; |
1243 | struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; | 1247 | struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; |
1244 | struct cifs_credits credits = { .value = 1, .instance = 0 }; | 1248 | struct cifs_credits credits = { .value = 1, .instance = 0 }; |
1249 | struct TCP_Server_Info *server; | ||
1245 | 1250 | ||
1246 | if (ses == NULL) { | 1251 | if (ses == NULL) { |
1247 | cifs_dbg(VFS, "Null smb session\n"); | 1252 | cifs_dbg(VFS, "Null smb session\n"); |
1248 | return -EIO; | 1253 | return -EIO; |
1249 | } | 1254 | } |
1250 | if (ses->server == NULL) { | 1255 | server = ses->server; |
1256 | if (server == NULL) { | ||
1251 | cifs_dbg(VFS, "Null tcp session\n"); | 1257 | cifs_dbg(VFS, "Null tcp session\n"); |
1252 | return -EIO; | 1258 | return -EIO; |
1253 | } | 1259 | } |
1254 | 1260 | ||
1255 | if (ses->server->tcpStatus == CifsExiting) | 1261 | if (server->tcpStatus == CifsExiting) |
1256 | return -ENOENT; | 1262 | return -ENOENT; |
1257 | 1263 | ||
1258 | /* Ensure that we do not send more than 50 overlapping requests | 1264 | /* Ensure that we do not send more than 50 overlapping requests |
@@ -1260,12 +1266,12 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, | |||
1260 | use ses->maxReq */ | 1266 | use ses->maxReq */ |
1261 | 1267 | ||
1262 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | 1268 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { |
1263 | cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", | 1269 | cifs_server_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", |
1264 | len); | 1270 | len); |
1265 | return -EIO; | 1271 | return -EIO; |
1266 | } | 1272 | } |
1267 | 1273 | ||
1268 | rc = wait_for_free_request(ses->server, flags, &credits.instance); | 1274 | rc = wait_for_free_request(server, flags, &credits.instance); |
1269 | if (rc) | 1275 | if (rc) |
1270 | return rc; | 1276 | return rc; |
1271 | 1277 | ||
@@ -1273,70 +1279,70 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, | |||
1273 | and avoid races inside tcp sendmsg code that could cause corruption | 1279 | and avoid races inside tcp sendmsg code that could cause corruption |
1274 | of smb data */ | 1280 | of smb data */ |
1275 | 1281 | ||
1276 | mutex_lock(&ses->server->srv_mutex); | 1282 | mutex_lock(&server->srv_mutex); |
1277 | 1283 | ||
1278 | rc = allocate_mid(ses, in_buf, &midQ); | 1284 | rc = allocate_mid(ses, in_buf, &midQ); |
1279 | if (rc) { | 1285 | if (rc) { |
1280 | mutex_unlock(&ses->server->srv_mutex); | 1286 | mutex_unlock(&ses->server->srv_mutex); |
1281 | /* Update # of requests on wire to server */ | 1287 | /* Update # of requests on wire to server */ |
1282 | add_credits(ses->server, &credits, 0); | 1288 | add_credits(server, &credits, 0); |
1283 | return rc; | 1289 | return rc; |
1284 | } | 1290 | } |
1285 | 1291 | ||
1286 | rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); | 1292 | rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number); |
1287 | if (rc) { | 1293 | if (rc) { |
1288 | mutex_unlock(&ses->server->srv_mutex); | 1294 | mutex_unlock(&server->srv_mutex); |
1289 | goto out; | 1295 | goto out; |
1290 | } | 1296 | } |
1291 | 1297 | ||
1292 | midQ->mid_state = MID_REQUEST_SUBMITTED; | 1298 | midQ->mid_state = MID_REQUEST_SUBMITTED; |
1293 | 1299 | ||
1294 | cifs_in_send_inc(ses->server); | 1300 | cifs_in_send_inc(server); |
1295 | rc = smb_send(ses->server, in_buf, len); | 1301 | rc = smb_send(server, in_buf, len); |
1296 | cifs_in_send_dec(ses->server); | 1302 | cifs_in_send_dec(server); |
1297 | cifs_save_when_sent(midQ); | 1303 | cifs_save_when_sent(midQ); |
1298 | 1304 | ||
1299 | if (rc < 0) | 1305 | if (rc < 0) |
1300 | ses->server->sequence_number -= 2; | 1306 | server->sequence_number -= 2; |
1301 | 1307 | ||
1302 | mutex_unlock(&ses->server->srv_mutex); | 1308 | mutex_unlock(&server->srv_mutex); |
1303 | 1309 | ||
1304 | if (rc < 0) | 1310 | if (rc < 0) |
1305 | goto out; | 1311 | goto out; |
1306 | 1312 | ||
1307 | rc = wait_for_response(ses->server, midQ); | 1313 | rc = wait_for_response(server, midQ); |
1308 | if (rc != 0) { | 1314 | if (rc != 0) { |
1309 | send_cancel(ses->server, &rqst, midQ); | 1315 | send_cancel(server, &rqst, midQ); |
1310 | spin_lock(&GlobalMid_Lock); | 1316 | spin_lock(&GlobalMid_Lock); |
1311 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { | 1317 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
1312 | /* no longer considered to be "in-flight" */ | 1318 | /* no longer considered to be "in-flight" */ |
1313 | midQ->callback = DeleteMidQEntry; | 1319 | midQ->callback = DeleteMidQEntry; |
1314 | spin_unlock(&GlobalMid_Lock); | 1320 | spin_unlock(&GlobalMid_Lock); |
1315 | add_credits(ses->server, &credits, 0); | 1321 | add_credits(server, &credits, 0); |
1316 | return rc; | 1322 | return rc; |
1317 | } | 1323 | } |
1318 | spin_unlock(&GlobalMid_Lock); | 1324 | spin_unlock(&GlobalMid_Lock); |
1319 | } | 1325 | } |
1320 | 1326 | ||
1321 | rc = cifs_sync_mid_result(midQ, ses->server); | 1327 | rc = cifs_sync_mid_result(midQ, server); |
1322 | if (rc != 0) { | 1328 | if (rc != 0) { |
1323 | add_credits(ses->server, &credits, 0); | 1329 | add_credits(server, &credits, 0); |
1324 | return rc; | 1330 | return rc; |
1325 | } | 1331 | } |
1326 | 1332 | ||
1327 | if (!midQ->resp_buf || !out_buf || | 1333 | if (!midQ->resp_buf || !out_buf || |
1328 | midQ->mid_state != MID_RESPONSE_RECEIVED) { | 1334 | midQ->mid_state != MID_RESPONSE_RECEIVED) { |
1329 | rc = -EIO; | 1335 | rc = -EIO; |
1330 | cifs_dbg(VFS, "Bad MID state?\n"); | 1336 | cifs_server_dbg(VFS, "Bad MID state?\n"); |
1331 | goto out; | 1337 | goto out; |
1332 | } | 1338 | } |
1333 | 1339 | ||
1334 | *pbytes_returned = get_rfc1002_length(midQ->resp_buf); | 1340 | *pbytes_returned = get_rfc1002_length(midQ->resp_buf); |
1335 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); | 1341 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); |
1336 | rc = cifs_check_receive(midQ, ses->server, 0); | 1342 | rc = cifs_check_receive(midQ, server, 0); |
1337 | out: | 1343 | out: |
1338 | cifs_delete_mid(midQ); | 1344 | cifs_delete_mid(midQ); |
1339 | add_credits(ses->server, &credits, 0); | 1345 | add_credits(server, &credits, 0); |
1340 | 1346 | ||
1341 | return rc; | 1347 | return rc; |
1342 | } | 1348 | } |
@@ -1379,19 +1385,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
1379 | struct kvec iov = { .iov_base = in_buf, .iov_len = len }; | 1385 | struct kvec iov = { .iov_base = in_buf, .iov_len = len }; |
1380 | struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; | 1386 | struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; |
1381 | unsigned int instance; | 1387 | unsigned int instance; |
1388 | struct TCP_Server_Info *server; | ||
1382 | 1389 | ||
1383 | if (tcon == NULL || tcon->ses == NULL) { | 1390 | if (tcon == NULL || tcon->ses == NULL) { |
1384 | cifs_dbg(VFS, "Null smb session\n"); | 1391 | cifs_dbg(VFS, "Null smb session\n"); |
1385 | return -EIO; | 1392 | return -EIO; |
1386 | } | 1393 | } |
1387 | ses = tcon->ses; | 1394 | ses = tcon->ses; |
1395 | server = ses->server; | ||
1388 | 1396 | ||
1389 | if (ses->server == NULL) { | 1397 | if (server == NULL) { |
1390 | cifs_dbg(VFS, "Null tcp session\n"); | 1398 | cifs_dbg(VFS, "Null tcp session\n"); |
1391 | return -EIO; | 1399 | return -EIO; |
1392 | } | 1400 | } |
1393 | 1401 | ||
1394 | if (ses->server->tcpStatus == CifsExiting) | 1402 | if (server->tcpStatus == CifsExiting) |
1395 | return -ENOENT; | 1403 | return -ENOENT; |
1396 | 1404 | ||
1397 | /* Ensure that we do not send more than 50 overlapping requests | 1405 | /* Ensure that we do not send more than 50 overlapping requests |
@@ -1399,12 +1407,12 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
1399 | use ses->maxReq */ | 1407 | use ses->maxReq */ |
1400 | 1408 | ||
1401 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | 1409 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { |
1402 | cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", | 1410 | cifs_tcon_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", |
1403 | len); | 1411 | len); |
1404 | return -EIO; | 1412 | return -EIO; |
1405 | } | 1413 | } |
1406 | 1414 | ||
1407 | rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, &instance); | 1415 | rc = wait_for_free_request(server, CIFS_BLOCKING_OP, &instance); |
1408 | if (rc) | 1416 | if (rc) |
1409 | return rc; | 1417 | return rc; |
1410 | 1418 | ||
@@ -1412,31 +1420,31 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
1412 | and avoid races inside tcp sendmsg code that could cause corruption | 1420 | and avoid races inside tcp sendmsg code that could cause corruption |
1413 | of smb data */ | 1421 | of smb data */ |
1414 | 1422 | ||
1415 | mutex_lock(&ses->server->srv_mutex); | 1423 | mutex_lock(&server->srv_mutex); |
1416 | 1424 | ||
1417 | rc = allocate_mid(ses, in_buf, &midQ); | 1425 | rc = allocate_mid(ses, in_buf, &midQ); |
1418 | if (rc) { | 1426 | if (rc) { |
1419 | mutex_unlock(&ses->server->srv_mutex); | 1427 | mutex_unlock(&server->srv_mutex); |
1420 | return rc; | 1428 | return rc; |
1421 | } | 1429 | } |
1422 | 1430 | ||
1423 | rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); | 1431 | rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number); |
1424 | if (rc) { | 1432 | if (rc) { |
1425 | cifs_delete_mid(midQ); | 1433 | cifs_delete_mid(midQ); |
1426 | mutex_unlock(&ses->server->srv_mutex); | 1434 | mutex_unlock(&server->srv_mutex); |
1427 | return rc; | 1435 | return rc; |
1428 | } | 1436 | } |
1429 | 1437 | ||
1430 | midQ->mid_state = MID_REQUEST_SUBMITTED; | 1438 | midQ->mid_state = MID_REQUEST_SUBMITTED; |
1431 | cifs_in_send_inc(ses->server); | 1439 | cifs_in_send_inc(server); |
1432 | rc = smb_send(ses->server, in_buf, len); | 1440 | rc = smb_send(server, in_buf, len); |
1433 | cifs_in_send_dec(ses->server); | 1441 | cifs_in_send_dec(server); |
1434 | cifs_save_when_sent(midQ); | 1442 | cifs_save_when_sent(midQ); |
1435 | 1443 | ||
1436 | if (rc < 0) | 1444 | if (rc < 0) |
1437 | ses->server->sequence_number -= 2; | 1445 | server->sequence_number -= 2; |
1438 | 1446 | ||
1439 | mutex_unlock(&ses->server->srv_mutex); | 1447 | mutex_unlock(&server->srv_mutex); |
1440 | 1448 | ||
1441 | if (rc < 0) { | 1449 | if (rc < 0) { |
1442 | cifs_delete_mid(midQ); | 1450 | cifs_delete_mid(midQ); |
@@ -1444,21 +1452,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
1444 | } | 1452 | } |
1445 | 1453 | ||
1446 | /* Wait for a reply - allow signals to interrupt. */ | 1454 | /* Wait for a reply - allow signals to interrupt. */ |
1447 | rc = wait_event_interruptible(ses->server->response_q, | 1455 | rc = wait_event_interruptible(server->response_q, |
1448 | (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || | 1456 | (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || |
1449 | ((ses->server->tcpStatus != CifsGood) && | 1457 | ((server->tcpStatus != CifsGood) && |
1450 | (ses->server->tcpStatus != CifsNew))); | 1458 | (server->tcpStatus != CifsNew))); |
1451 | 1459 | ||
1452 | /* Were we interrupted by a signal ? */ | 1460 | /* Were we interrupted by a signal ? */ |
1453 | if ((rc == -ERESTARTSYS) && | 1461 | if ((rc == -ERESTARTSYS) && |
1454 | (midQ->mid_state == MID_REQUEST_SUBMITTED) && | 1462 | (midQ->mid_state == MID_REQUEST_SUBMITTED) && |
1455 | ((ses->server->tcpStatus == CifsGood) || | 1463 | ((server->tcpStatus == CifsGood) || |
1456 | (ses->server->tcpStatus == CifsNew))) { | 1464 | (server->tcpStatus == CifsNew))) { |
1457 | 1465 | ||
1458 | if (in_buf->Command == SMB_COM_TRANSACTION2) { | 1466 | if (in_buf->Command == SMB_COM_TRANSACTION2) { |
1459 | /* POSIX lock. We send a NT_CANCEL SMB to cause the | 1467 | /* POSIX lock. We send a NT_CANCEL SMB to cause the |
1460 | blocking lock to return. */ | 1468 | blocking lock to return. */ |
1461 | rc = send_cancel(ses->server, &rqst, midQ); | 1469 | rc = send_cancel(server, &rqst, midQ); |
1462 | if (rc) { | 1470 | if (rc) { |
1463 | cifs_delete_mid(midQ); | 1471 | cifs_delete_mid(midQ); |
1464 | return rc; | 1472 | return rc; |
@@ -1477,9 +1485,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
1477 | } | 1485 | } |
1478 | } | 1486 | } |
1479 | 1487 | ||
1480 | rc = wait_for_response(ses->server, midQ); | 1488 | rc = wait_for_response(server, midQ); |
1481 | if (rc) { | 1489 | if (rc) { |
1482 | send_cancel(ses->server, &rqst, midQ); | 1490 | send_cancel(server, &rqst, midQ); |
1483 | spin_lock(&GlobalMid_Lock); | 1491 | spin_lock(&GlobalMid_Lock); |
1484 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { | 1492 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
1485 | /* no longer considered to be "in-flight" */ | 1493 | /* no longer considered to be "in-flight" */ |
@@ -1494,20 +1502,20 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
1494 | rstart = 1; | 1502 | rstart = 1; |
1495 | } | 1503 | } |
1496 | 1504 | ||
1497 | rc = cifs_sync_mid_result(midQ, ses->server); | 1505 | rc = cifs_sync_mid_result(midQ, server); |
1498 | if (rc != 0) | 1506 | if (rc != 0) |
1499 | return rc; | 1507 | return rc; |
1500 | 1508 | ||
1501 | /* rcvd frame is ok */ | 1509 | /* rcvd frame is ok */ |
1502 | if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { | 1510 | if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { |
1503 | rc = -EIO; | 1511 | rc = -EIO; |
1504 | cifs_dbg(VFS, "Bad MID state?\n"); | 1512 | cifs_tcon_dbg(VFS, "Bad MID state?\n"); |
1505 | goto out; | 1513 | goto out; |
1506 | } | 1514 | } |
1507 | 1515 | ||
1508 | *pbytes_returned = get_rfc1002_length(midQ->resp_buf); | 1516 | *pbytes_returned = get_rfc1002_length(midQ->resp_buf); |
1509 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); | 1517 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); |
1510 | rc = cifs_check_receive(midQ, ses->server, 0); | 1518 | rc = cifs_check_receive(midQ, server, 0); |
1511 | out: | 1519 | out: |
1512 | cifs_delete_mid(midQ); | 1520 | cifs_delete_mid(midQ); |
1513 | if (rstart && rc == -EACCES) | 1521 | if (rstart && rc == -EACCES) |
diff --git a/include/linux/root_dev.h b/include/linux/root_dev.h index bab671b0782f..4e78651371ba 100644 --- a/include/linux/root_dev.h +++ b/include/linux/root_dev.h | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | enum { | 9 | enum { |
10 | Root_NFS = MKDEV(UNNAMED_MAJOR, 255), | 10 | Root_NFS = MKDEV(UNNAMED_MAJOR, 255), |
11 | Root_CIFS = MKDEV(UNNAMED_MAJOR, 254), | ||
11 | Root_RAM0 = MKDEV(RAMDISK_MAJOR, 0), | 12 | Root_RAM0 = MKDEV(RAMDISK_MAJOR, 0), |
12 | Root_RAM1 = MKDEV(RAMDISK_MAJOR, 1), | 13 | Root_RAM1 = MKDEV(RAMDISK_MAJOR, 1), |
13 | Root_FD0 = MKDEV(FLOPPY_MAJOR, 0), | 14 | Root_FD0 = MKDEV(FLOPPY_MAJOR, 0), |