lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250624180742.5795-21-sashal@kernel.org>
Date: Tue, 24 Jun 2025 14:07:40 -0400
From: Sasha Levin <sashal@...nel.org>
To: linux-kernel@...r.kernel.org
Cc: linux-doc@...r.kernel.org,
	linux-api@...r.kernel.org,
	workflows@...r.kernel.org,
	tools@...nel.org,
	Sasha Levin <sashal@...nel.org>
Subject: [RFC v2 20/22] block: sysfs API specifications

Add documentation to block sysfs specifications.

Signed-off-by: Sasha Levin <sashal@...nel.org>
---
 block/blk-integrity.c | 131 +++++++++++++++++++++++
 block/blk-sysfs.c     | 243 ++++++++++++++++++++++++++++++++++++++++++
 block/genhd.c         |  99 +++++++++++++++++
 3 files changed, 473 insertions(+)

diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index e4e2567061f9d..bfe08c8fab91b 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -13,6 +13,8 @@
 #include <linux/scatterlist.h>
 #include <linux/export.h>
 #include <linux/slab.h>
+#include <linux/kernel_api_spec.h>
+#include <linux/syscall_api_spec.h>
 
 #include "blk.h"
 
@@ -234,6 +236,29 @@ static ssize_t flag_show(struct device *dev, char *page, unsigned char flag)
 	return sysfs_emit(page, "%d\n", !(bi->flags & flag));
 }
 
