Commit af6a12ea authored by Steven French's avatar Steven French Committed by Steve French

Query File System Alignment

In SMB3 it is now possible to query the file system
alignment info, and the preferred (for performance)
sector size and whether the underlying disk
has no seek penalty (like SSD).

Query this information at mount time for SMB3,
and make it visible in /proc/fs/cifs/DebugData
for debugging purposes.

This alignment information and preferred sector
size info will be helpful for the copy offload
patches to setup the right chunks in the CopyChunk
requests.   Presumably the knowledge that the
underlying disk is SSD could also help us
make better readahead and writebehind
decisions (something to look at in the future).
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 2167114c
...@@ -853,6 +853,8 @@ struct cifs_tcon { ...@@ -853,6 +853,8 @@ struct cifs_tcon {
__u32 maximal_access; __u32 maximal_access;
__u32 vol_serial_number; __u32 vol_serial_number;
__le64 vol_create_time; __le64 vol_create_time;
__u32 ss_flags; /* sector size flags */
__u32 perf_sector_size; /* best sector size for perf */
#endif /* CONFIG_CIFS_SMB2 */ #endif /* CONFIG_CIFS_SMB2 */
#ifdef CONFIG_CIFS_FSCACHE #ifdef CONFIG_CIFS_FSCACHE
u64 resource_id; /* server resource id */ u64 resource_id; /* server resource id */
......
...@@ -209,6 +209,36 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) ...@@ -209,6 +209,36 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
return rsize; return rsize;
} }
static void
smb3_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,
FS_ATTRIBUTE_INFORMATION);
SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
FS_DEVICE_INFORMATION);
SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
return;
}
static void static void
smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
{ {
...@@ -332,7 +362,19 @@ smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon) ...@@ -332,7 +362,19 @@ smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon)
seq_puts(m, " ASYMMETRIC,"); seq_puts(m, " ASYMMETRIC,");
if (tcon->capabilities == 0) if (tcon->capabilities == 0)
seq_puts(m, " None"); seq_puts(m, " None");
if (tcon->ss_flags & SSINFO_FLAGS_ALIGNED_DEVICE)
seq_puts(m, " Aligned,");
if (tcon->ss_flags & SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE)
seq_puts(m, " Partition Aligned,");
if (tcon->ss_flags & SSINFO_FLAGS_NO_SEEK_PENALTY)
seq_puts(m, " SSD,");
if (tcon->ss_flags & SSINFO_FLAGS_TRIM_ENABLED)
seq_puts(m, " TRIM-support,");
seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags); seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags);
if (tcon->perf_sector_size)
seq_printf(m, "\tOptimal sector size: 0x%x",
tcon->perf_sector_size);
} }
static void static void
...@@ -1048,7 +1090,7 @@ struct smb_version_operations smb30_operations = { ...@@ -1048,7 +1090,7 @@ struct smb_version_operations smb30_operations = {
.logoff = SMB2_logoff, .logoff = SMB2_logoff,
.tree_connect = SMB2_tcon, .tree_connect = SMB2_tcon,
.tree_disconnect = SMB2_tdis, .tree_disconnect = SMB2_tdis,
.qfs_tcon = smb2_qfs_tcon, .qfs_tcon = smb3_qfs_tcon,
.is_path_accessible = smb2_is_path_accessible, .is_path_accessible = smb2_is_path_accessible,
.can_echo = smb2_can_echo, .can_echo = smb2_can_echo,
.echo = SMB2_echo, .echo = SMB2_echo,
......
...@@ -2373,8 +2373,11 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2373,8 +2373,11 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
} else if (level == FS_ATTRIBUTE_INFORMATION) { } else if (level == FS_ATTRIBUTE_INFORMATION) {
max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO); max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO);
min_len = MIN_FS_ATTR_INFO_SIZE; min_len = MIN_FS_ATTR_INFO_SIZE;
} else if (level == FS_SECTOR_SIZE_INFORMATION) {
max_len = sizeof(struct smb3_fs_ss_info);
min_len = sizeof(struct smb3_fs_ss_info);
} else { } else {
cifs_dbg(FYI, "Invalid qfsinfo level %d", level); cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level);
return -EINVAL; return -EINVAL;
} }
...@@ -2403,6 +2406,13 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2403,6 +2406,13 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
else if (level == FS_DEVICE_INFORMATION) else if (level == FS_DEVICE_INFORMATION)
memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset
+ (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO)); + (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
else if (level == FS_SECTOR_SIZE_INFORMATION) {
struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
(4 /* RFC1001 len */ + offset + (char *)&rsp->hdr);
tcon->ss_flags = le32_to_cpu(ss_info->Flags);
tcon->perf_sector_size =
le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
}
qfsattr_exit: qfsattr_exit:
free_rsp_buf(resp_buftype, iov.iov_base); free_rsp_buf(resp_buftype, iov.iov_base);
......
...@@ -877,14 +877,16 @@ struct smb2_lease_ack { ...@@ -877,14 +877,16 @@ struct smb2_lease_ack {
/* File System Information Classes */ /* File System Information Classes */
#define FS_VOLUME_INFORMATION 1 /* Query */ #define FS_VOLUME_INFORMATION 1 /* Query */
#define FS_LABEL_INFORMATION 2 /* Set */ #define FS_LABEL_INFORMATION 2 /* Local only */
#define FS_SIZE_INFORMATION 3 /* Query */ #define FS_SIZE_INFORMATION 3 /* Query */
#define FS_DEVICE_INFORMATION 4 /* Query */ #define FS_DEVICE_INFORMATION 4 /* Query */
#define FS_ATTRIBUTE_INFORMATION 5 /* Query */ #define FS_ATTRIBUTE_INFORMATION 5 /* Query */
#define FS_CONTROL_INFORMATION 6 /* Query, Set */ #define FS_CONTROL_INFORMATION 6 /* Query, Set */
#define FS_FULL_SIZE_INFORMATION 7 /* Query */ #define FS_FULL_SIZE_INFORMATION 7 /* Query */
#define FS_OBJECT_ID_INFORMATION 8 /* Query, Set */ #define FS_OBJECT_ID_INFORMATION 8 /* Query, Set */
#define FS_DRIVER_PATH_INFORMATION 9 /* Query */ #define FS_DRIVER_PATH_INFORMATION 9 /* Local only */
#define FS_VOLUME_FLAGS_INFORMATION 10 /* Local only */
#define FS_SECTOR_SIZE_INFORMATION 11 /* SMB3 or later. Query */
struct smb2_fs_full_size_info { struct smb2_fs_full_size_info {
__le64 TotalAllocationUnits; __le64 TotalAllocationUnits;
...@@ -894,6 +896,22 @@ struct smb2_fs_full_size_info { ...@@ -894,6 +896,22 @@ struct smb2_fs_full_size_info {
__le32 BytesPerSector; __le32 BytesPerSector;
} __packed; } __packed;
#define SSINFO_FLAGS_ALIGNED_DEVICE 0x00000001
#define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE 0x00000002
#define SSINFO_FLAGS_NO_SEEK_PENALTY 0x00000004
#define SSINFO_FLAGS_TRIM_ENABLED 0x00000008
/* sector size info struct */
struct smb3_fs_ss_info {
__le32 LogicalBytesPerSector;
__le32 PhysicalBytesPerSectorForAtomicity;
__le32 PhysicalBytesPerSectorForPerf;
__le32 FileSystemEffectivePhysicalBytesPerSectorForAtomicity;
__le32 Flags;
__le32 ByteOffsetForSectorAlignment;
__le32 ByteOffsetForPartitionAlignment;
} __packed;
/* partial list of QUERY INFO levels */ /* partial list of QUERY INFO levels */
#define FILE_DIRECTORY_INFORMATION 1 #define FILE_DIRECTORY_INFORMATION 1
#define FILE_FULL_DIRECTORY_INFORMATION 2 #define FILE_FULL_DIRECTORY_INFORMATION 2
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment