aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifspdu.h3
-rw-r--r--fs/cifs/smb2ops.c28
-rw-r--r--fs/cifs/smb2pdu.c42
-rw-r--r--fs/cifs/smb2proto.h2
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
2218typedef struct { 2221typedef 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
212static void
213smb2_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
212static int 237static int
213smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, 238smb2_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
2354qinf_exit: 2354qfsinf_exit:
2355 free_rsp_buf(resp_buftype, iov.iov_base);
2356 return rc;
2357}
2358
2359int
2360SMB2_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
2392qfsattr_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,
150extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, 150extern 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);
153extern int SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
154 u64 persistent_file_id, u64 volatile_file_id);
153extern int SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon, 155extern 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,