+/*
+ * Sysfs API specifications for integrity attributes
+ */
+DEFINE_SYSFS_API_SPEC(format)
+	KAPI_DESCRIPTION("Metadata format for integrity")
+	KAPI_LONG_DESC("Metadata format for integrity capable block device. "
+		       "E.g. T10-DIF-TYPE1-CRC. This field describes the type of T10 "
+		       "Protection Information that the block device can send and receive. "
+		       "If the device can store application integrity metadata but "
+		       "no T10 Protection Information profile is used, this field "
+		       "contains 'nop'. If the device does not support integrity "
+		       "metadata, this field contains 'none'.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "format", "string", "Integrity metadata format")
+		KAPI_PARAM_TYPE(KAPI_TYPE_STRING)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/integrity/format")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/integrity/format")
+KAPI_END_SPEC;
+
 static ssize_t format_show(struct device *dev, struct device_attribute *attr,
 			   char *page)
 {
@@ -244,6 +269,33 @@ static ssize_t format_show(struct device *dev, struct device_attribute *attr,
 	return sysfs_emit(page, "%s\n", blk_integrity_profile_name(bi));
 }
 
+DEFINE_SYSFS_API_SPEC(tag_size)
+	KAPI_DESCRIPTION("Integrity tag size")
+	KAPI_LONG_DESC("Number of bytes of integrity tag space available per "
+		       "protection_interval_bytes, which is typically "
+		       "the device's logical block size. "
+		       "This field describes the size of the application tag "
+		       "if the storage device is formatted with T10 Protection "
+		       "Information and permits use of the application tag.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "tag_size", "unsigned int", "Tag size in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/integrity/tag_size")
+		KAPI_PARAM_RANGE(0, 65535)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/integrity/tag_size")
+	KAPI_NOTES("If the device does not support T10 Protection Information (even if the "
+		   "device provides application integrity metadata space), this field is set to 0. "
+		   "The owner of this tag space is the owner of the block device. The filesystem "
+		   "can use this extra space to tag sectors as they see fit. Because the tag space "
+		   "is limited, the block interface allows tagging bigger chunks by way of interleaving. "
+		   "This way, 8*16 bits of information can be attached to a typical 4KB filesystem block.")
+KAPI_END_SPEC;
+
 static ssize_t tag_size_show(struct device *dev, struct device_attribute *attr,
 			     char *page)
 {
@@ -252,6 +304,26 @@ static ssize_t tag_size_show(struct device *dev, struct device_attribute *attr,
 	return sysfs_emit(page, "%u\n", bi->tag_size);
 }
 
+DEFINE_SYSFS_API_SPEC(protection_interval_bytes)
+	KAPI_DESCRIPTION("Protection interval size")
+	KAPI_LONG_DESC("Describes the number of data bytes which are protected by one "
+		       "integrity tuple. Typically the device's logical block size. "
+		       "For example, a 512-byte sector with 8-byte integrity metadata "
+		       "would have a protection interval of 512 bytes.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "protection_interval_bytes", "unsigned int", "Protection interval in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/integrity/protection_interval_bytes")
+		KAPI_PARAM_RANGE(0, 65536)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/integrity/protection_interval_bytes")
+	KAPI_NOTES("This is typically the same as the device's logical block size")
+KAPI_END_SPEC;
+
 static ssize_t protection_interval_bytes_show(struct device *dev,
 					      struct device_attribute *attr,
 					      char *page)
@@ -275,6 +347,25 @@ static ssize_t read_verify_show(struct device *dev,
 	return flag_show(dev, page, BLK_INTEGRITY_NOVERIFY);
 }
 
+DEFINE_SYSFS_API_SPEC(read_verify)
+	KAPI_DESCRIPTION("Read request integrity verification")
+	KAPI_LONG_DESC("Indicates whether the block layer should verify the integrity "
+		       "of read requests serviced by devices that support sending "
+		       "integrity metadata. A value of 1 enables verification, while "
+		       "0 disables it. When enabled, the block layer will check "
+		       "integrity metadata on read operations.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "read_verify", "bool", "Enable read integrity verification")
+		KAPI_PARAM_TYPE(KAPI_TYPE_BOOL)
+		KAPI_PERMISSIONS(0644)
+		KAPI_PATH("/sys/block/<disk>/integrity/read_verify")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_RW)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("echo 1 > /sys/block/sda/integrity/read_verify")
+	KAPI_NOTES("This attribute only has effect if the device supports integrity metadata")
+KAPI_END_SPEC;
+
 static ssize_t write_generate_store(struct device *dev,
 				    struct device_attribute *attr,
 				    const char *page, size_t count)
@@ -288,6 +379,46 @@ static ssize_t write_generate_show(struct device *dev,
 	return flag_show(dev, page, BLK_INTEGRITY_NOGENERATE);
 }
 
+DEFINE_SYSFS_API_SPEC(write_generate)
+	KAPI_DESCRIPTION("Write request integrity generation")
+	KAPI_LONG_DESC("Indicates whether the block layer should automatically generate "
+		       "checksums for write requests bound for devices that support "
+		       "receiving integrity metadata. A value of 1 enables generation, "
+		       "while 0 disables it. When enabled, the block layer will compute "
+		       "and attach integrity metadata to write operations.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "write_generate", "bool", "Enable write integrity generation")
+		KAPI_PARAM_TYPE(KAPI_TYPE_BOOL)
+		KAPI_PERMISSIONS(0644)
+		KAPI_PATH("/sys/block/<disk>/integrity/write_generate")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_RW)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("echo 1 > /sys/block/sda/integrity/write_generate")
+	KAPI_NOTES("This attribute only has effect if the device supports integrity metadata")
+KAPI_END_SPEC;
+
+DEFINE_SYSFS_API_SPEC(device_is_integrity_capable)
+	KAPI_DESCRIPTION("Device integrity capability")
+	KAPI_LONG_DESC("Indicates whether a storage device is capable of storing "
+		       "integrity metadata. Set if the device is T10 PI-capable. "
+		       "This flag is set to 1 if the storage media is formatted "
+		       "with T10 Protection Information. If the storage media is "
+		       "not formatted with T10 Protection Information, this flag "
+		       "is set to 0. This is a key indicator for whether the device "
+		       "supports end-to-end data protection using standards like "
+		       "T10 DIF (Data Integrity Field) for SCSI devices.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "device_is_integrity_capable", "bool", "Device integrity capability flag")
+		KAPI_PARAM_TYPE(KAPI_TYPE_BOOL)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/integrity/device_is_integrity_capable")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/integrity/device_is_integrity_capable")
+KAPI_END_SPEC;
+
 static ssize_t device_is_integrity_capable_show(struct device *dev,
 						struct device_attribute *attr,
 						char *page)
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index b2b9b89d6967c..8446ed4fc63d8 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -10,6 +10,8 @@
 #include <linux/backing-dev.h>
 #include <linux/blktrace_api.h>
 #include <linux/debugfs.h>
+#include <linux/kernel_api_spec.h>
+#include <linux/syscall_api_spec.h>
 
 #include "blk.h"
 #include "blk-mq.h"
@@ -51,6 +53,31 @@ queue_var_store(unsigned long *var, const char *page, size_t count)
 	return count;
 }
 
+DEFINE_SYSFS_API_SPEC(nr_requests)
+	KAPI_DESCRIPTION("Number of allocatable requests")
+	KAPI_LONG_DESC("This controls how many requests may be allocated in the "
+		       "block layer for read or write requests. Note that the total "
+		       "allocated number may be twice this amount, since it applies only "
+		       "to reads or writes (not the accumulated sum). "
+		       "When CONFIG_BLK_CGROUP is enabled, each request queue may have "
+		       "up to N request pools for N block cgroups.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "nr_requests", "unsigned int", "Number of allocatable requests")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0644)
+		KAPI_PATH("/sys/block/<disk>/queue/nr_requests")
+		KAPI_PARAM_RANGE(BLKDEV_MIN_RQ, INT_MAX)
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_RW)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("echo 256 > /sys/block/sda/queue/nr_requests")
+	KAPI_NOTES("To avoid priority inversion through request starvation, a request queue "
+		   "maintains a separate request pool per each cgroup when CONFIG_BLK_CGROUP "
+		   "is enabled, and this parameter applies to each such per-block-cgroup "
+		   "request pool. IOW, if there are N block cgroups, each request queue may "
+		   "have up to N request pools, each independently regulated by nr_requests.")
+KAPI_END_SPEC;
+
 static ssize_t queue_requests_show(struct gendisk *disk, char *page)
 {
 	ssize_t ret;
@@ -89,6 +116,29 @@ queue_requests_store(struct gendisk *disk, const char *page, size_t count)
 	return ret;
 }
 
+DEFINE_SYSFS_API_SPEC(read_ahead_kb)
+	KAPI_DESCRIPTION("Read-ahead size")
+	KAPI_LONG_DESC("Maximum number of kilobytes to read-ahead for filesystems "
+		       "on this block device. For MADV_HUGEPAGE, the readahead size "
+		       "may exceed this setting since its granularity is based on the "
+		       "hugepage size.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "read_ahead_kb", "unsigned int", "Read-ahead size in kilobytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0644)
+		KAPI_PATH("/sys/block/<disk>/queue/read_ahead_kb")
+		KAPI_PARAM_RANGE(0, ULONG_MAX >> (PAGE_SHIFT - 10))
+		KAPI_UNITS("kilobytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_RW)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("echo 128 > /sys/block/sda/queue/read_ahead_kb")
+	KAPI_NOTES("128 KB for each device is a good starting point, but increasing to "
+		   "4-8 MB might improve performance in environments where sequential "
+		   "reading of large files takes place. Changes are not persistent "
+		   "across reboots unless saved in startup scripts.")
+KAPI_END_SPEC;
+
 static ssize_t queue_ra_show(struct gendisk *disk, char *page)
 {
 	ssize_t ret;
@@ -124,6 +174,62 @@ queue_ra_store(struct gendisk *disk, const char *page, size_t count)
 	return ret;
 }
 
+/*
+ * Sysfs API specifications for queue attributes
+ */
+DEFINE_SYSFS_API_SPEC(logical_block_size)
+	KAPI_DESCRIPTION("Logical block size")
+	KAPI_LONG_DESC("This is the smallest unit the storage device can address. "
+		       "It is typically 512 bytes.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "logical_block_size", "unsigned int", "Logical block size in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PATH("/sys/block/<disk>/queue/logical_block_size")
+		KAPI_PERMISSIONS(0444)
+		KAPI_PARAM_RANGE(512, 4096)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/queue/logical_block_size")
+KAPI_END_SPEC;
+
+DEFINE_SYSFS_API_SPEC(physical_block_size)
+	KAPI_DESCRIPTION("Physical block size")
+	KAPI_LONG_DESC("This is the smallest unit a physical storage device can "
+		       "write atomically. It is usually the same as the logical block "
+		       "size but may be bigger. One example is SATA drives with 4KB "
+		       "sectors that expose a 512-byte logical block size to the "
+		       "operating system.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "physical_block_size", "unsigned int", "Physical block size in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/queue/physical_block_size")
+		KAPI_PARAM_RANGE(512, 4194304)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/queue/physical_block_size")
+KAPI_END_SPEC;
+
+DEFINE_SYSFS_API_SPEC(hw_sector_size)
+	KAPI_DESCRIPTION("Hardware sector size")
+	KAPI_LONG_DESC("This is the hardware sector size of the device, in bytes.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "hw_sector_size", "unsigned int", "Hardware sector size in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/queue/hw_sector_size")
+		KAPI_PARAM_RANGE(512, 4194304)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/queue/hw_sector_size")
+KAPI_END_SPEC;
+
 #define QUEUE_SYSFS_LIMIT_SHOW(_field)					\
 static ssize_t queue_##_field##_show(struct gendisk *disk, char *page)	\
 {									\
@@ -147,7 +253,53 @@ QUEUE_SYSFS_LIMIT_SHOW(virt_boundary_mask)
 QUEUE_SYSFS_LIMIT_SHOW(dma_alignment)
 QUEUE_SYSFS_LIMIT_SHOW(max_open_zones)
 QUEUE_SYSFS_LIMIT_SHOW(max_active_zones)
+DEFINE_SYSFS_API_SPEC(atomic_write_unit_min_bytes)
+	KAPI_DESCRIPTION("Minimum atomic write unit size")
+	KAPI_LONG_DESC("This parameter specifies the smallest block which can "
+		       "be written atomically with an atomic write operation. All "
+		       "atomic write operations must begin at a "
+		       "atomic_write_unit_min boundary and must be multiples of "
+		       "atomic_write_unit_min. This value must be a power-of-two.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "atomic_write_unit_min_bytes", "unsigned int", "Minimum atomic write unit size in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/queue/atomic_write_unit_min_bytes")
+		KAPI_PARAM_RANGE(0, ULLONG_MAX)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/nvme0n1/queue/atomic_write_unit_min_bytes")
+	KAPI_NOTES("This value must be a power-of-two. All atomic write operations must "
+		   "begin at a atomic_write_unit_min boundary and must be multiples of "
+		   "atomic_write_unit_min.")
+KAPI_END_SPEC;
+
 QUEUE_SYSFS_LIMIT_SHOW(atomic_write_unit_min)
+
+DEFINE_SYSFS_API_SPEC(atomic_write_unit_max_bytes)
+	KAPI_DESCRIPTION("Maximum atomic write unit size")
+	KAPI_LONG_DESC("This parameter defines the largest block which can be "
+		       "written atomically with an atomic write operation. This "
+		       "value must be a multiple of atomic_write_unit_min and must "
+		       "be a power-of-two. This value will not be larger than "
+		       "atomic_write_max_bytes.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "atomic_write_unit_max_bytes", "unsigned int", "Maximum atomic write unit size in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/queue/atomic_write_unit_max_bytes")
+		KAPI_PARAM_RANGE(0, ULLONG_MAX)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/nvme0n1/queue/atomic_write_unit_max_bytes")
+	KAPI_NOTES("This value must be a multiple of atomic_write_unit_min and must be a "
+		   "power-of-two. This value will not be larger than atomic_write_max_bytes.")
+KAPI_END_SPEC;
+
 QUEUE_SYSFS_LIMIT_SHOW(atomic_write_unit_max)
 
 #define QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(_field)			\
@@ -161,7 +313,60 @@ static ssize_t queue_##_field##_show(struct gendisk *disk, char *page)	\
 QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(max_discard_sectors)
 QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(max_hw_discard_sectors)
 QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(max_write_zeroes_sectors)
+
+DEFINE_SYSFS_API_SPEC(atomic_write_max_bytes)
+	KAPI_DESCRIPTION("Maximum atomic write size")
+	KAPI_LONG_DESC("This parameter specifies the maximum atomic write "
+		       "size reported by the device. This parameter is relevant "
+		       "for merging of writes, where a merged atomic write "
+		       "operation must not exceed this number of bytes. "
+		       "This parameter may be greater than atomic_write_unit_max_bytes.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "atomic_write_max_bytes", "unsigned int", "Maximum atomic write size in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/queue/atomic_write_max_bytes")
+		KAPI_PARAM_RANGE(0, ULLONG_MAX)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/nvme0n1/queue/atomic_write_max_bytes")
+	KAPI_NOTES("This parameter is relevant for merging of writes, where a merged atomic "
+		   "write operation must not exceed this number of bytes. May be greater than "
+		   "atomic_write_unit_max_bytes as atomic_write_unit_max_bytes will be rounded "
+		   "down to a power-of-two and may also be limited by other queue limits such "
+		   "as max_segments. Will not be larger than max_hw_sectors_kb.")
+KAPI_END_SPEC;
+
 QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(atomic_write_max_sectors)
+
+DEFINE_SYSFS_API_SPEC(atomic_write_boundary_bytes)
+	KAPI_DESCRIPTION("Atomic write boundary size")
+	KAPI_LONG_DESC("A device may need to internally split an atomic write I/O "
+		       "which straddles a given logical block address boundary. This "
+		       "parameter specifies the size in bytes of the atomic boundary if "
+		       "one is reported by the device. This value must be a "
+		       "power-of-two and at least the size as in "
+		       "atomic_write_unit_max_bytes.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "atomic_write_boundary_bytes", "unsigned int", "Atomic write boundary size in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/queue/atomic_write_boundary_bytes")
+		KAPI_PARAM_RANGE(0, ULLONG_MAX)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/nvme0n1/queue/atomic_write_boundary_bytes")
+	KAPI_NOTES("A device may need to internally split an atomic write I/O which straddles "
+		   "a given logical block address boundary. This specifies the size in bytes of "
+		   "the atomic boundary if one is reported by the device. Must be a power-of-two "
+		   "and at least the size as in atomic_write_unit_max_bytes. Any attempt to merge "
+		   "atomic write I/Os must not result in a merged I/O which crosses this boundary.")
+KAPI_END_SPEC;
+
 QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(atomic_write_boundary_sectors)
 QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_BYTES(max_zone_append_sectors)
 
@@ -171,7 +376,45 @@ static ssize_t queue_##_field##_show(struct gendisk *disk, char *page)	\
 	return queue_var_show(disk->queue->limits._field >> 1, page);	\
 }
 
+DEFINE_SYSFS_API_SPEC(max_sectors_kb)
+	KAPI_DESCRIPTION("Maximum request size (software limit)")
+	KAPI_LONG_DESC("This is the maximum number of kilobytes that the block "
+		       "layer will allow for a filesystem request. Must be smaller than "
+		       "or equal to the maximum size allowed by the hardware. Write 0 "
+		       "to use default kernel settings.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "max_sectors_kb", "unsigned int", "Maximum request size in kilobytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0644)
+		KAPI_PATH("/sys/block/<disk>/queue/max_sectors_kb")
+		KAPI_PARAM_RANGE(0, UINT_MAX)
+		KAPI_UNITS("kilobytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_RW)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("echo 512 > /sys/block/sda/queue/max_sectors_kb")
+	KAPI_NOTES("Must be <= max_hw_sectors_kb")
+KAPI_END_SPEC;
+
 QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_KB(max_sectors)
+
+DEFINE_SYSFS_API_SPEC(max_hw_sectors_kb)
+	KAPI_DESCRIPTION("Maximum request size (hardware limit)")
+	KAPI_LONG_DESC("This is the maximum number of kilobytes supported in a "
+		       "single data transfer.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "max_hw_sectors_kb", "unsigned int", "Maximum hardware request size in kilobytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/queue/max_hw_sectors_kb")
+		KAPI_PARAM_RANGE(0, UINT_MAX)
+		KAPI_UNITS("kilobytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/queue/max_hw_sectors_kb")
+KAPI_END_SPEC;
+
 QUEUE_SYSFS_LIMIT_SHOW_SECTORS_TO_KB(max_hw_sectors)
 
 #define QUEUE_SYSFS_SHOW_CONST(_name, _val)				\
diff --git a/block/genhd.c b/block/genhd.c
index 8171a6bc3210f..3cbc5418825f0 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -26,6 +26,8 @@
 #include <linux/badblocks.h>
 #include <linux/part_stat.h>
 #include <linux/blktrace_api.h>
+#include <linux/kernel_api_spec.h>
+#include <linux/syscall_api_spec.h>
 
 #include "blk-throttle.h"
 #include "blk.h"
@@ -1104,6 +1106,25 @@ ssize_t part_stat_show(struct device *dev,
  * For bio-based device, started from bdev_start_io_acct();
  * For rq-based device, started from blk_mq_start_request();
  */
+DEFINE_SYSFS_API_SPEC(inflight)
+	KAPI_DESCRIPTION("I/O requests in progress")
+	KAPI_LONG_DESC("Reports the number of I/O requests currently in progress "
+		       "(pending / in flight) in a device driver. This can be less "
+		       "than the number of requests queued in the block device queue. "
+		       "The report contains 2 fields: one for read requests "
+		       "and one for write requests.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "inflight", "string", "Two unsigned integers: read and write requests in flight")
+		KAPI_PARAM_TYPE(KAPI_TYPE_STRING)
+		KAPI_PATH("/sys/block/<disk>/inflight")
+		KAPI_PERMISSIONS(0444)
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/inflight")
+	KAPI_NOTES("The value type is unsigned int. Related to /sys/block/<disk>/queue/nr_requests")
+KAPI_END_SPEC;
+
 ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
@@ -1123,6 +1144,28 @@ static ssize_t disk_capability_show(struct device *dev,
 	return sysfs_emit(buf, "0\n");
 }
 
+/*
+ * Sysfs API specifications for disk attributes
+ */
+DEFINE_SYSFS_API_SPEC(alignment_offset)
+	KAPI_DESCRIPTION("Physical block alignment offset")
+	KAPI_LONG_DESC("Storage devices may report a physical block size that is "
+		       "bigger than the logical block size. This parameter "
+		       "indicates how many bytes the beginning of the device is "
+		       "offset from the disk's natural alignment.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "alignment_offset", "int", "Alignment offset in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_INT)
+		KAPI_PATH("/sys/block/<disk>/alignment_offset")
+		KAPI_PERMISSIONS(0444)
+		KAPI_PARAM_RANGE(0, INT_MAX)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/alignment_offset")
+KAPI_END_SPEC;
+
 static ssize_t disk_alignment_offset_show(struct device *dev,
 					  struct device_attribute *attr,
 					  char *buf)
@@ -1132,6 +1175,27 @@ static ssize_t disk_alignment_offset_show(struct device *dev,
 	return sysfs_emit(buf, "%d\n", bdev_alignment_offset(disk->part0));
 }
 
+DEFINE_SYSFS_API_SPEC(discard_alignment)
+	KAPI_DESCRIPTION("Discard alignment offset")
+	KAPI_LONG_DESC("Devices that support discard functionality may "
+		       "internally allocate space in units that are bigger than "
+		       "the exported logical block size. The discard_alignment "
+		       "parameter indicates how many bytes the beginning of the "
+		       "device is offset from the internal allocation unit's "
+		       "natural alignment.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "discard_alignment", "int", "Discard alignment offset in bytes")
+		KAPI_PARAM_TYPE(KAPI_TYPE_INT)
+		KAPI_PATH("/sys/block/<disk>/discard_alignment")
+		KAPI_PERMISSIONS(0444)
+		KAPI_PARAM_RANGE(0, INT_MAX)
+		KAPI_UNITS("bytes")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/discard_alignment")
+KAPI_END_SPEC;
+
 static ssize_t disk_discard_alignment_show(struct device *dev,
 					   struct device_attribute *attr,
 					   char *buf)
@@ -1141,6 +1205,25 @@ static ssize_t disk_discard_alignment_show(struct device *dev,
 	return sysfs_emit(buf, "%d\n", bdev_alignment_offset(disk->part0));
 }
 
+DEFINE_SYSFS_API_SPEC(diskseq)
+	KAPI_DESCRIPTION("Disk sequence number")
+	KAPI_LONG_DESC("The diskseq attribute reports the disk sequence number, "
+		       "which is a monotonically increasing number assigned to "
+		       "every drive. Some devices, like the loop device, refresh "
+		       "this number every time the backing file is changed.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "diskseq", "uint64_t", "64-bit disk sequence number")
+		KAPI_PARAM_TYPE(KAPI_TYPE_UINT)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/diskseq")
+		KAPI_PARAM_RANGE(0, ULLONG_MAX)
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/diskseq")
+	KAPI_NOTES("Value type is 64 bit unsigned")
+KAPI_END_SPEC;
+
 static ssize_t diskseq_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
@@ -1149,6 +1232,22 @@ static ssize_t diskseq_show(struct device *dev,
 	return sysfs_emit(buf, "%llu\n", disk->diskseq);
 }
 
+DEFINE_SYSFS_API_SPEC(partscan)
+	KAPI_DESCRIPTION("Partition scanning status")
+	KAPI_LONG_DESC("Reports if partition scanning is enabled for the disk. "
+		       "Returns '1' if partition scanning is enabled, or '0' if not.")
+	KAPI_PARAM_COUNT(1)
+	KAPI_PARAM(0, "partscan", "bool", "Partition scanning enabled flag")
+		KAPI_PARAM_TYPE(KAPI_TYPE_BOOL)
+		KAPI_PERMISSIONS(0444)
+		KAPI_PATH("/sys/block/<disk>/partscan")
+		KAPI_PARAM_FLAGS(KAPI_PARAM_SYSFS_READONLY)
+	KAPI_PARAM_END
+	KAPI_SUBSYSTEM("block")
+	KAPI_EXAMPLES("cat /sys/block/sda/partscan")
+	KAPI_NOTES("The value type is a 32-bit unsigned integer, but only '0' and '1' are valid values")
+KAPI_END_SPEC;
+
 static ssize_t partscan_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-- 
2.39.5


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