diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifspdu.h | 3 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 28 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 42 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 2 |
4 files changed, 73 insertions, 2 deletions
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 08f9dfb1a894..d40bd77a2392 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -2215,6 +2215,9 @@ typedef struct { | |||
2215 | __le32 DeviceCharacteristics; | 2215 | __le32 DeviceCharacteristics; |
2216 | } __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */ | 2216 | } __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */ |
2217 | 2217 | ||
2218 | /* minimum includes first three fields, and empty FS Name */ | ||
2219 | #define MIN_FS_ATTR_INFO_SIZE 12 | ||
2220 | |||
2218 | typedef struct { | 2221 | typedef struct { |
2219 | __le32 Attributes; | 2222 | __le32 Attributes; |
2220 | __le32 MaxPathNameComponentLength; | 2223 | __le32 MaxPathNameComponentLength; |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index b96bacce955a..a53e2053ae9d 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -209,6 +209,31 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) | |||
209 | return rsize; | 209 | return rsize; |
210 | } | 210 | } |
211 | 211 | ||
212 | static void | ||
213 | smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) | ||
214 | { | ||
215 | int rc; | ||
216 | __le16 srch_path = 0; /* Null - open root of share */ | ||
217 | u8 oplock = SMB2_OPLOCK_LEVEL_NONE; | ||
218 | struct cifs_open_parms oparms; | ||
219 | struct cifs_fid fid; | ||
220 | |||
221 | oparms.tcon = tcon; | ||
222 | oparms.desired_access = FILE_READ_ATTRIBUTES; | ||
223 | oparms.disposition = FILE_OPEN; | ||
224 | oparms.create_options = 0; | ||
225 | oparms.fid = &fid; | ||
226 | oparms.reconnect = false; | ||
227 | |||
228 | rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL); | ||
229 | if (rc) | ||
230 | return; | ||
231 | |||
232 | SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid); | ||
233 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | ||
234 | return; | ||
235 | } | ||
236 | |||
212 | static int | 237 | static int |
213 | smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, | 238 | smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, |
214 | struct cifs_sb_info *cifs_sb, const char *full_path) | 239 | struct cifs_sb_info *cifs_sb, const char *full_path) |
@@ -873,6 +898,7 @@ struct smb_version_operations smb20_operations = { | |||
873 | .logoff = SMB2_logoff, | 898 | .logoff = SMB2_logoff, |
874 | .tree_connect = SMB2_tcon, | 899 | .tree_connect = SMB2_tcon, |
875 | .tree_disconnect = SMB2_tdis, | 900 | .tree_disconnect = SMB2_tdis, |
901 | .qfs_tcon = smb2_qfs_tcon, | ||
876 | .is_path_accessible = smb2_is_path_accessible, | 902 | .is_path_accessible = smb2_is_path_accessible, |
877 | .can_echo = smb2_can_echo, | 903 | .can_echo = smb2_can_echo, |
878 | .echo = SMB2_echo, | 904 | .echo = SMB2_echo, |
@@ -945,6 +971,7 @@ struct smb_version_operations smb21_operations = { | |||
945 | .logoff = SMB2_logoff, | 971 | .logoff = SMB2_logoff, |
946 | .tree_connect = SMB2_tcon, | 972 | .tree_connect = SMB2_tcon, |
947 | .tree_disconnect = SMB2_tdis, | 973 | .tree_disconnect = SMB2_tdis, |
974 | .qfs_tcon = smb2_qfs_tcon, | ||
948 | .is_path_accessible = smb2_is_path_accessible, | 975 | .is_path_accessible = smb2_is_path_accessible, |
949 | .can_echo = smb2_can_echo, | 976 | .can_echo = smb2_can_echo, |
950 | .echo = SMB2_echo, | 977 | .echo = SMB2_echo, |
@@ -1018,6 +1045,7 @@ struct smb_version_operations smb30_operations = { | |||
1018 | .logoff = SMB2_logoff, | 1045 | .logoff = SMB2_logoff, |
1019 | .tree_connect = SMB2_tcon, | 1046 | .tree_connect = SMB2_tcon, |
1020 | .tree_disconnect = SMB2_tdis, | 1047 | .tree_disconnect = SMB2_tdis, |
1048 | .qfs_tcon = smb2_qfs_tcon, | ||
1021 | .is_path_accessible = smb2_is_path_accessible, | 1049 | .is_path_accessible = smb2_is_path_accessible, |
1022 | .can_echo = smb2_can_echo, | 1050 | .can_echo = smb2_can_echo, |
1023 | .echo = SMB2_echo, | 1051 | .echo = SMB2_echo, |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index bbafa12e83b2..df12cf8bd979 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -2339,7 +2339,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
2339 | rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0); | 2339 | rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0); |
2340 | if (rc) { | 2340 | if (rc) { |
2341 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); | 2341 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
2342 | goto qinf_exit; | 2342 | goto qfsinf_exit; |
2343 | } | 2343 | } |
2344 | rsp = (struct smb2_query_info_rsp *)iov.iov_base; | 2344 | rsp = (struct smb2_query_info_rsp *)iov.iov_base; |
2345 | 2345 | ||
@@ -2351,7 +2351,45 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
2351 | if (!rc) | 2351 | if (!rc) |
2352 | copy_fs_info_to_kstatfs(info, fsdata); | 2352 | copy_fs_info_to_kstatfs(info, fsdata); |
2353 | 2353 | ||
2354 | qinf_exit: | 2354 | qfsinf_exit: |
2355 | free_rsp_buf(resp_buftype, iov.iov_base); | ||
2356 | return rc; | ||
2357 | } | ||
2358 | |||
2359 | int | ||
2360 | SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, | ||
2361 | u64 persistent_fid, u64 volatile_fid) | ||
2362 | { | ||
2363 | struct smb2_query_info_rsp *rsp = NULL; | ||
2364 | struct kvec iov; | ||
2365 | int rc = 0; | ||
2366 | int resp_buftype; | ||
2367 | struct cifs_ses *ses = tcon->ses; | ||
2368 | unsigned int rsp_len, offset; | ||
2369 | |||
2370 | rc = build_qfs_info_req(&iov, tcon, SMB_QUERY_FS_ATTRIBUTE_INFO, | ||
2371 | sizeof(FILE_SYSTEM_ATTRIBUTE_INFO), | ||
2372 | persistent_fid, volatile_fid); | ||
2373 | if (rc) | ||
2374 | return rc; | ||
2375 | |||
2376 | rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0); | ||
2377 | if (rc) { | ||
2378 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); | ||
2379 | goto qfsattr_exit; | ||
2380 | } | ||
2381 | rsp = (struct smb2_query_info_rsp *)iov.iov_base; | ||
2382 | |||
2383 | rsp_len = le32_to_cpu(rsp->OutputBufferLength); | ||
2384 | offset = le16_to_cpu(rsp->OutputBufferOffset); | ||
2385 | rc = validate_buf(offset, rsp_len, &rsp->hdr, MIN_FS_ATTR_INFO_SIZE); | ||
2386 | if (!rc) { | ||
2387 | memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset | ||
2388 | + (char *)&rsp->hdr, min_t(unsigned int, | ||
2389 | rsp_len, sizeof(FILE_SYSTEM_ATTRIBUTE_INFO))); | ||
2390 | } | ||
2391 | |||
2392 | qfsattr_exit: | ||
2355 | free_rsp_buf(resp_buftype, iov.iov_base); | 2393 | free_rsp_buf(resp_buftype, iov.iov_base); |
2356 | return rc; | 2394 | return rc; |
2357 | } | 2395 | } |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 3cf22e39420d..68dc00d5fb12 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -150,6 +150,8 @@ extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, | |||
150 | extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, | 150 | extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, |
151 | u64 persistent_file_id, u64 volatile_file_id, | 151 | u64 persistent_file_id, u64 volatile_file_id, |
152 | struct kstatfs *FSData); | 152 | struct kstatfs *FSData); |
153 | extern int SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, | ||
154 | u64 persistent_file_id, u64 volatile_file_id); | ||
153 | extern int SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon, | 155 | extern int SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon, |
154 | const __u64 persist_fid, const __u64 volatile_fid, | 156 | const __u64 persist_fid, const __u64 volatile_fid, |
155 | const __u32 pid, const __u64 length, const __u64 offset, | 157 | const __u32 pid, const __u64 length, const __u64 offset, |