Add documentation to block sysfs specifications.

Signed-off-by: Sasha Levin <[email protected]>
---
 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


Reply via email to