Skip to content

Commit

Permalink
Query file system attributes from server on SMB2, not just cifs, mounts
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steve French committed Oct 28, 2013
1 parent 64a5cfa commit 34f6264
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 2 deletions.
3 changes: 3 additions & 0 deletions fs/cifs/cifspdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -2215,6 +2215,9 @@ typedef struct {
__le32 DeviceCharacteristics;
} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */

/* minimum includes first three fields, and empty FS Name */
#define MIN_FS_ATTR_INFO_SIZE 12

typedef struct {
__le32 Attributes;
__le32 MaxPathNameComponentLength;
Expand Down
28 changes: 28 additions & 0 deletions fs/cifs/smb2ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,31 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
return rsize;
}

static void
smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
{
int rc;
__le16 srch_path = 0; /* Null - open root of share */
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
struct cifs_open_parms oparms;
struct cifs_fid fid;

oparms.tcon = tcon;
oparms.desired_access = FILE_READ_ATTRIBUTES;
oparms.disposition = FILE_OPEN;
oparms.create_options = 0;
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
if (rc)
return;

SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid);
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
return;
}

static int
smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, const char *full_path)
Expand Down Expand Up @@ -873,6 +898,7 @@ struct smb_version_operations smb20_operations = {
.logoff = SMB2_logoff,
.tree_connect = SMB2_tcon,
.tree_disconnect = SMB2_tdis,
.qfs_tcon = smb2_qfs_tcon,
.is_path_accessible = smb2_is_path_accessible,
.can_echo = smb2_can_echo,
.echo = SMB2_echo,
Expand Down Expand Up @@ -945,6 +971,7 @@ struct smb_version_operations smb21_operations = {
.logoff = SMB2_logoff,
.tree_connect = SMB2_tcon,
.tree_disconnect = SMB2_tdis,
.qfs_tcon = smb2_qfs_tcon,
.is_path_accessible = smb2_is_path_accessible,
.can_echo = smb2_can_echo,
.echo = SMB2_echo,
Expand Down Expand Up @@ -1018,6 +1045,7 @@ struct smb_version_operations smb30_operations = {
.logoff = SMB2_logoff,
.tree_connect = SMB2_tcon,
.tree_disconnect = SMB2_tdis,
.qfs_tcon = smb2_qfs_tcon,
.is_path_accessible = smb2_is_path_accessible,
.can_echo = smb2_can_echo,
.echo = SMB2_echo,
Expand Down
42 changes: 40 additions & 2 deletions fs/cifs/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2339,7 +2339,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0);
if (rc) {
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
goto qinf_exit;
goto qfsinf_exit;
}
rsp = (struct smb2_query_info_rsp *)iov.iov_base;

Expand All @@ -2351,7 +2351,45 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
if (!rc)
copy_fs_info_to_kstatfs(info, fsdata);

qinf_exit:
qfsinf_exit:
free_rsp_buf(resp_buftype, iov.iov_base);
return rc;
}

int
SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid)
{
struct smb2_query_info_rsp *rsp = NULL;
struct kvec iov;
int rc = 0;
int resp_buftype;
struct cifs_ses *ses = tcon->ses;
unsigned int rsp_len, offset;

rc = build_qfs_info_req(&iov, tcon, SMB_QUERY_FS_ATTRIBUTE_INFO,
sizeof(FILE_SYSTEM_ATTRIBUTE_INFO),
persistent_fid, volatile_fid);
if (rc)
return rc;

rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0);
if (rc) {
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
goto qfsattr_exit;
}
rsp = (struct smb2_query_info_rsp *)iov.iov_base;

rsp_len = le32_to_cpu(rsp->OutputBufferLength);
offset = le16_to_cpu(rsp->OutputBufferOffset);
rc = validate_buf(offset, rsp_len, &rsp->hdr, MIN_FS_ATTR_INFO_SIZE);
if (!rc) {
memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset
+ (char *)&rsp->hdr, min_t(unsigned int,
rsp_len, sizeof(FILE_SYSTEM_ATTRIBUTE_INFO)));
}

qfsattr_exit:
free_rsp_buf(resp_buftype, iov.iov_base);
return rc;
}
Expand Down
2 changes: 2 additions & 0 deletions fs/cifs/smb2proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id,
struct kstatfs *FSData);
extern int SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id);
extern int SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon,
const __u64 persist_fid, const __u64 volatile_fid,
const __u32 pid, const __u64 length, const __u64 offset,
Expand Down

0 comments on commit 34f6264

Please sign in to comment.