From patchwork Wed Jul 21 10:42:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 12390687 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E6ECC636C9 for ; Wed, 21 Jul 2021 11:33:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2CEA06109F for ; Wed, 21 Jul 2021 11:33:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237566AbhGUKwO (ORCPT ); Wed, 21 Jul 2021 06:52:14 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:53609 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238997AbhGUKBn (ORCPT ); Wed, 21 Jul 2021 06:01:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1626864137; x=1658400137; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=CU+e4sS6gth+Cfnm1xAN4p/coEJ7DQfiO8rP00tgzFw=; b=Nodx+hPrW0anGBLeNsRwLwonVTQ2j5YhhQ7gx71cLyJ8DedMLX4JoZmJ zow3WaBJl5zN7sj56MSYBIutMVJNn1/Oq0Ipijg7szolZQWi8gisNC7MR OxxA30o3ANSoVBu4Ns0FOqK0/vNXCDp5IEE0RBwYqiFpQsG+xhkbWIx0o LigjbbrcG2ZXdw0DNMLAH0/F5U97sdYcMviwqoJS8EOBrkrg6gb2NIh0R ckXyAoGkqJPVENT1DK4OiyPjGgHaUlwyj2LDhFsU6PeJ7kwtHlABBDup0 NKdVAzrDJDQB4vNS1AkobXgmSAFoU0BnnZ7dt/ibzWsK/hPMYot+WWBN5 w==; X-IronPort-AV: E=Sophos;i="5.84,257,1620662400"; d="scan'208";a="179944861" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 21 Jul 2021 18:42:09 +0800 IronPort-SDR: GJbu9cF8ULx+kYp+WqiRUjFAu+q+4hFYeUHELK4WeN+QwmE2QkcXVPlKl8vbdhtuXtqCkjuGXw /xbSBA2DgiXa5r7jyqR/6+5RznPFP/3o6STNiELoEE3d47+ZnRUZakfs0vYfaGcgQyzhPVJbtj PWSHndEsA3ktOZjJwOLbg8ch6DthJxx3cHWuiQk0oaaes37nqghWmKLSGNzy+/dTkz/Pl8ySlj 6BQdbQjr0zrRZaHp7qCGWL0MgSTCQKYCD3GWkju9E7WW/IQIKMmh+m117UlLAe1E+dGf1L2zdC qqWnF8stkGA53cLDQBn0LHu6 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2021 03:20:03 -0700 IronPort-SDR: UVCKnDUWFypa5SMMMeOK0jJ1RUiH8b5CxsoFhdhkLKW/dWxcatZRTwmxzmROZB2D7wYmxiyfxP YexGrr3kELoOFGr/AWlSjTvNTBblhKxAcDnjsmhGerqRDnhPMEFBuY/t38b66lU+c8KVK8Gmf2 iQY2OKBI320rpT+oVQD+2FYD08yRcsJmTaIcdQhhUhRG0Y8Hy317H0HF/eU3aDvKqM1FjpybBt jF5SBeCeicUmfW7HOjgBZsffGCXaLDjA3KrdBucAB3Bh7Kbg/HKwiejql7RBsGgi0q6I2cjzag 2uY= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip02.wdc.com with ESMTP; 21 Jul 2021 03:42:09 -0700 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , linux-ide@vger.kernel.org Subject: [PATCH 1/4] block: Add concurrent positioning ranges support Date: Wed, 21 Jul 2021 19:42:02 +0900 Message-Id: <20210721104205.885115-2-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210721104205.885115-1-damien.lemoal@wdc.com> References: <20210721104205.885115-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org The Concurrent Positioning Ranges VPD page (for SCSI) and Log (for ATA) contain parameters describing the number of sets of contiguous LBAs that can be served independently by a single LUN multi-actuator disk. This patch provides the blk_queue_set_cranges() function allowing a device driver to signal to the block layer that a disk has multiple actuators, each one serving a contiguous range of sectors. To describe the set of sector ranges representing the different actuators of a device, the data type struct blk_cranges is introduced. For a device with multiple actuators, a struct blk_cranges is attached to the device request queue by the blk_queue_set_cranges() function. The function blk_alloc_cranges() is provided for drivers to allocate this structure. The blk_cranges structure contains kobjects (struct kobject) to register with sysfs the set of sector ranges defined by a device. On initial device scan, this registration is done from blk_register_queue() using the block layer internal function blk_register_cranges(). If a driver calls blk_queue_set_cranges() for a registered queue, e.g. when a device is revalidated, blk_queue_set_cranges() will execute blk_register_cranges() to update the queue sysfs attribute files. The sysfs file structure created starts from the cranges sub-directory and contains the start sector and number of sectors served by an actuator, with the information for each actuator grouped in one directory per actuator. E.g. for a dual actuator drive, we have: $ tree /sys/block/sdk/queue/cranges/ /sys/block/sdk/queue/cranges/ |-- 0 | |-- nr_sectors | `-- sector `-- 1 |-- nr_sectors `-- sector For a regular single actuator device, the cranges directory does not exist. Device revalidation may lead to changes to this structure and to the attribute values. When manipulated, the queue sysfs_lock and sysfs_dir_lock are held for atomicity, similarly to how the blk-mq and elevator sysfs queue sub-directories are protected. The code related to the management of cranges is added in the new file block/blk-cranges.c. Signed-off-by: Damien Le Moal --- block/Makefile | 2 +- block/blk-cranges.c | 286 ++++++++++++++++++++++++++++++++++++++ block/blk-sysfs.c | 13 ++ block/blk.h | 3 + drivers/ata/libata-scsi.c | 1 + include/linux/blkdev.h | 29 ++++ 6 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 block/blk-cranges.c diff --git a/block/Makefile b/block/Makefile index bfbe4e13ca1e..e477e6ca9ea6 100644 --- a/block/Makefile +++ b/block/Makefile @@ -9,7 +9,7 @@ obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-core.o blk-sysfs.o \ blk-lib.o blk-mq.o blk-mq-tag.o blk-stat.o \ blk-mq-sysfs.o blk-mq-cpumap.o blk-mq-sched.o ioctl.o \ genhd.o ioprio.o badblocks.o partitions/ blk-rq-qos.o \ - disk-events.o + disk-events.o blk-cranges.o obj-$(CONFIG_BOUNCE) += bounce.o obj-$(CONFIG_BLK_SCSI_REQUEST) += scsi_ioctl.o diff --git a/block/blk-cranges.c b/block/blk-cranges.c new file mode 100644 index 000000000000..e8ff0d40a5c9 --- /dev/null +++ b/block/blk-cranges.c @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Block device concurrent positioning ranges. + * + * Copyright (C) 2021 Western Digital Corporation or its Affiliates. + */ +#include +#include +#include +#include + +#include "blk.h" + +static ssize_t blk_crange_sector_show(struct blk_crange *cr, char *page) +{ + return sprintf(page, "%llu\n", cr->sector); +} + +static ssize_t blk_crange_nr_sectors_show(struct blk_crange *cr, char *page) +{ + return sprintf(page, "%llu\n", cr->nr_sectors); +} + +struct blk_crange_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct blk_crange *cr, char *page); +}; + +static struct blk_crange_sysfs_entry blk_crange_sector_entry = { + .attr = { .name = "sector", .mode = 0444 }, + .show = blk_crange_sector_show, +}; + +static struct blk_crange_sysfs_entry blk_crange_nr_sectors_entry = { + .attr = { .name = "nr_sectors", .mode = 0444 }, + .show = blk_crange_nr_sectors_show, +}; + +static struct attribute *blk_crange_attrs[] = { + &blk_crange_sector_entry.attr, + &blk_crange_nr_sectors_entry.attr, + NULL, +}; +ATTRIBUTE_GROUPS(blk_crange); + +static ssize_t blk_crange_sysfs_show(struct kobject *kobj, + struct attribute *attr, char *page) +{ + struct blk_crange_sysfs_entry *entry; + struct blk_crange *cr; + struct request_queue *q; + ssize_t ret; + + entry = container_of(attr, struct blk_crange_sysfs_entry, attr); + cr = container_of(kobj, struct blk_crange, kobj); + q = cr->queue; + + mutex_lock(&q->sysfs_lock); + ret = entry->show(cr, page); + mutex_unlock(&q->sysfs_lock); + + return ret; +} + +static const struct sysfs_ops blk_crange_sysfs_ops = { + .show = blk_crange_sysfs_show, +}; + +/* + * Dummy release function to make kobj happy. + */ +static void blk_cranges_sysfs_nop_release(struct kobject *kobj) +{ +} + +static struct kobj_type blk_crange_ktype = { + .sysfs_ops = &blk_crange_sysfs_ops, + .default_groups = blk_crange_groups, + .release = blk_cranges_sysfs_nop_release, +}; + +static struct kobj_type blk_cranges_ktype = { + .release = blk_cranges_sysfs_nop_release, +}; + +/** + * blk_register_cranges - register with sysfs a set of concurrent ranges + * @disk: Target disk + * @new_cranges: New set of concurrent ranges + * + * Register with sysfs a set of concurrent ranges for @disk. If @new_cranges + * is not NULL, this set of concurrent ranges is registered and the + * old set specified by q->cranges is unregistered. Otherwise, q->cranges + * is registered if it is not already. + */ +int blk_register_cranges(struct gendisk *disk, struct blk_cranges *new_cranges) +{ + struct request_queue *q = disk->queue; + struct blk_cranges *cranges; + int i, ret; + + lockdep_assert_held(&q->sysfs_dir_lock); + lockdep_assert_held(&q->sysfs_lock); + + /* If a new range set is specified, unregister the old one */ + if (new_cranges) { + if (q->cranges) + blk_unregister_cranges(disk); + q->cranges = new_cranges; + } + + cranges = q->cranges; + if (!cranges) + return 0; + + /* + * At this point, q->cranges is the new set of sector ranges that needs + * to be registered with sysfs. + */ + WARN_ON(cranges->sysfs_registered); + ret = kobject_init_and_add(&cranges->kobj, &blk_cranges_ktype, + &q->kobj, "%s", "cranges"); + if (ret) + goto free; + + for (i = 0; i < cranges->nr_ranges; i++) { + cranges->ranges[i].queue = q; + ret = kobject_init_and_add(&cranges->ranges[i].kobj, + &blk_crange_ktype, &cranges->kobj, + "%d", i); + if (ret) + goto delete_obj; + } + + cranges->sysfs_registered = true; + + return 0; + +delete_obj: + while (--i >= 0) + kobject_del(&cranges->ranges[i].kobj); + kobject_del(&cranges->kobj); +free: + kfree(cranges); + q->cranges = NULL; + return ret; +} + +void blk_unregister_cranges(struct gendisk *disk) +{ + struct request_queue *q = disk->queue; + struct blk_cranges *cranges = q->cranges; + int i; + + lockdep_assert_held(&q->sysfs_dir_lock); + lockdep_assert_held(&q->sysfs_lock); + + if (!cranges) + return; + + if (cranges->sysfs_registered) { + for (i = 0; i < cranges->nr_ranges; i++) + kobject_del(&cranges->ranges[i].kobj); + kobject_del(&cranges->kobj); + } + + kfree(cranges); + q->cranges = NULL; +} + +static bool blk_check_ranges(struct gendisk *disk, struct blk_cranges *cr) +{ + sector_t capacity = get_capacity(disk); + sector_t min_sector = (sector_t)-1; + sector_t max_sector = 0; + int i; + + /* + * Sector ranges may overlap but should overall contain all sectors + * within the disk capacity. + */ + for (i = 0; i < cr->nr_ranges; i++) { + min_sector = min(min_sector, cr->ranges[i].sector); + max_sector = max(max_sector, cr->ranges[i].sector + + cr->ranges[i].nr_sectors); + } + + if (min_sector != 0 || max_sector < capacity) { + pr_warn("Invalid concurrent ranges: missing sectors\n"); + return false; + } + + if (max_sector > capacity) { + pr_warn("Invalid concurrent ranges: beyond capacity\n"); + return false; + } + + return true; +} + +static bool blk_cranges_changed(struct gendisk *disk, struct blk_cranges *new) +{ + struct blk_cranges *old = disk->queue->cranges; + int i; + + if (!old || old->nr_ranges != new->nr_ranges) + return true; + + for (i = 0; i < new->nr_ranges; i++) { + if (old->ranges[i].sector != new->ranges[i].sector || + old->ranges[i].nr_sectors != new->ranges[i].nr_sectors) + return true; + } + + return false; +} + +/** + * blk_alloc_cranges - Allocate a concurrent positioning range structure + * @disk: target disk + * @nr_ranges: Number of concurrent ranges + * + * Allocate a struct blk_cranges structure with @nr_ranges range descriptors. + */ +struct blk_cranges *blk_alloc_cranges(struct gendisk *disk, int nr_ranges) +{ + struct blk_cranges *cr; + + cr = kzalloc_node(struct_size(cr, ranges, nr_ranges), GFP_KERNEL, + disk->queue->node); + if (cr) + cr->nr_ranges = nr_ranges; + return cr; +} +EXPORT_SYMBOL_GPL(blk_alloc_cranges); + +/** + * blk_queue_set_cranges - Set a disk concurrent positioning ranges + * @disk: target disk + * @cr: concurrent ranges structure + * + * Set the concurrant positioning ranges information of the request queue + * of @disk to @cr. If @cr is NULL and the concurrent ranges structure + * already set, if any, is cleared. If there are no differences between + * @cr and the concurrent ranges structure already set, @cr is freed. + */ +void blk_queue_set_cranges(struct gendisk *disk, struct blk_cranges *cr) +{ + struct request_queue *q = disk->queue; + + if (WARN_ON_ONCE(cr && !cr->nr_ranges)) { + kfree(cr); + cr = NULL; + } + + mutex_lock(&q->sysfs_dir_lock); + mutex_lock(&q->sysfs_lock); + + if (cr && !blk_check_ranges(disk, cr)) { + kfree(cr); + cr = NULL; + } + + if (!blk_cranges_changed(disk, cr)) { + kfree(cr); + goto unlock; + } + + /* + * This may be called for a registered queue. E.g. during a device + * revalidation. If that is the case, we need to register the new set + * of concurrent ranges. If the queue is not already registered, the + * device request queue registration will register the ranges. + */ + if (blk_queue_registered(q)) { + blk_register_cranges(disk, cr); + } else { + swap(q->cranges, cr); + kfree(cr); + } + +unlock: + mutex_unlock(&q->sysfs_lock); + mutex_unlock(&q->sysfs_dir_lock); +} +EXPORT_SYMBOL_GPL(blk_queue_set_cranges); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 370d83c18057..aeac98ecc5a0 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -899,9 +899,21 @@ int blk_register_queue(struct gendisk *disk) } mutex_lock(&q->sysfs_lock); + + ret = blk_register_cranges(disk, NULL); + if (ret) { + mutex_unlock(&q->sysfs_lock); + mutex_unlock(&q->sysfs_dir_lock); + kobject_del(&q->kobj); + blk_trace_remove_sysfs(dev); + kobject_put(&dev->kobj); + return ret; + } + if (q->elevator) { ret = elv_register_queue(q, false); if (ret) { + blk_unregister_cranges(disk); mutex_unlock(&q->sysfs_lock); mutex_unlock(&q->sysfs_dir_lock); kobject_del(&q->kobj); @@ -985,6 +997,7 @@ void blk_unregister_queue(struct gendisk *disk) mutex_lock(&q->sysfs_lock); if (q->elevator) elv_unregister_queue(q); + blk_unregister_cranges(disk); mutex_unlock(&q->sysfs_lock); mutex_unlock(&q->sysfs_dir_lock); diff --git a/block/blk.h b/block/blk.h index 4b885c0f6708..650c0d87987c 100644 --- a/block/blk.h +++ b/block/blk.h @@ -368,4 +368,7 @@ extern struct device_attribute dev_attr_events; extern struct device_attribute dev_attr_events_async; extern struct device_attribute dev_attr_events_poll_msecs; +int blk_register_cranges(struct gendisk *disk, struct blk_cranges *new_cranges); +void blk_unregister_cranges(struct gendisk *disk); + #endif /* BLK_INTERNAL_H */ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b9588c52815d..144e8cac44ba 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1947,6 +1947,7 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf) 0xb1, /* page 0xb1, block device characteristics page */ 0xb2, /* page 0xb2, thin provisioning page */ 0xb6, /* page 0xb6, zoned block device characteristics */ + 0xb9, /* page 0xb9, concurrent positioning ranges */ }; num_pages = sizeof(pages); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3177181c4326..cd58aa1090a3 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -378,6 +378,29 @@ static inline int blkdev_zone_mgmt_ioctl(struct block_device *bdev, #endif /* CONFIG_BLK_DEV_ZONED */ +/* + * Concurrent sector ranges: struct blk_crange describes range of + * contiguous sectors that can be served by independent resources on the + * device. The set of ranges defined in struct blk_cranges must overall + * include all sectors within the device capacity. + * For a device with multiple ranges, e.g. a single LUN multi-actuator HDD, + * requests targeting sectors in different ranges can be executed in parallel. + * A request can straddle a range boundary. + */ +struct blk_crange { + struct kobject kobj; + struct request_queue *queue; + sector_t sector; + sector_t nr_sectors; +}; + +struct blk_cranges { + struct kobject kobj; + bool sysfs_registered; + unsigned int nr_ranges; + struct blk_crange ranges[]; +}; + struct request_queue { struct request *last_merge; struct elevator_queue *elevator; @@ -570,6 +593,9 @@ struct request_queue { #define BLK_MAX_WRITE_HINTS 5 u64 write_hints[BLK_MAX_WRITE_HINTS]; + + /* Concurrent sector ranges */ + struct blk_cranges *cranges; }; /* Keep blk_queue_flag_name[] in sync with the definitions below */ @@ -1163,6 +1189,9 @@ extern void blk_queue_required_elevator_features(struct request_queue *q, extern bool blk_queue_can_use_dma_map_merging(struct request_queue *q, struct device *dev); +struct blk_cranges *blk_alloc_cranges(struct gendisk *disk, int nr_ranges); +void blk_queue_set_cranges(struct gendisk *disk, struct blk_cranges *cr); + /* * Number of physical segments as sent to the device. * From patchwork Wed Jul 21 10:42:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 12390709 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B4D64C07E9B for ; Wed, 21 Jul 2021 11:33:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9A530610D2 for ; Wed, 21 Jul 2021 11:33:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236460AbhGUKwR (ORCPT ); Wed, 21 Jul 2021 06:52:17 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:53613 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239000AbhGUKBn (ORCPT ); Wed, 21 Jul 2021 06:01:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1626864137; x=1658400137; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=eVdP8gEwYf4LJlTw6lqJ7/xD91dkYaBGnEouf+NGHy0=; b=Ridags+ICRLzVeBAmYoa2Nq2tn6fu9zhh2TSGHl5BbE9AlXmvg8gZJzM seyrLFwED+1htCH4j3+kKiRGBCYLSVuItP7syVO+aDA/3Kpm4z97Wafj1 bo+t+FKTx+jtpBsTw6Po95ZAocgl8oh958NwBp8hmxrMt37Fn0M8uK9RI MS1Yh/t46f4HGgbJr5IQylMuTtWGV/7ktFxsthNwphlLsoXJOnoD4BFx4 382FEN2NizZsQu15FNgzBlwu1Bed2qThVpTFfSSJnmm6u2zQ/NcyBvLiP Dbgnt4w7L+ujuHaef6sP1ymKOIht+xVm0+zdQt7lNeMQySq8YNHevpv6w g==; X-IronPort-AV: E=Sophos;i="5.84,257,1620662400"; d="scan'208";a="179944864" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 21 Jul 2021 18:42:10 +0800 IronPort-SDR: Wp9IfKAJV7RmcCqBb56iNgxHKjlbO64GLakLhmTZVA1VSnJ5Vhx4uGtpF/OiYFTcpv+YABKLlF 1W3Dbi8E3ZYS0FvRdhhdhF8TBMJansM6aOGqynJ3pDyfSas5PjhBQjQ7larWMFbRihPX7ycxmb tRTVU0BTyHlKYpX9azijUekAiceTRh6/VpFl3uG2aqbf0jMyjiud7obK89TMCrrhyUmhDxcTvR e009g2hMNpxaiRuiQB9PuSiKoCYEew/Ii9jDQJYEp/66CiNg8E8tGrrAExg7QZNPzRIV2TYz5+ nUujgpO5Z3q7Jp1++J+9jFFL Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2021 03:20:04 -0700 IronPort-SDR: bTMR8BTD0ma/ePjNUwX7cj+5dpncOyhvfCpEgFIFfzTsk8nP3OoG5ZS10kFmIz2Ty6X51XIusa GO64HUf7asGxV01BE4W6aeSaLSDpV2zo9atgdj+tVrIGxOoHVFvJr7pGPJsH10/yd1+8IufS/Q w0Wl9d7UYwZPPDZj65EOFmjWA4/JtKk1sjcYFEHYmaeauAkw/muXPb9G4EzEZIhbuYiZfAlGfQ JFE3Qyu7Pey83V12d+Bw0wICJxvLnytHQip6cUNOpb/hi9qWAxGRYabJ0GLwbJ3XVOxZEG5Hrq EcQ= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip02.wdc.com with ESMTP; 21 Jul 2021 03:42:10 -0700 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , linux-ide@vger.kernel.org Subject: [PATCH 2/4] scsi: sd: add concurrent positioning ranges support Date: Wed, 21 Jul 2021 19:42:03 +0900 Message-Id: <20210721104205.885115-3-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210721104205.885115-1-damien.lemoal@wdc.com> References: <20210721104205.885115-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Add the sd_read_cpr() function to the sd scsi disk driver to discover if a device has multiple concurrent positioning ranges (i.e. multiple actuators on an HDD). This new function is called from sd_revalidate_disk() and uses the block layer functions blk_alloc_cranges() and blk_queue_set_cranges() to set a device cranges according to the information retrieved from log page B9h, if the device supports it. The format of the Concurrent Positioning Ranges VPD page B9h is defined in section 6.6.6 of SBC-5. Signed-off-by: Damien Le Moal Reported-by: kernel test robot Reported-by: Dan Carpenter Reviewed-by: Hannes Reinecke --- drivers/scsi/sd.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/sd.h | 1 + 2 files changed, 81 insertions(+) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index b8d55af763f9..b1e767a01b9f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3125,6 +3125,85 @@ static void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer) sdkp->security = 1; } +static inline sector_t sd64_to_sectors(struct scsi_disk *sdkp, u8 *buf) +{ + return logical_to_sectors(sdkp->device, get_unaligned_be64(buf)); +} + +/** + * sd_read_cpr - Query concurrent positioning ranges + * @sdkp: disk to query + */ +static void sd_read_cpr(struct scsi_disk *sdkp) +{ + unsigned char *buffer, *desc; + struct blk_cranges *cr = NULL; + unsigned int nr_cpr = 0; + int i, vpd_len, buf_len = SD_BUF_SIZE; + + /* + * We need to have the capacity set first for the block layer to be + * able to check the ranges. + */ + if (sdkp->first_scan) + return; + + if (!sdkp->capacity) + goto out; + + /* + * Concurrent Positioning Ranges VPD: there can be at most 256 ranges, + * leading to a maximum page size of 64 + 256*32 bytes. + */ + buf_len = 64 + 256*32; + buffer = kmalloc(buf_len, GFP_KERNEL); + if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb9, buffer, buf_len)) + goto out; + + /* We must have at least a 64B header and one 32B range descriptor */ + vpd_len = get_unaligned_be16(&buffer[2]) + 3; + if (vpd_len > buf_len || vpd_len < 64 + 32 || (vpd_len & 31)) { + sd_printk(KERN_ERR, sdkp, + "Invalid Concurrent Positioning Ranges VPD page\n"); + goto out; + } + + nr_cpr = (vpd_len - 64) / 32; + if (nr_cpr == 1) { + nr_cpr = 0; + goto out; + } + + cr = blk_alloc_cranges(sdkp->disk, nr_cpr); + if (!cr) { + nr_cpr = 0; + goto out; + } + + desc = &buffer[64]; + for (i = 0; i < nr_cpr; i++, desc += 32) { + if (desc[0] != i) { + sd_printk(KERN_ERR, sdkp, + "Invalid Concurrent Positioning Range number\n"); + nr_cpr = 0; + break; + } + + cr->ranges[i].sector = sd64_to_sectors(sdkp, desc + 8); + cr->ranges[i].nr_sectors = sd64_to_sectors(sdkp, desc + 16); + } + +out: + blk_queue_set_cranges(sdkp->disk, cr); + if (nr_cpr && sdkp->nr_actuators != nr_cpr) { + sd_printk(KERN_NOTICE, sdkp, + "%u concurrent positioning ranges\n", nr_cpr); + sdkp->nr_actuators = nr_cpr; + } + + kfree(buffer); +} + /* * Determine the device's preferred I/O size for reads and writes * unless the reported value is unreasonably small, large, not a @@ -3240,6 +3319,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_app_tag_own(sdkp, buffer); sd_read_write_same(sdkp, buffer); sd_read_security(sdkp, buffer); + sd_read_cpr(sdkp); } /* diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index b59136c4125b..2e5932bde43d 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -106,6 +106,7 @@ struct scsi_disk { u8 protection_type;/* Data Integrity Field */ u8 provisioning_mode; u8 zeroing_mode; + u8 nr_actuators; /* Number of actuators */ unsigned ATO : 1; /* state of disk ATO bit */ unsigned cache_override : 1; /* temp override of WCE,RCD */ unsigned WCE : 1; /* state of disk WCE bit */ From patchwork Wed Jul 21 10:42:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 12390713 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A28E2C07E9B for ; Wed, 21 Jul 2021 11:33:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 81E486108B for ; Wed, 21 Jul 2021 11:33:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237451AbhGUKwc (ORCPT ); Wed, 21 Jul 2021 06:52:32 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:53609 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239023AbhGUKBw (ORCPT ); Wed, 21 Jul 2021 06:01:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1626864149; x=1658400149; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=dvwRLyQ/uyyN0Ac8uzZ5GsxrgGBHTzT8Or9L4J+FKvU=; b=cfdtP8/T6tsfjCEnUimddZGezdKouHcETlXMkB9nhLNc61zY7fi4XfdB Wkip/NCYHXGJHQVT0xPSO/Yj5EoVcKlUsTT6RXwj1PPWKwSsn7iUVAmvC qt5iWpkRnYoYOIEiMwavOxRYnoCEA5mL24OfN+3tWS9ASkumLDkFp+ZYY oElPGLE01IghjnfnU4oSXy8zjRFVvkWvZNGqWKf7wJycphm7esEHK4glm RbAokMyimQAO2sig2hpuYLD23/QxdnC+y9lIFWpX8u5sNBJounH61Mx2+ N95+8Ot31KOdLWXVPQBDQST/hS4cmtbxil1952mmrxIzoV1xs1xJEcHUv w==; X-IronPort-AV: E=Sophos;i="5.84,257,1620662400"; d="scan'208";a="179944868" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 21 Jul 2021 18:42:11 +0800 IronPort-SDR: ZuYwIJ6Mw4a/5C7TC9Q381P/NEnMrjV5/nRZuAlMrhZ0+jjwbNouMv8ESgvFcPNVRj9GTjCGcK VfI8ey9ERirVUeLR/hM9obv8xcQNdx//MEgyk09tY+ka6bu7uzsEDAbvrCQYxpsfmZTGt1E0hE sLROZtS4uG+BRgLEyayIHy11V8XnGUzPdkHIJp6+L9UfmhYg5nLwFx0k3Jiryls7g9qqzNKbkA FcIeBjbNUa0JAiUDljXn5QSDUk6S+dWAOrBQpvA9dAulHVzZPrIPYvOE8YIbXwjn4FHiulUUPU 2dFDLn2BFplAAMzt4iC0dnGQ Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2021 03:20:05 -0700 IronPort-SDR: ApW7V0ic12nGlCPn0gJz6PZ9yHNVNYJcvDDc1LLXYUzjt7JEVqKQexuUTKTjqreWk03tF8cm2V wQp1g8Q23BpIiGNvRFJnootyt3KZIv9aFwvMxGvuH7366hpDHsoPISnB1R7bkeKiuqP6qyYR7K 3r/wtY2wm9+F75sbyupLJk7dq3WPC4ttmGOhQqLpBRCcvbk+ItV/fXdhqn26B8Cs4hJY5qm1da x5pbGQnLy4cXQJlDlGEy4XbLANBaz5wHJF1x33JIA+XQoXAlioRvIyfN8Cm5zKqtq8M9YIxOtc aUA= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip02.wdc.com with ESMTP; 21 Jul 2021 03:42:12 -0700 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , linux-ide@vger.kernel.org Subject: [PATCH 3/4] libata: support concurrent positioning ranges log Date: Wed, 21 Jul 2021 19:42:04 +0900 Message-Id: <20210721104205.885115-4-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210721104205.885115-1-damien.lemoal@wdc.com> References: <20210721104205.885115-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Add support to discover if an ATA device supports the Concurrent Positioning Ranges Log (address 0x47), indicating that the device is capable of seeking to multiple different locations in parallel using multiple actuators serving different LBA ranges. Also add support to translate the concurrent positioning ranges log into its equivalent Concurrent Positioning Ranges VPD page B9h in libata-scsi.c. The format of the Concurrent Positioning Ranges Log is defined in ACS-5 r9. Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke --- drivers/ata/libata-core.c | 57 +++++++++++++++++++++++++++++++++++++++ drivers/ata/libata-scsi.c | 46 ++++++++++++++++++++++++------- include/linux/ata.h | 1 + include/linux/libata.h | 11 ++++++++ 4 files changed, 106 insertions(+), 9 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 61c762961ca8..863287c77ba2 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2363,6 +2363,62 @@ static void ata_dev_config_trusted(struct ata_device *dev) dev->flags |= ATA_DFLAG_TRUSTED; } +static void ata_dev_config_cpr(struct ata_device *dev) +{ + unsigned int err_mask; + size_t buf_len; + int i, nr_cpr = 0; + struct ata_cpr *cpr = NULL; + u8 *buf, *desc; + + dev->nr_cpr = 0; + kfree(dev->cpr); + dev->cpr = NULL; + + if (!ata_identify_page_supported(dev, + ATA_LOG_CONCURRENT_POSITIONING_RANGES)) + return; + + /* + * Read IDENTIFY DEVICE data log, page 0x47 + * (concurrent positioning ranges). We can have at most 255 32B range + * descriptors plus a 64B header. + */ + buf_len = (64 + 255 * 32 + 511) & ~511; + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return; + + err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, + ATA_LOG_CONCURRENT_POSITIONING_RANGES, + buf, buf_len >> 9); + if (err_mask) + goto free; + + nr_cpr = buf[0]; + if (!nr_cpr) + goto free; + + cpr = kcalloc(nr_cpr, sizeof(struct ata_cpr), GFP_KERNEL); + if (!cpr) { + nr_cpr = 0; + goto free; + } + + desc = &buf[64]; + for (i = 0; i < nr_cpr; i++, desc += 32) { + cpr[i].num = desc[0]; + cpr[i].num_storage_elements = desc[1]; + cpr[i].start_lba = get_unaligned_le64(&desc[8]); + cpr[i].num_lbas = get_unaligned_le64(&desc[16]); + } + +free: + kfree(buf); + dev->nr_cpr = nr_cpr; + dev->cpr = cpr; +} + /** * ata_dev_configure - Configure the specified ATA/ATAPI device * @dev: Target device to configure @@ -2591,6 +2647,7 @@ int ata_dev_configure(struct ata_device *dev) ata_dev_config_sense_reporting(dev); ata_dev_config_zac(dev); ata_dev_config_trusted(dev); + ata_dev_config_cpr(dev); dev->cdb_len = 32; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 144e8cac44ba..922f130b8382 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1937,7 +1937,7 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) */ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf) { - int num_pages; + int i, num_pages = 0; static const u8 pages[] = { 0x00, /* page 0x00, this page */ 0x80, /* page 0x80, unit serial no page */ @@ -1950,11 +1950,14 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf) 0xb9, /* page 0xb9, concurrent positioning ranges */ }; - num_pages = sizeof(pages); - if (!(args->dev->flags & ATA_DFLAG_ZAC)) - num_pages--; + for (i = 0; i < sizeof(pages); i++) { + if (pages[i] == 0xb6 && + !(args->dev->flags & ATA_DFLAG_ZAC)) + continue; + rbuf[num_pages + 4] = pages[i]; + num_pages++; + } rbuf[3] = num_pages; /* number of supported VPD pages */ - memcpy(rbuf + 4, pages, num_pages); return 0; } @@ -2164,6 +2167,25 @@ static unsigned int ata_scsiop_inq_b6(struct ata_scsi_args *args, u8 *rbuf) return 0; } +static unsigned int ata_scsiop_inq_b9(struct ata_scsi_args *args, u8 *rbuf) +{ + u8 *desc = &rbuf[64]; + int i; + + /* SCSI Concurrent Positioning Ranges VPD page: SBC-5 rev 1 or later */ + rbuf[1] = 0xb9; + put_unaligned_be16(64 + (int)args->dev->nr_cpr * 32 - 4, &rbuf[3]); + + for (i = 0; i < args->dev->nr_cpr; i++, desc += 32) { + desc[0] = args->dev->cpr[i].num; + desc[1] = args->dev->cpr[i].num_storage_elements; + put_unaligned_be64(args->dev->cpr[i].start_lba, &desc[8]); + put_unaligned_be64(args->dev->cpr[i].num_lbas, &desc[16]); + } + + return 0; +} + /** * modecpy - Prepare response for MODE SENSE * @dest: output buffer @@ -4163,11 +4185,17 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2); break; case 0xb6: - if (dev->flags & ATA_DFLAG_ZAC) { + if (dev->flags & ATA_DFLAG_ZAC) ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b6); - break; - } - fallthrough; + else + ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); + break; + case 0xb9: + if (dev->nr_cpr) + ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b9); + else + ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); + break; default: ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); break; diff --git a/include/linux/ata.h b/include/linux/ata.h index 1b44f40c7700..199e47e97d64 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -329,6 +329,7 @@ enum { ATA_LOG_SECURITY = 0x06, ATA_LOG_SATA_SETTINGS = 0x08, ATA_LOG_ZONED_INFORMATION = 0x09, + ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47, /* Identify device SATA settings log:*/ ATA_LOG_DEVSLP_OFFSET = 0x30, diff --git a/include/linux/libata.h b/include/linux/libata.h index 3fcd24236793..94b7e152e76e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -670,6 +670,13 @@ struct ata_ering { struct ata_ering_entry ring[ATA_ERING_SIZE]; }; +struct ata_cpr { + u8 num; + u8 num_storage_elements; + u64 start_lba; + u64 num_lbas; +}; + struct ata_device { struct ata_link *link; unsigned int devno; /* 0 or 1 */ @@ -729,6 +736,10 @@ struct ata_device { u32 zac_zones_optimal_nonseq; u32 zac_zones_max_open; + /* Concurrent positioning ranges */ + u8 nr_cpr; + struct ata_cpr *cpr; + /* error history */ int spdn_cnt; /* ering is CLEAR_END, read comment above CLEAR_END */ From patchwork Wed Jul 21 10:42:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 12390711 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D5B06C636C9 for ; Wed, 21 Jul 2021 11:33:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B494A6109F for ; Wed, 21 Jul 2021 11:33:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237849AbhGUKw1 (ORCPT ); Wed, 21 Jul 2021 06:52:27 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:53613 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239025AbhGUKBw (ORCPT ); Wed, 21 Jul 2021 06:01:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1626864149; x=1658400149; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=uQP3CdubqmQZPiPY+fgwiZR463GJzvIEuEEIrPo+s2w=; b=QkguLOSIv8ny4H0fkJupnHuLxYK0OJz6ZBh2ISsPzvNX3r7SNefujwHO AjVlscV60I5i8KtfqFU9mkDzviZ+xForFX+MvTGVlj7Z0snUZIFjXJYKr CHbp0Bx4xnTX53DKR/JSuAyEiZ0YRicUyWxnqW6P8oSGuzJXPolaqYmq6 zUTfVITpdDitV6/3g1k2HQbS5AslQg52ChFB71OMfRKm4rD7TDXXEIlRl S9kUJhrGkekMXouArG63PMFqXgvACgzgA8DS1Jee7Wc37A8DfV/WweDtj uwstJhORdGx0U0BSqWsZxT0SGKwZ0n7D7R9vn3on8SpCt6rFoxOI1mTyp w==; X-IronPort-AV: E=Sophos;i="5.84,257,1620662400"; d="scan'208";a="179944869" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 21 Jul 2021 18:42:12 +0800 IronPort-SDR: ifU48VsC0IdYkXmpAip16IthDt6A4DbqtHfS5Bg7PdmuXbyZo1iQtmC5EKInnuXRLS7gFiVb0a 6aQjc5daS5glPHKBRAj5n6onXuJKPZ2H568clgXmoIadTjJRDIaNvNFJgm6x2d3xaH3W2CclNw Ti6IkH7BpwT543tSyY5OD6tEBATiBkZznfu7B/J6cJ75DCdIIpNW4Eu33hYKPy3uBqWxhVMtMy /0Wx7+CEphFWUlob4u9sUfjEy+2wX94sYba8ORwLK81IzCPIntnlia9alwLFZ4yjICSbIQr8AE KKQRI2Ol1wHlBHzvu0C5kDhY Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2021 03:20:06 -0700 IronPort-SDR: 1qCu7lDYHJFdF9VhS+q0kcCqa1PAYXgZVJo6CTOseycZHPjelo8Vwonw87xigSbkmVQYD4HSyu +PknNeMWp7NwH3xcHxqEw+daQhp1vMgTdC4gxahx21WfT+9rovYLAZQ/wCn79BQg51HrpZRgo6 VkfroFBh6bkPX6eRf185V8WU8n4iHUG17LKUmKhS3uD+ltlkEAjUlYT6xZwp25vPFtODHjqRWq WUy0w6TZn7BbxXf0hLZ3fghuUzeSJRgagOlEAH6WAebOgKdTmFgTFRJSz2nLc7Md9wpOitWbWY faA= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip02.wdc.com with ESMTP; 21 Jul 2021 03:42:13 -0700 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , linux-ide@vger.kernel.org Subject: [PATCH 4/4] doc: document sysfs queue/cranges attributes Date: Wed, 21 Jul 2021 19:42:05 +0900 Message-Id: <20210721104205.885115-5-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210721104205.885115-1-damien.lemoal@wdc.com> References: <20210721104205.885115-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Update the file Documentation/block/queue-sysfs.rst to add a description of a device queue sysfs entries related to concurrent sector ranges (e.g. concurrent positioning ranges for multi-actuator hard-disks). While at it, also fix a typo in this file introduction paragraph. Signed-off-by: Damien Le Moal --- Documentation/block/queue-sysfs.rst | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/Documentation/block/queue-sysfs.rst b/Documentation/block/queue-sysfs.rst index 4dc7f0d499a8..ffbea0c7a576 100644 --- a/Documentation/block/queue-sysfs.rst +++ b/Documentation/block/queue-sysfs.rst @@ -4,7 +4,7 @@ Queue sysfs files This text file will detail the queue files that are located in the sysfs tree for each block device. Note that stacked devices typically do not export -any settings, since their queue merely functions are a remapping target. +any settings, since their queue merely functions as a remapping target. These files are the ones found in the /sys/block/xxx/queue/ directory. Files denoted with a RO postfix are readonly and the RW postfix means @@ -286,4 +286,29 @@ sequential zones of zoned block devices (devices with a zoned attributed that reports "host-managed" or "host-aware"). This value is always 0 for regular block devices. +cranges (RO) +------------ + +The presence of this sub-directory of the /sys/block/xxx/queue/ directory +indicates that the device is capable of executing requests targeting +different sector ranges in parallel. For instance, single LUN multi-actuator +hard-disks will likely have a cranges directory if the device correctly +advertizes the sector ranges of its actuators. + +The cranges directory contains one directory per sector range, with each +range described using the sector (RO) attribute file to indicate the first +sector of the range and the nr_sectors (RO) attribute file to indicate the +total number of sector in the range starting from the first sector. +For example, a dual-actuator hard disk will have the following cranges +entries.:: + + $ tree /sys/block//queue/cranges/ + /sys/block//queue/cranges/ + |-- 0 + | |-- nr_sectors + | `-- sector + `-- 1 + |-- nr_sectors + `-- sector + Jens Axboe , February 2009