aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2013-10-09 03:07:00 -0400
committerSteve French <smfrench@gmail.com>2013-10-28 10:22:55 -0400
commit34f626406c09dd45878ce75170abab342985ec24 (patch)
tree6904e8c808392920874febebf28129e6d1a1b974 /fs
parent64a5cfa6db94c5abba2cafe77aca077dd1e3283b (diff)
Query file system attributes from server on SMB2, not just cifs, mounts
Currently SMB2 and SMB3 mounts do not query the file system attributes from the server at mount time as is done for cifs. These can be useful for debugging. Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs')
-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,