From patchwork Mon Nov 11 02:39:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 11236463 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DE4E617E6 for ; Mon, 11 Nov 2019 02:39:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BD1CC206C3 for ; Mon, 11 Nov 2019 02:39:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="P3GpTILI" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726811AbfKKCjf (ORCPT ); Sun, 10 Nov 2019 21:39:35 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52028 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726770AbfKKCje (ORCPT ); Sun, 10 Nov 2019 21:39:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1573439975; x=1604975975; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=FdDMBM8oW2SBfdkbPDmth/Mj8PXjLYk7YajwPtVTjXo=; b=P3GpTILIpPb7JVtwqYsfca/xvLIbTMJB/J6oIiBHvoxqE43kPzTferKY G+RMtJCpa4L4Am83cO5j1+6wTcny71D8nnmTdg1+jcBlAUOH+rwES9O9Y OpB/9B+09NvRGFzImLaREpQ9nw/6Xz9cjpMw7OJHOB6NdeLF77P91G7f9 JO6ciaaiWfZcvHLoijjhFc5L2ZXAQcTR1kbReOY+fpSfc9QlTOgasVPfG TlAzSSQkyK2TdrCwTS/um7UO+xaBp4B9bIdnghFNAKjq71DVY8B7f5JPy HeNip4w3/ie2BnNmwYHHdeJULbdUCxLwybSorSB5hx9SOBZXrDWbd3O41 w==; IronPort-SDR: mqtF/u73RMx8s/kGkQPbfu5+fMLpFBY6jxw7/WJ/yZtVCZfKyNxaCjOVWlisTh3EbWVnLvZdP9 Hic/ddv/WCjbANJD1bb4VpJ11ficGyvfEJAwlscvQZ/a2uqHYIkoq9y/oLQg3HonJni6H5HkNf GG49h/+8e98oqzEi6RwfNIxtDlp/E8+1MqGscs/IpUUR+SQJr4SsQ89Mu3FMzWYZEQRkypH3bO yY3+zoJz7xUDntfxOlET0bsRHOr9hKGj9d+E1LPKSaTW/pUg5f8Qv7YOiR7ice+16NBDo5957g 894= X-IronPort-AV: E=Sophos;i="5.68,291,1569254400"; d="scan'208";a="127062960" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 11 Nov 2019 10:39:34 +0800 IronPort-SDR: cFvGGPMmo/wcei5u8RsGjy1RlCCexK02zSkGldsdAxvG3bzk/PGNcTz9hrVx6r3L4vbYJH4gcZ BnWhA6qvpCvEJjNoWx36BVar472SPCiVOG/yWMREwlZi5j/CpDjGtjTAdJLx4feF0ZVwyeSPiW uVlrvLvqSnZTDHVXlUrWESL/rVIT3JCydpdpSfa4rwp/Fd4WwrHG43vzaGje4LSwDnmz0UvVrE lzNbzkH73eTeWoE3fz+dDeBS9MDa8CdLBAnVLJt+hrla7ZbIDyT6OHrUrUWljkV5NRlqn0XgRC tsxIe6GfBfs25xrnepxNA/7Q Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Nov 2019 18:34:39 -0800 IronPort-SDR: 4oxQANO3Le6zwGzSh84WyY/rR6HLvilbmxQhOVSuP4qz734lp+9TQlCDsh2oXnApWZuFEYGinl xIbAznCo/WIgVk0WVuLYnczVGMa0iIt+2ucgguDebEO5GaRSSVw+7yUHCC0MR/N7Pv5LBknbKY 8hDnJaTQgc0y0tK0Dk8bg8RNdNmhFjp2mARQ0sXmp32jMzh3qiY3zMxOqmU+d8P7fnY45nDRVG k5oX+zOEY/IrPFo93bYDDT3zTJ3Q0f2d41WyR/BA2m17hxK8GTVWx68OLqKIWNQGOZ+0+6wePk 56s= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 10 Nov 2019 18:39:34 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , dm-devel@redhat.com, Mike Snitzer , linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim , Chao Yu Subject: [PATCH v2 1/9] block: Enhance blk_revalidate_disk_zones() Date: Mon, 11 Nov 2019 11:39:22 +0900 Message-Id: <20191111023930.638129-2-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111023930.638129-1-damien.lemoal@wdc.com> References: <20191111023930.638129-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org For ZBC and ZAC zoned devices, the scsi driver revalidation processing implemented by sd_revalidate_disk() includes a call to sd_zbc_read_zones() which executes a full disk zone report used to check that all zones of the disk are the same size. This processing is followed by a call to blk_revalidate_disk_zones(), used to initialize the device request queue zone bitmaps (zone type and zone write lock bitmaps). To do so, blk_revalidate_disk_zones() also executes a full device zone report to obtain zone types. As a result, the entire zoned block device revalidation process includes two full device zone report. By moving the zone size checks into blk_revalidate_disk_zones(), this process can be optimized to a single full device zone report, leading to shorter device scan and revalidation times. This patch implements this optimization, reducing the original full device zone report implemented in sd_zbc_check_zones() to a single, small, report zones command execution to obtain the size of the first zone of the device. Checks whether all zones of the device are the same size as the first zone size are moved to the generic blk_check_zone() function called from blk_revalidate_disk_zones(). This optimization also has the following benefits: 1) fewer memory allocations in the scsi layer during disk revalidation as the potentailly large buffer for zone report execution is not needed. 2) Implement zone checks in a generic manner, reducing the burden on device driver which only need to obtain the zone size and check that this size is a power of 2 number of LBAs. Any new type of zoned block device will benefit from this. Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- block/blk-zoned.c | 62 +++++++++++++++++++++++- drivers/scsi/sd_zbc.c | 107 ++++++++---------------------------------- 2 files changed, 80 insertions(+), 89 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index 481eaf7d04d4..dae787f67019 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -448,6 +448,58 @@ void blk_queue_free_zone_bitmaps(struct request_queue *q) q->seq_zones_wlock = NULL; } +/* + * Helper function to check the validity of zones of a zoned block device. + */ +static bool blk_zone_valid(struct gendisk *disk, struct blk_zone *zone, + sector_t *sector) +{ + struct request_queue *q = disk->queue; + sector_t zone_sectors = blk_queue_zone_sectors(q); + sector_t capacity = get_capacity(disk); + + /* + * All zones must have the same size, with the exception on an eventual + * smaller last zone. + */ + if (zone->start + zone_sectors < capacity && + zone->len != zone_sectors) { + pr_warn("%s: Invalid zoned device with non constant zone size\n", + disk->disk_name); + return false; + } + + if (zone->start + zone->len >= capacity && + zone->len > zone_sectors) { + pr_warn("%s: Invalid zoned device with larger last zone size\n", + disk->disk_name); + return false; + } + + /* Check for holes in the zone report */ + if (zone->start != *sector) { + pr_warn("%s: Zone gap at sectors %llu..%llu\n", + disk->disk_name, *sector, zone->start); + return false; + } + + /* Check zone type */ + switch (zone->type) { + case BLK_ZONE_TYPE_CONVENTIONAL: + case BLK_ZONE_TYPE_SEQWRITE_REQ: + case BLK_ZONE_TYPE_SEQWRITE_PREF: + break; + default: + pr_warn("%s: Invalid zone type 0x%x at sectors %llu\n", + disk->disk_name, (int)zone->type, zone->start); + return false; + } + + *sector += zone->len; + + return true; +} + /** * blk_revalidate_disk_zones - (re)allocate and initialize zone bitmaps * @disk: Target disk @@ -497,7 +549,10 @@ int blk_revalidate_disk_zones(struct gendisk *disk) if (!seq_zones_bitmap) goto out; - /* Get zone information and initialize seq_zones_bitmap */ + /* + * Get zone information to check the zones and initialize + * seq_zones_bitmap. + */ rep_nr_zones = nr_zones; zones = blk_alloc_zones(&rep_nr_zones); if (!zones) @@ -511,11 +566,14 @@ int blk_revalidate_disk_zones(struct gendisk *disk) if (!nrz) break; for (i = 0; i < nrz; i++) { + if (!blk_zone_valid(disk, &zones[i], §or)) { + ret = -ENODEV; + goto out; + } if (zones[i].type != BLK_ZONE_TYPE_CONVENTIONAL) set_bit(z, seq_zones_bitmap); z++; } - sector += nrz * blk_queue_zone_sectors(q); } if (WARN_ON(z != nr_zones)) { diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 39f10ec0dfcf..7c4690f26698 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -339,32 +339,19 @@ static int sd_zbc_check_zoned_characteristics(struct scsi_disk *sdkp, * Returns the zone size in number of blocks upon success or an error code * upon failure. */ -static int sd_zbc_check_zones(struct scsi_disk *sdkp, u32 *zblocks) +static int sd_zbc_check_zones(struct scsi_disk *sdkp, unsigned char *buf, + u32 *zblocks) { - size_t bufsize, buflen; - unsigned int noio_flag; + size_t buflen; u64 zone_blocks = 0; - sector_t max_lba, block = 0; - unsigned char *buf; + sector_t max_lba; unsigned char *rec; int ret; - u8 same; - - /* Do all memory allocations as if GFP_NOIO was specified */ - noio_flag = memalloc_noio_save(); - /* Get a buffer */ - buf = sd_zbc_alloc_report_buffer(sdkp, SD_ZBC_REPORT_MAX_ZONES, - &bufsize); - if (!buf) { - ret = -ENOMEM; - goto out; - } - - /* Do a report zone to get max_lba and the same field */ - ret = sd_zbc_do_report_zones(sdkp, buf, bufsize, 0, false); + /* Do a report zone to get max_lba and the size of the first zone */ + ret = sd_zbc_do_report_zones(sdkp, buf, SD_BUF_SIZE, 0, false); if (ret) - goto out_free; + return ret; if (sdkp->rc_basis == 0) { /* The max_lba field is the capacity of this device */ @@ -379,82 +366,28 @@ static int sd_zbc_check_zones(struct scsi_disk *sdkp, u32 *zblocks) } } - /* - * Check same field: for any value other than 0, we know that all zones - * have the same size. - */ - same = buf[4] & 0x0f; - if (same > 0) { - rec = &buf[64]; - zone_blocks = get_unaligned_be64(&rec[8]); - goto out; - } - - /* - * Check the size of all zones: all zones must be of - * equal size, except the last zone which can be smaller - * than other zones. - */ - do { - - /* Parse REPORT ZONES header */ - buflen = min_t(size_t, get_unaligned_be32(&buf[0]) + 64, - bufsize); - rec = buf + 64; - - /* Parse zone descriptors */ - while (rec < buf + buflen) { - u64 this_zone_blocks = get_unaligned_be64(&rec[8]); - - if (zone_blocks == 0) { - zone_blocks = this_zone_blocks; - } else if (this_zone_blocks != zone_blocks && - (block + this_zone_blocks < sdkp->capacity - || this_zone_blocks > zone_blocks)) { - zone_blocks = 0; - goto out; - } - block += this_zone_blocks; - rec += 64; - } - - if (block < sdkp->capacity) { - ret = sd_zbc_do_report_zones(sdkp, buf, bufsize, block, - true); - if (ret) - goto out_free; - } - - } while (block < sdkp->capacity); - -out: - if (!zone_blocks) { - if (sdkp->first_scan) - sd_printk(KERN_NOTICE, sdkp, - "Devices with non constant zone " - "size are not supported\n"); - ret = -ENODEV; - } else if (!is_power_of_2(zone_blocks)) { + /* Parse REPORT ZONES header */ + buflen = min_t(size_t, get_unaligned_be32(&buf[0]) + 64, SD_BUF_SIZE); + rec = buf + 64; + zone_blocks = get_unaligned_be64(&rec[8]); + if (!zone_blocks || !is_power_of_2(zone_blocks)) { if (sdkp->first_scan) sd_printk(KERN_NOTICE, sdkp, "Devices with non power of 2 zone " "size are not supported\n"); - ret = -ENODEV; - } else if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) { + return -ENODEV; + } + + if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) { if (sdkp->first_scan) sd_printk(KERN_NOTICE, sdkp, "Zone size too large\n"); - ret = -EFBIG; - } else { - *zblocks = zone_blocks; - ret = 0; + return -EFBIG; } -out_free: - memalloc_noio_restore(noio_flag); - kvfree(buf); + *zblocks = zone_blocks; - return ret; + return 0; } int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf) @@ -480,7 +413,7 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf) * Check zone size: only devices with a constant zone size (except * an eventual last runt zone) that is a power of 2 are supported. */ - ret = sd_zbc_check_zones(sdkp, &zone_blocks); + ret = sd_zbc_check_zones(sdkp, buf, &zone_blocks); if (ret != 0) goto err; From patchwork Mon Nov 11 02:39:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 11236467 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4983E17E6 for ; Mon, 11 Nov 2019 02:39:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 289DA2075B for ; Mon, 11 Nov 2019 02:39:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="ZaLgeFYs" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726834AbfKKCjg (ORCPT ); Sun, 10 Nov 2019 21:39:36 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52028 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726770AbfKKCjg (ORCPT ); Sun, 10 Nov 2019 21:39:36 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1573439976; x=1604975976; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=pRKa9RYPbmYIjqNqnNPy9xId0wvUi5EB+wPZWDfjvWA=; b=ZaLgeFYsegTa3PNE23HNzERN0Fh7VRnF9gUblFWdJ7BZLUowtN0Xs/t6 OudC/6umSIovlj/2XPPgMcUJ7b6/ulWpg+Z6TE9SOWSt+I3c9rgMoFo9B 1O6J1bKPGqHatSxxy6bgdnb/k5pe2/rxehmuVWuJDr6dVLVUE+QEQ3IJI 2/duxAnyjHlHOfbyaRC0uMeTWUg2xykT39cWAKto+6iSpRP2dhyk7Epy+ PZu4k4UMyLInrIY8Vi4vV1dWP7eBFGaZck6gFHh8fx2FUw7d1LCtNY6rX OyMEMQKYNpxQ5hKsi1lUZG+Syf69rG/U+oQ2l7/pJ6DlxHg2KpprpsSZM g==; IronPort-SDR: Q4kFFmNWDiECznUrbkp9m2zelk8rZyVCEzZxVdLIEI0UFvhzk7ahDpGvwkl22wyqAFlkeRy73k D330yM1sCKzKr6o7QU5YrHOBvgrGguDVJ7giXbeqZcsEjGsuxgRMY081dYA2hs/B/QZdfvnuMZ SD2pYIdlksJs1vFIqTMH8ZQ0Wvwng1ciQ0xBWWhsLb9bS13oON1ZeSeQ7E+QRQFW4dqBUQ+eJ4 HSDDZ1B5Qm0a6sFc1aoW2AYes8n19rtXyjUTGBjn646m56pfkG2RsB3qsSTGDs54Tq4Sv8hbDa ZBg= X-IronPort-AV: E=Sophos;i="5.68,291,1569254400"; d="scan'208";a="127062963" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 11 Nov 2019 10:39:36 +0800 IronPort-SDR: iy1E/f2SeRHSl2NR4k/Xew+QBmls//EErBJ4RtneW7W0Qo2ZsxDmh5bwFJ2qirBAH3kJzTiXUw nQVOdjrPi1epwFVzoWL8IZZa8q6V+5SMwfeBOfQ9o8D1M0ilqzsFqCHrV3nCPyyBQ7IOcnotiA zT2JAGcyxhZsJk1SJgAn23U4XAKVLbPSmPzCazjPsuRj3l2hi0qhl/u/3dyMthEOBr0hs63IOl vKrbTLhYa3E+j7ezuGFw4lrmINFc2gi6ovbOd0QblPTsglJCc5dnRawoBv85Dwp0kJyAO1pWlZ HfE/fhj/eXtaHfBi5K0Cv4Fs Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Nov 2019 18:34:40 -0800 IronPort-SDR: 7KNGaRYyEF8x+/ZjhGLu+4u7TY3OdEre8o8K8/TSWKs251Hma92sBpZPSA97z7BpbhbhrdKCih 20juh7bT6ZoQyJrVgJHjWUPUUiQtcwoWZTZ5S4umULlxJ66POPAasvaVIFu28RLa8V7fo4US+n i3LfYjAeNMB3hSVfcBGoSOkKyvNlOCxOBxEBguMsrNWpPHVw8tD6fqnn5xtN11LUgxpGeSHVoc H70zVCimk3duIOd4rIT2UQ3ODoLxwdogWfGpLa3Y4iWYeM+bD4sfoVMS+mr5D5N4UCAcDW9sOF VNQ= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 10 Nov 2019 18:39:35 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , dm-devel@redhat.com, Mike Snitzer , linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim , Chao Yu Subject: [PATCH v2 2/9] block: cleanup the !zoned case in blk_revalidate_disk_zones Date: Mon, 11 Nov 2019 11:39:23 +0900 Message-Id: <20191111023930.638129-3-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111023930.638129-1-damien.lemoal@wdc.com> References: <20191111023930.638129-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Christoph Hellwig blk_revalidate_disk_zones is never called for non-zoned devices. Just return early and warn instead of trying to handle this case. Signed-off-by: Christoph Hellwig Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke Reviewed-by: Chaitanya Kulkarni --- block/blk-zoned.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index dae787f67019..523a28d7a15c 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -520,6 +520,9 @@ int blk_revalidate_disk_zones(struct gendisk *disk) sector_t sector = 0; int ret = 0; + if (WARN_ON_ONCE(!blk_queue_is_zoned(q))) + return -EIO; + /* * BIO based queues do not use a scheduler so only q->nr_zones * needs to be updated so that the sysfs exposed value is correct. @@ -535,10 +538,8 @@ int blk_revalidate_disk_zones(struct gendisk *disk) */ noio_flag = memalloc_noio_save(); - if (!blk_queue_is_zoned(q) || !nr_zones) { - nr_zones = 0; + if (!nr_zones) goto update; - } /* Allocate bitmaps */ ret = -ENOMEM; From patchwork Mon Nov 11 02:39:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 11236471 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3B2C617E6 for ; Mon, 11 Nov 2019 02:39:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 191C6206C3 for ; Mon, 11 Nov 2019 02:39:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="dJQfEhdH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726847AbfKKCji (ORCPT ); Sun, 10 Nov 2019 21:39:38 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52028 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726770AbfKKCji (ORCPT ); Sun, 10 Nov 2019 21:39:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1573439978; x=1604975978; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=QRNHYLozP3GBLyGc1aFL68IZ/69XtP6zwGS2IDkAHaY=; b=dJQfEhdHOq/y5/aYuP0jIFQIDfvi3elNjNTEk5DyJBp43ptXnAjzL6ji qznCoxmGUdg8pc9qZ5T/l9FU84zcgs3nmLEqOtD+IKUjRCIL6POhOFvWU orXoHbD2WMg3kl7R6J+6/GYtDQ1r56oyL799hIHX+jI4051zRcDOb/Uud PY8CVb7XFh1cPYlhdhGgG+/xgLMylevfnSEkpHfaAdU3k0Q/hJZ9FYJ7r IAdjRbTyiJc3zJVUmv25jzJWTJBy1kAj4szG2xa4XuIAunXtNJWryYT9S UoI7hZ+JgkkOYphKY42IiHwe9yXqS/xcuYWA/vTjCwrkzjShZy+///xKG A==; IronPort-SDR: DBklDDLOkUcFRgJZlxSJoEj1M3fM71k1kQ8l6gQ0Ei8kV9irBljfumGMZTuMlR/+eMG6hcN10u V6KOH3qOic0cwtTDjmldyVeg3m0PVnlm3xQVevw29ywU0Hj7ofcA58Ls/ZmJLg/DisUCSUdgh+ 1PDmq7ow2yHasJ3k9MJzLUY0Xcghhvs6GQ1quzO/iKSkIO+0HN/y6SkYc0EeWftRzswduoqT9S Hsfajh9fZK4+S/YR53h3RXyN9x+IL9FbNty7IZ2EG/q33oRiHzN4UW3Hy3TmuH4FOHdSXmYYsz GpM= X-IronPort-AV: E=Sophos;i="5.68,291,1569254400"; d="scan'208";a="127062969" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 11 Nov 2019 10:39:38 +0800 IronPort-SDR: BVGV3M1Cved4n3R2g5F0upfTSEN+g8XrL8L4PwKwx+CGYjliVzH3BvnC4IreUXaJMyLmShszou 6NnY2yqAtoAiwET3k9AsIppva2Xqm/+Z9mDUZAmB/1lr227xRqaOwS+Av5qFkGRZ1oiLMrefnx +jTpwTd2Tc+k8VKj6iZq4ChB3ZmtV6+j3KsLhACphp0Cawz1UUeKx2FqfA7DzaF6Z1pGivrIyG +eOqw7rPk4RMjOwcpeICy8BfeB+d4B007KIuOnOEiQRPRf1qjDJ8adajApfki6XVx4HTN/b1dq haLsEenxaUjzl7xLQEVNXxC/ Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Nov 2019 18:34:42 -0800 IronPort-SDR: B7knMz2tWWR9ca5USo3tzOeizXPdpEdpYWZVz/33KQ3Z8OzM5F5QnkhkDX7m62qSoCaUftzU4U Ic50Gu4JEc65YJv4JYwZ1lCiiz1pqlSQ0sKjQmt5ikknSprgnHkfp9D94Xt2SSx26F7aoun6WP CMTTDptq7Fg6197WwXyztPcBBjm9g2USjNPoxAmAi6qrZYvZ4in8tT5OdbsDUQ7lTGSMXdmTxg a73cB4IB07UsLASMGju6BzMJEHA5aRzX3qgEfvR2Sm6aBqIzMJz8OIyO/iLbqp0pdj10DTVD1c uhg= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 10 Nov 2019 18:39:37 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , dm-devel@redhat.com, Mike Snitzer , linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim , Chao Yu Subject: [PATCH v2 3/9] block: Simplify report zones execution Date: Mon, 11 Nov 2019 11:39:24 +0900 Message-Id: <20191111023930.638129-4-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111023930.638129-1-damien.lemoal@wdc.com> References: <20191111023930.638129-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org All kernel users of blkdev_report_zones() as well as applications use through ioctl(BLKZONEREPORT) expect to potentially get less zone descriptors than requested. As such, the use of the internal report zones command execution loop implemented by blk_report_zones() is not necessary and can even be harmful to performance by causing the execution of inefficient small zones report command to service the reminder of a requested zone array. This patch removes blk_report_zones(), simplifying the code. Also remove a now incorrect comment in dm_blk_report_zones(). Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig Reviewed-by: Javier Gonzalez Reviewed-by: Hannes Reinecke --- block/blk-zoned.c | 34 +++++----------------------------- drivers/md/dm.c | 6 ------ 2 files changed, 5 insertions(+), 35 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index 523a28d7a15c..ea4e086ba00e 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -119,31 +119,6 @@ static bool blkdev_report_zone(struct block_device *bdev, struct blk_zone *rep) return true; } -static int blk_report_zones(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones) -{ - struct request_queue *q = disk->queue; - unsigned int z = 0, n, nrz = *nr_zones; - sector_t capacity = get_capacity(disk); - int ret; - - while (z < nrz && sector < capacity) { - n = nrz - z; - ret = disk->fops->report_zones(disk, sector, &zones[z], &n); - if (ret) - return ret; - if (!n) - break; - sector += blk_queue_zone_sectors(q) * n; - z += n; - } - - WARN_ON(z > *nr_zones); - *nr_zones = z; - - return 0; -} - /** * blkdev_report_zones - Get zones information * @bdev: Target block device @@ -164,6 +139,7 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector, struct blk_zone *zones, unsigned int *nr_zones) { struct request_queue *q = bdev_get_queue(bdev); + struct gendisk *disk = bdev->bd_disk; unsigned int i, nrz; int ret; @@ -175,7 +151,7 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector, * report_zones method. If it does not have one defined, the device * driver has a bug. So warn about that. */ - if (WARN_ON_ONCE(!bdev->bd_disk->fops->report_zones)) + if (WARN_ON_ONCE(!disk->fops->report_zones)) return -EOPNOTSUPP; if (!*nr_zones || sector >= bdev->bd_part->nr_sects) { @@ -185,8 +161,8 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector, nrz = min(*nr_zones, __blkdev_nr_zones(q, bdev->bd_part->nr_sects - sector)); - ret = blk_report_zones(bdev->bd_disk, get_start_sect(bdev) + sector, - zones, &nrz); + ret = disk->fops->report_zones(disk, get_start_sect(bdev) + sector, + zones, &nrz); if (ret) return ret; @@ -561,7 +537,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk) while (z < nr_zones) { nrz = min(nr_zones - z, rep_nr_zones); - ret = blk_report_zones(disk, sector, zones, &nrz); + ret = disk->fops->report_zones(disk, sector, zones, &nrz); if (ret) goto out; if (!nrz) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index bc143c1b2333..89189c29438f 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -473,12 +473,6 @@ static int dm_blk_report_zones(struct gendisk *disk, sector_t sector, goto out; } - /* - * blkdev_report_zones() will loop and call this again to cover all the - * zones of the target, eventually moving on to the next target. - * So there is no need to loop here trying to fill the entire array - * of zones. - */ ret = tgt->type->report_zones(tgt, sector, zones, nr_zones); out: From patchwork Mon Nov 11 02:39:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 11236475 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2CBDD17E6 for ; Mon, 11 Nov 2019 02:39:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0B2FA2067B for ; Mon, 11 Nov 2019 02:39:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="lM/D7aRD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726902AbfKKCjk (ORCPT ); Sun, 10 Nov 2019 21:39:40 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52028 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726853AbfKKCjk (ORCPT ); Sun, 10 Nov 2019 21:39:40 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1573439980; x=1604975980; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=utVEkPZAchArYh5SgdJN1MSWMEStdCpU26QNS2ZuWjM=; b=lM/D7aRDkb2Gf48aBjcrOhVaEigypsmE/lL8qwOJ0Ba6i/QUduqJXKAQ 6zYRD/kbllZkcot3IuohHKA3U4q64gn3Yx4nbBbh7yCnXh66OY8Lo31gN 3rqxSVq7UGa7eyH7m2qEEj0EzwWfKHMMpHXJ3kw/hhphYJd707Fr2w6rh exU/v/OqbkOisgMHcz6FrvZIU9F48g57A1FWhZW1VFDgv+9tiwe78vVBx NxlMbJyP1lvOZ55Ahxls/icXkVoS9hk2XFs00pdEkxnA3BUHRHWczR/Pz GpLibPpAQ11tQGxwtJnj4sd6uHfJ5+H7WWcshNPvCdb7WFchSuGwV+qzb A==; IronPort-SDR: u16xRvzWAvaofsT3A0JN0Q6lnAkUTE2037c3vH/W5gCFc6hqR0IKGB+3WmoJMAvaNr9iTw0ZjR om6bbg9rz4qovfFw2nb2Pwr5ioNa18BH+tSULm6kw8L2i/togrT3Cf7YHUovgdEviO43aghYR5 34vqwf8T2i1FHNiNPS2ld75S79wiNj6lJxA5uuH/4CceXqnaMFoMBwZvD6ni6SvnBesj0Oh262 k0pT1PXnBiSEOIckUkplIt8Ahz0Sh+HJ21i55rzj5f3W3186VmNeXwTg0bsrdFFbT/EdQyimMT QaU= X-IronPort-AV: E=Sophos;i="5.68,291,1569254400"; d="scan'208";a="127062970" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 11 Nov 2019 10:39:39 +0800 IronPort-SDR: ljLiyE6q5riFRHjRTHK2rVI0KLW6ST5WnGlIxmtPkLCkBKuIeqKQBVsVji3KUqnY7DU1s1BWhV qZfyraWy2BHfVl6ty4S7FWwDEcNFcxO1kS7w8pSynkDN78WZ5z6vwuo1lw7F/eq0K9n374gBq1 xtMoTIkPr1NADFxTyvSSE0d1ekEJaWSSyKkRbhUQUemyKwjxZHcQnrZBStpIOD1dblQhBir7p+ HAyJcFH6jnIifxIkc3X9RiWb169CGoyuDpmLbQXwssC7sXVBxmb1lb2PH3QFJLE39FHsDrouGy 8jd4bSlewa14KcX8CJ0Q1/qj Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Nov 2019 18:34:44 -0800 IronPort-SDR: pgSL4c208LsPbdHz9kRxJ+gjIMzeJC3XDYb0C7Na268ScNYQssVyNtAUsehnv07gO8dERFDYUj kFnXniFyP/q4BbmiSvMJ6xJLdFIip3NYYfFTOHCfJy2/iwhcXwKsD6CQ4XuFTqcMmhEZNxvltn 2QC6rznjs1+XBx1QmAursOrsOchyCUvTzkLG4NiBIfKfdL/d5o1MI/IWjDXe74NsQTGgSNpDyX EyxE7Y5kbjwFIIkDVc7HCLcIvuTlhDP/P78YtSJeA0+u8FgeXyKza/XU+9aoOVpwuF3X4FBU1Z uPA= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 10 Nov 2019 18:39:39 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , dm-devel@redhat.com, Mike Snitzer , linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim , Chao Yu Subject: [PATCH v2 4/9] block: Remove partition support for zoned block devices Date: Mon, 11 Nov 2019 11:39:25 +0900 Message-Id: <20191111023930.638129-5-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111023930.638129-1-damien.lemoal@wdc.com> References: <20191111023930.638129-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org No known partitioning tool supports zoned block devices, especially the host managed flavor with strong sequential write constraints. Furthermore, there are also no known user nor use cases for partitioned zoned block devices. This patch removes partition device creation for zoned block devices, which allows simplifying the processing of zone commands for zoned block devices. A warning is added if a partition table is found on the device. For report zones operations no zone sector information remapping is necessary anymore, simplifying the code. Of note is that remapping of zone reports for DM targets is still necessary as done by dm_remap_zone_report(). Similarly, remaping of a zone reset bio is not necessary anymore. Testing for the applicability of the zone reset all request also becomes simpler and only needs to check that the number of sectors of the requested zone range is equal to the disk capacity. Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- block/blk-core.c | 6 +--- block/blk-zoned.c | 62 ++++++-------------------------- block/partition-generic.c | 74 +++++---------------------------------- drivers/md/dm.c | 3 -- 4 files changed, 21 insertions(+), 124 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 3306a3c5bed6..df6b70476187 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -851,11 +851,7 @@ static inline int blk_partition_remap(struct bio *bio) if (unlikely(bio_check_ro(bio, p))) goto out; - /* - * Zone management bios do not have a sector count but they do have - * a start sector filled out and need to be remapped. - */ - if (bio_sectors(bio) || op_is_zone_mgmt(bio_op(bio))) { + if (bio_sectors(bio)) { if (bio_check_eod(bio, part_nr_sects_read(p))) goto out; bio->bi_iter.bi_sector += p->start_sect; diff --git a/block/blk-zoned.c b/block/blk-zoned.c index ea4e086ba00e..ae665e490858 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -93,32 +93,10 @@ unsigned int blkdev_nr_zones(struct block_device *bdev) if (!blk_queue_is_zoned(q)) return 0; - return __blkdev_nr_zones(q, bdev->bd_part->nr_sects); + return __blkdev_nr_zones(q, get_capacity(bdev->bd_disk)); } EXPORT_SYMBOL_GPL(blkdev_nr_zones); -/* - * Check that a zone report belongs to this partition, and if yes, fix its start - * sector and write pointer and return true. Return false otherwise. - */ -static bool blkdev_report_zone(struct block_device *bdev, struct blk_zone *rep) -{ - sector_t offset = get_start_sect(bdev); - - if (rep->start < offset) - return false; - - rep->start -= offset; - if (rep->start + rep->len > bdev->bd_part->nr_sects) - return false; - - if (rep->type == BLK_ZONE_TYPE_CONVENTIONAL) - rep->wp = rep->start + rep->len; - else - rep->wp -= offset; - return true; -} - /** * blkdev_report_zones - Get zones information * @bdev: Target block device @@ -140,8 +118,7 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector, { struct request_queue *q = bdev_get_queue(bdev); struct gendisk *disk = bdev->bd_disk; - unsigned int i, nrz; - int ret; + sector_t capacity = get_capacity(disk); if (!blk_queue_is_zoned(q)) return -EOPNOTSUPP; @@ -154,27 +131,14 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector, if (WARN_ON_ONCE(!disk->fops->report_zones)) return -EOPNOTSUPP; - if (!*nr_zones || sector >= bdev->bd_part->nr_sects) { + if (!*nr_zones || sector >= capacity) { *nr_zones = 0; return 0; } - nrz = min(*nr_zones, - __blkdev_nr_zones(q, bdev->bd_part->nr_sects - sector)); - ret = disk->fops->report_zones(disk, get_start_sect(bdev) + sector, - zones, &nrz); - if (ret) - return ret; + *nr_zones = min(*nr_zones, __blkdev_nr_zones(q, capacity - sector)); - for (i = 0; i < nrz; i++) { - if (!blkdev_report_zone(bdev, zones)) - break; - zones++; - } - - *nr_zones = i; - - return 0; + return disk->fops->report_zones(disk, sector, zones, nr_zones); } EXPORT_SYMBOL_GPL(blkdev_report_zones); @@ -185,15 +149,11 @@ static inline bool blkdev_allow_reset_all_zones(struct block_device *bdev, if (!blk_queue_zone_resetall(bdev_get_queue(bdev))) return false; - if (sector || nr_sectors != part_nr_sects_read(bdev->bd_part)) - return false; /* - * REQ_OP_ZONE_RESET_ALL can be executed only if the block device is - * the entire disk, that is, if the blocks device start offset is 0 and - * its capacity is the same as the entire disk. + * REQ_OP_ZONE_RESET_ALL can be executed only if the number of sectors + * of the applicable zone range is the entire disk. */ - return get_start_sect(bdev) == 0 && - part_nr_sects_read(bdev->bd_part) == get_capacity(bdev->bd_disk); + return !sector && nr_sectors == get_capacity(bdev->bd_disk); } /** @@ -218,6 +178,7 @@ int blkdev_zone_mgmt(struct block_device *bdev, enum req_opf op, { struct request_queue *q = bdev_get_queue(bdev); sector_t zone_sectors = blk_queue_zone_sectors(q); + sector_t capacity = get_capacity(bdev->bd_disk); sector_t end_sector = sector + nr_sectors; struct bio *bio = NULL; int ret; @@ -231,7 +192,7 @@ int blkdev_zone_mgmt(struct block_device *bdev, enum req_opf op, if (!op_is_zone_mgmt(op)) return -EOPNOTSUPP; - if (!nr_sectors || end_sector > bdev->bd_part->nr_sects) + if (!nr_sectors || end_sector > capacity) /* Out of range */ return -EINVAL; @@ -239,8 +200,7 @@ int blkdev_zone_mgmt(struct block_device *bdev, enum req_opf op, if (sector & (zone_sectors - 1)) return -EINVAL; - if ((nr_sectors & (zone_sectors - 1)) && - end_sector != bdev->bd_part->nr_sects) + if ((nr_sectors & (zone_sectors - 1)) && end_sector != capacity) return -EINVAL; while (sector < end_sector) { diff --git a/block/partition-generic.c b/block/partition-generic.c index aee643ce13d1..31bff3fb28af 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -459,56 +459,6 @@ static int drop_partitions(struct gendisk *disk, struct block_device *bdev) return 0; } -static bool part_zone_aligned(struct gendisk *disk, - struct block_device *bdev, - sector_t from, sector_t size) -{ - unsigned int zone_sectors = bdev_zone_sectors(bdev); - - /* - * If this function is called, then the disk is a zoned block device - * (host-aware or host-managed). This can be detected even if the - * zoned block device support is disabled (CONFIG_BLK_DEV_ZONED not - * set). In this case, however, only host-aware devices will be seen - * as a block device is not created for host-managed devices. Without - * zoned block device support, host-aware drives can still be used as - * regular block devices (no zone operation) and their zone size will - * be reported as 0. Allow this case. - */ - if (!zone_sectors) - return true; - - /* - * Check partition start and size alignement. If the drive has a - * smaller last runt zone, ignore it and allow the partition to - * use it. Check the zone size too: it should be a power of 2 number - * of sectors. - */ - if (WARN_ON_ONCE(!is_power_of_2(zone_sectors))) { - u32 rem; - - div_u64_rem(from, zone_sectors, &rem); - if (rem) - return false; - if ((from + size) < get_capacity(disk)) { - div_u64_rem(size, zone_sectors, &rem); - if (rem) - return false; - } - - } else { - - if (from & (zone_sectors - 1)) - return false; - if ((from + size) < get_capacity(disk) && - (size & (zone_sectors - 1))) - return false; - - } - - return true; -} - int rescan_partitions(struct gendisk *disk, struct block_device *bdev) { struct parsed_partitions *state = NULL; @@ -544,6 +494,14 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) } return -EIO; } + + /* Partitions are not supported on zoned block devices */ + if (bdev_is_zoned(bdev)) { + pr_warn("%s: ignoring partition table on zoned block device\n", + disk->disk_name); + goto out; + } + /* * If any partition code tried to read beyond EOD, try * unlocking native capacity even if partition table is @@ -607,21 +565,6 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) } } - /* - * On a zoned block device, partitions should be aligned on the - * device zone size (i.e. zone boundary crossing not allowed). - * Otherwise, resetting the write pointer of the last zone of - * one partition may impact the following partition. - */ - if (bdev_is_zoned(bdev) && - !part_zone_aligned(disk, bdev, from, size)) { - printk(KERN_WARNING - "%s: p%d start %llu+%llu is not zone aligned\n", - disk->disk_name, p, (unsigned long long) from, - (unsigned long long) size); - continue; - } - part = add_partition(disk, p, from, size, state->parts[p].flags, &state->parts[p].info); @@ -635,6 +578,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) md_autodetect_dev(part_to_dev(part)->devt); #endif } +out: free_partitions(state); return 0; } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 89189c29438f..76f4cfdd6b41 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1211,9 +1211,6 @@ EXPORT_SYMBOL_GPL(dm_accept_partial_bio); * The zone descriptors obtained with a zone report indicate * zone positions within the underlying device of the target. The zone * descriptors must be remapped to match their position within the dm device. - * The caller target should obtain the zones information using - * blkdev_report_zones() to ensure that remapping for partition offset is - * already handled. */ void dm_remap_zone_report(struct dm_target *ti, sector_t start, struct blk_zone *zones, unsigned int *nr_zones) From patchwork Mon Nov 11 02:39:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 11236477 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7D16415AB for ; Mon, 11 Nov 2019 02:39:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5BA23206C3 for ; Mon, 11 Nov 2019 02:39:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="LPrDs3ud" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726923AbfKKCjm (ORCPT ); Sun, 10 Nov 2019 21:39:42 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52028 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726906AbfKKCjl (ORCPT ); Sun, 10 Nov 2019 21:39:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1573439982; x=1604975982; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=Mhdy8g97yrlGhg/4RxtKDJYb9b3tPtuYVaQdVOv/e+c=; b=LPrDs3udB0j+Cn50+Fc8dDwcobvwtT7GzDaXekDAHBoe9CjDD0utZvfn JwDzu7/hBqtYJ7KSBWNwtWXWP1Ye1lBdWOc+64G+Ra3ClBLMYwvhSApaK 6+ntMAidbhfiMJm939KY3+EHIKFBHUJ7hlJStl9E5h8dh2XpH5jc0k8py Dj25KANU5GQI8KLxNt06DEC1KcprCucrNUBd9B51SQSejjMzCsMcPxxHx 7HAAX58i9sokMLOjrHOOWQqpUCC3WgSsoU0/nFBjJ2uHCLlHKrtxrBETq kmkY5gphEp6QBCwUguqnPe7VRY+ZEcMaKmaXEa3qd8weS6BAjrrOkpvug w==; IronPort-SDR: XgaDhrhLnim1SgKbySnyf+A02hU0ezxMnDtlbpUks+vtCQkx0LqNtQZhoqfO6gYvmmD8r6bnYe F4UnapC3QChFD/JLqf9gh+nurmUjuA331eZlPkUf5Cgj9hO+hJTkR+pY8oHpa4VB7ANbS8VIYh Gp5odrysSlbm8bxVFifH7QsY43Uz1LdnrK8h3kbBh2Bm+ouNpCGoEawsp0AJD1KmJL7tCGQ2Pa i8umDEjYzI3FukeNM1qNvihlfbiAr7pbkKsQToy26yJYJhjuN5M/MXGsw48Of1kJaZJVoaeF13 z10= X-IronPort-AV: E=Sophos;i="5.68,291,1569254400"; d="scan'208";a="127062975" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 11 Nov 2019 10:39:41 +0800 IronPort-SDR: FoL4vUE9DFst9Pq/VF57vYgNBFHGYoYvpyQT/qKzxpaYkPtnAM1bejc+cdmBM/ABSYg6qKQUTr SlJg3jeO4PK6qQMCbJ/Zs70gDY9Kr3IZajJNC+vZqFeVsPE3jMA8RD4taiyvV7VSoQzZficP2R qkytzG4ie8fQmG5atns0MEs/E/1JfU+jiYcDYFcaEODc1CT/KHlR5JkCWAWXVBlhYa9lVsWJTo 35HqVIjwJGXkkv74UxYlsLbuRSlX5fIaENoMSaXwXBPRFvUs0SRZ/gyiraUOZTyyf4sBhw+y77 /BVLsdcVkn4VGUPYlJj+jbih Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Nov 2019 18:34:45 -0800 IronPort-SDR: NyyzMjuId9K/cwPW4JejXGl9FOwY6f4zFA0r2xaWlqpgAWgx+kRjiP8OqVZDjDYVpGEZpwSIMZ hPo4W3ycGN7s6Py3xxyG2l2wTUQ/d4aQg2jSYGFmjC19ej2PEMO11ERUdlhul1ZcvGNJ3lyNXt TwsZraiGWIr9JWb9WdpAaWwQmF+iIsp8W4sgEKr9m/r1q5emigRYnXyY5HU9WxK5wLBB9UifKr lZg8Zm0UZPNOJcTwRXXQwzESDgKQlU0hTaJsdD9YS951Nzj26s42T6SjnXuO1JrvfTrj2PhTSR Nlk= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 10 Nov 2019 18:39:40 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , dm-devel@redhat.com, Mike Snitzer , linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim , Chao Yu Subject: [PATCH v2 5/9] null_blk: clean up the block device operations Date: Mon, 11 Nov 2019 11:39:26 +0900 Message-Id: <20191111023930.638129-6-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111023930.638129-1-damien.lemoal@wdc.com> References: <20191111023930.638129-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Christoph Hellwig Remove the pointless stub open and release methods, give the operations vector a slightly less confusing name, and use normal alignment for the assignment operators. Signed-off-by: Christoph Hellwig Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke Reviewed-by: Chaitanya Kulkarni --- drivers/block/null_blk_main.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 40a64bdd8ea7..89d385bab45b 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -1442,20 +1442,9 @@ static void null_config_discard(struct nullb *nullb) blk_queue_flag_set(QUEUE_FLAG_DISCARD, nullb->q); } -static int null_open(struct block_device *bdev, fmode_t mode) -{ - return 0; -} - -static void null_release(struct gendisk *disk, fmode_t mode) -{ -} - -static const struct block_device_operations null_fops = { - .owner = THIS_MODULE, - .open = null_open, - .release = null_release, - .report_zones = null_zone_report, +static const struct block_device_operations null_ops = { + .owner = THIS_MODULE, + .report_zones = null_zone_report, }; static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq) @@ -1556,7 +1545,7 @@ static int null_gendisk_register(struct nullb *nullb) disk->flags |= GENHD_FL_EXT_DEVT | GENHD_FL_SUPPRESS_PARTITION_INFO; disk->major = null_major; disk->first_minor = nullb->index; - disk->fops = &null_fops; + disk->fops = &null_ops; disk->private_data = nullb; disk->queue = nullb->q; strncpy(disk->disk_name, nullb->disk_name, DISK_NAME_LEN); From patchwork Mon Nov 11 02:39:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 11236483 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 501A417E6 for ; Mon, 11 Nov 2019 02:39:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2EE5B206C3 for ; Mon, 11 Nov 2019 02:39:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="OTFCa9l+" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726932AbfKKCjn (ORCPT ); Sun, 10 Nov 2019 21:39:43 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52028 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726906AbfKKCjn (ORCPT ); Sun, 10 Nov 2019 21:39:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1573439983; x=1604975983; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=1sZL6pRQBdfWfCo5BBLxp9YY078NIfK2LTB4YfkymDk=; b=OTFCa9l+5SAjVQxVkWOQYuBhAsuVJvlXbvUUBDy0sffA1Ue+diGPUbkJ UU0cBnxAXVdRIL7mS9F+vwtnpeqxFL9ofDc/XUuPqdPgNqBCZtraPp+iz 4KYIleshn79C5sEBCtRgckCZUveYK93El0bqvFktlJCD5VVwJzMpeAy1f aCORSrYq35lfisBeKLfYeVzyiVsO2UhWurBxTc2P0VveSvkpTB19zMnQz a1pQITLTAJktR7zH+Tw3IWzTgMs+z3tiCzQOQpeO8XiYt0eWXFk5lyEQt T9HHDvxE5Xu6vAbCt9tlUAJWyXLYOZfR6iZDJdO7RdTE2lYtOhUHhelI+ Q==; IronPort-SDR: 3f9y3Pis3dkngwV7Dt8dWvy0bJFJQhSmwwONiGPRLaNH4cMKzWZPZ+p8Ml6NHBgbnsPFLPRTt/ x33ImY36eGakydix6NpJbGdZT48lKMkHydTm/0aq7NqrArQkqa6bHsSjWdt+oKimivnJPDBZle VFfJ1j4dhfmesUCl4Q8JKHyU02NBAAhUH5Q6/mz86ZPvpNcsAQMbnu6+s+P9XyCnL3erxWS2Mp AkxOvNnt+rbopKyRFYIbbLolg/pFkaI61q4tZiz82tK+Y5ytb6TBO7MEYLYIjB5GHL0NN2plY4 rZY= X-IronPort-AV: E=Sophos;i="5.68,291,1569254400"; d="scan'208";a="127062980" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 11 Nov 2019 10:39:43 +0800 IronPort-SDR: +eDvJygzmTo7cDZ4RTUTGdPh9/Yz8AVx7Ec98zfVCpzfz+CNWYxzEGOiYHWt9OK3s7+4BTRlmR mQTvfkr+eDQKhcE/0Z530H3zy7jwR8aKwMJcC6pmJEdzDI5DEjMcMQbbS4RoaZpjaDK8UXuSM2 zWJpNkv22K7HUnAlmAD5OVf8rCKMXqi2HhUwOjIOPwaqRq66LsRkuLLBW8Gj26d0ZLFNKNVXBi atAy+/OMXSAG80OTZf3/v3UGWw2i5CbJhhWfJ6PY/SHdFnMPe+qLY7pxHZnMymDBQxip0EcdnR lxC3UTcqpBCHfKc3RWniyNCV Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Nov 2019 18:34:47 -0800 IronPort-SDR: lRZvIR/O5C0FpMyv+zvFumbYyQBnPVJ1FnoQZqkVLMMooNpJ/0rjTHZmZrD0WyLE2miEIqSrqF 3qm5nhqw7bx89FHZ+2c0CEbg6mgkTF5Wn9pJmNykmdtz+KiVQd5tZCWpERfIuyJiJNk/psksj5 5qAfYNqbiGrsIRZhQaWEG3Ew0fTF+bL3Dw2Nz4hvT8fwQI7uGQJemGKVZYXfZ0mV4OJ1xcXCLj 7bJqos/8t3hXxm7xir3bif0kRptpQdRgHnmsNIx9erUM5fPxVSQHGUpaCqVC2Ud65pA5T2XHA4 2nE= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 10 Nov 2019 18:39:42 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , dm-devel@redhat.com, Mike Snitzer , linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim , Chao Yu Subject: [PATCH v2 6/9] null_blk: clean up report zones Date: Mon, 11 Nov 2019 11:39:27 +0900 Message-Id: <20191111023930.638129-7-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111023930.638129-1-damien.lemoal@wdc.com> References: <20191111023930.638129-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Christoph Hellwig Make the instance name match the method name and define the name to NULL instead of providing an inline stub, which is rather pointless for a method call. Signed-off-by: Christoph Hellwig Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke Reviewed-by: Chaitanya Kulkarni --- drivers/block/null_blk.h | 11 +++-------- drivers/block/null_blk_main.c | 2 +- drivers/block/null_blk_zoned.c | 4 ++-- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h index 93c2a3d403da..9bf56fbab091 100644 --- a/drivers/block/null_blk.h +++ b/drivers/block/null_blk.h @@ -91,8 +91,8 @@ struct nullb { #ifdef CONFIG_BLK_DEV_ZONED int null_zone_init(struct nullb_device *dev); void null_zone_exit(struct nullb_device *dev); -int null_zone_report(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones); +int null_report_zones(struct gendisk *disk, sector_t sector, + struct blk_zone *zones, unsigned int *nr_zones); blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op, sector_t sector, sector_t nr_sectors); @@ -105,12 +105,6 @@ static inline int null_zone_init(struct nullb_device *dev) return -EINVAL; } static inline void null_zone_exit(struct nullb_device *dev) {} -static inline int null_zone_report(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, - unsigned int *nr_zones) -{ - return -EOPNOTSUPP; -} static inline blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op, sector_t sector, sector_t nr_sectors) @@ -123,5 +117,6 @@ static inline size_t null_zone_valid_read_len(struct nullb *nullb, { return len; } +#define null_report_zones NULL #endif /* CONFIG_BLK_DEV_ZONED */ #endif /* __NULL_BLK_H */ diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 89d385bab45b..2687eb36441c 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -1444,7 +1444,7 @@ static void null_config_discard(struct nullb *nullb) static const struct block_device_operations null_ops = { .owner = THIS_MODULE, - .report_zones = null_zone_report, + .report_zones = null_report_zones, }; static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq) diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c index 02f41a3bc4cb..00696f16664b 100644 --- a/drivers/block/null_blk_zoned.c +++ b/drivers/block/null_blk_zoned.c @@ -66,8 +66,8 @@ void null_zone_exit(struct nullb_device *dev) kvfree(dev->zones); } -int null_zone_report(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones) +int null_report_zones(struct gendisk *disk, sector_t sector, + struct blk_zone *zones, unsigned int *nr_zones) { struct nullb *nullb = disk->private_data; struct nullb_device *dev = nullb->dev; From patchwork Mon Nov 11 02:39:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 11236487 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 569C017E6 for ; Mon, 11 Nov 2019 02:39:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 34F0820842 for ; Mon, 11 Nov 2019 02:39:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="n8+k64wo" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726943AbfKKCjp (ORCPT ); Sun, 10 Nov 2019 21:39:45 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52028 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726804AbfKKCjp (ORCPT ); Sun, 10 Nov 2019 21:39:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1573439985; x=1604975985; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=ZiPMJXvFrkhjV/NQNmkkfkyUBz8ze5+Dwp1BnuDjbu8=; b=n8+k64woMpgPDhJrNZ4ck32+raxfxJfoyZ6D3YhCHBBm1Ox9px7JZO2h OvcjbBnCuOKzN/fPUi0iCCPgs21WC8pneU4pHp/QJRDFJQYnyqTUBswmY hCPistSwg8FTpKBntIPCG71rvOUrWqXJAUpNUUoS9sc0zTwX5JKDfInjW rERdIvpOKHGzLxvQWU4F2L36loXWn5xljZ3H4Mnt1EUk3p0oDI/acd661 YVfDtwvdES6GhgFj4Yy0pq4BUr6T+Jrn0oF8jIvM90GnITF9qMmK1lSGX Bi4ePufzGMs57+1M33z6Gt2+SLNRpcGucY2KYm5vpdocWex26gabePVek A==; IronPort-SDR: yCwUE5X9LqScjo/JWTgWyXbYKAYxoGe5g5iTLeqx0kePpVVMBX2Z4JJPXKLou7bp+2GnlWk23q 0kmPu4IUSRimpIM0u8Qpcenjv82dKxUy0FN5Agq+wZZ0VWksfcum08ApTbFY30GdfXiJSBV9HX l3kX7jz0l8OcOKU4E56yVBP+lFv57sDUiQIsvQkBkg0ejV/S2/I1RkYLlrxhV3RA2+vtyWTRRF GJ7OGX1TDjDah8AkA7TnM8leB823lq9nX1es+55dig0rOqx6K2CD0G6lfzP6j7VKIVtFTRuUFQ dpA= X-IronPort-AV: E=Sophos;i="5.68,291,1569254400"; d="scan'208";a="127062981" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 11 Nov 2019 10:39:44 +0800 IronPort-SDR: HRjn+SH/dYTybCdDTDUWSz2FQL1yR6jDVdJ5od2Tp/KyxaNgs8EALaqn0lfwbX2DCvbY42lh5q A+Vz282gBCZC+YEOTIYUz6bco90cQQHIkxKKEowuLlJASCGnjpT9IlOm9rWPms0WVstnJh3I4u TEu4ZW9V5SK0yY3+OWoUe4hdaIBc/1a+n8XKCKn4RSapAsRLjHOM58s88837Qg1wig8QS4HMto JyV75T6Rt4oFJ4rXCBrZxQ4Q18/d/OFWps+kGCDtpfoZMHb0xLw8nmoQSGOLuDzPo+ZrZJc4R6 XBEiX+JGq/RrqO5nojfb9S/q Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Nov 2019 18:34:49 -0800 IronPort-SDR: AAngVtZSiBojiLXp/FiK1WVNwreEkIoLIx3acvuylkjpOHLL9ELYXZ2JqDTlY6aVogeqZQj4lB wDhA3CGOwsJkD/b6NhTbI+/eA5P/jUxynwAB3Fhf2jAH6Ix3ST6hbx5OEjgYm4oSoF4gUoexpv 5NHZ8UP9iR7U/MVywlalJ4BQ/r0o3NiNkZ0/AM0umuOi4I6VwKb+hhxc/FtQsiCbRZie4a95yh 9tum5aOleaM3tjCo0NGNvjcFhKFILYHybeUdGPE5lG5eoMzqfSqcBcdhqhSeZH6RdmIQYzwTQo O4g= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 10 Nov 2019 18:39:44 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , dm-devel@redhat.com, Mike Snitzer , linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim , Chao Yu Subject: [PATCH v2 7/9] null_blk: Add zone_nr_conv to features Date: Mon, 11 Nov 2019 11:39:28 +0900 Message-Id: <20191111023930.638129-8-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111023930.638129-1-damien.lemoal@wdc.com> References: <20191111023930.638129-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org For a null_blk device with zoned mode enabled, the number of conventional zones can be configured through configfs with the zone_nr_conv parameter. Add this missing parameter in the features string. Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke Reviewed-by: Chaitanya Kulkarni --- drivers/block/null_blk_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 2687eb36441c..27fb34d7da31 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c @@ -467,7 +467,7 @@ nullb_group_drop_item(struct config_group *group, struct config_item *item) static ssize_t memb_group_features_show(struct config_item *item, char *page) { - return snprintf(page, PAGE_SIZE, "memory_backed,discard,bandwidth,cache,badblocks,zoned,zone_size\n"); + return snprintf(page, PAGE_SIZE, "memory_backed,discard,bandwidth,cache,badblocks,zoned,zone_size,zone_nr_conv\n"); } CONFIGFS_ATTR_RO(memb_group_, features); From patchwork Mon Nov 11 02:39:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 11236489 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 007E215AB for ; Mon, 11 Nov 2019 02:39:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D2A58206C3 for ; Mon, 11 Nov 2019 02:39:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="lkmG9Ghj" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726950AbfKKCjq (ORCPT ); Sun, 10 Nov 2019 21:39:46 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52028 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726804AbfKKCjq (ORCPT ); Sun, 10 Nov 2019 21:39:46 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1573439986; x=1604975986; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=bpIGBElxsl0fjSxZjNS/ZKnF4nvJx57BXQeH1ukfHDw=; b=lkmG9GhjtD9D9E3codvGlxX9XGo/sms1+XwvmgndovJwVWhK+VJcbaBV 84ZqObTfS1d8md2CJfjTibckYL9ftbhDNTk7+ak/TRPEyB4dEuVXVel7o cqT0ax5+R8c6BbwYvzYuHHh1EJz7AXOOFXEh5MCSpnfUrL7vNJGJ/Wruh OBR1u6WiVYaVleMBQ/nBJRmcpMlmRyULFkBMpJFqI8VHTsID18nkGfmbx GVxOSGL5ZSgNMJPVdJjB2mNUTCmPjRazF2FEgkz+wqwpiPG7O4MRP2g2U lktPSrhe1rVh6eHDvP2lWaK5gY75Z6mv3pks9tyapVkQLXohyfjtzmz+W Q==; IronPort-SDR: VTV7oBSxCraEInY9C3Mr+DNx6tMnDDVfJ/11oLDjLpV7edL/PJIqGH0CjAXpMq0xtVI8/X7/xp hru/QXkBlP2qhcJ03V71VpInpiJhqNWbehUUA21BVMWAxqJYoy0dFUtiPxK/bRpYKb2MCuZKFT Kc6drPvdoEcoEyxQoDio/7hF+Nyvhf0VJ9jllQMsqXZOTVhdAafqeF8vpY9DzKv2aiuUSgAh6K HtlBIdDFOlcC4EGRH9a9jpmHXc9G1sSXXYkXPuC4X4MdwcumFgZzW9US5j4XyBl8z67cU8+qwn cTY= X-IronPort-AV: E=Sophos;i="5.68,291,1569254400"; d="scan'208";a="127062983" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 11 Nov 2019 10:39:46 +0800 IronPort-SDR: WPN/zGsraGkYrJ9eU3LNeH97TInzidMcBnG+TogpwpTbt3Vn3hrTAlvtvICvxHMXj2ztoSqNyW UR8ANGl4s5MWzAynn/VquC9bLVQu/bTtJrYrIMTdJrRHp4H8T7Bu7Rt6LHd9aJqogdRvfFJjWt 2m0I1WTQakWaYASIrJMl6LYWWOWkh8gVL0qud+ay2TmgDLteGC9simks/Q/7+k7ick2yElTQqo mKLxK6XvCS4d9vZsiVkX9LeoZG9oJ57XW/JiXwQD4BvID06MihctGG042/i4a/qcMg3atZTtdK oTf5Jh0rgWVbfYAoK8nYhJPm Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Nov 2019 18:34:51 -0800 IronPort-SDR: d26YsSQ5WsgX0IMpopyKqryqzsAOLpcKOoJ2xbrC9TC0FnQgPCTQe7zeg6q06lZ8pNRHBKuQ7s 5TE96C5OXVFDXE/+AZmA82Y6G1fOMeS83me1ZR0vzCoSjwg+nWzv33CLcEvQoW9W90j3QZtO0I cv/Ps1TEZ+32UGA3y2kyRVxggtfLPM9TBjUv08jRX/PUace73jULqDKhykdlOGtnibsh+1O73H Z7msO/3h3ePoSqFMRZQ4iPq5DDX9gukcQL6g+MvEi9FdyRWEvsPxfBbo2AzYLBrHvGsdvH5nHm Yac= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 10 Nov 2019 18:39:45 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , dm-devel@redhat.com, Mike Snitzer , linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim , Chao Yu Subject: [PATCH v2 8/9] scsi: sd_zbc: Cleanup sd_zbc_alloc_report_buffer() Date: Mon, 11 Nov 2019 11:39:29 +0900 Message-Id: <20191111023930.638129-9-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111023930.638129-1-damien.lemoal@wdc.com> References: <20191111023930.638129-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org There is no need to arbitrarily limit the size of a report zone to the number of zones defined by SD_ZBC_REPORT_MAX_ZONES. Rather, simply calculate the report buffer size needed for the requested number of zones without exceeding the device total number of zones. This buffer size limitation to the hardware maximum transfer size and page mapping capabilities is kept unchanged. Starting with this initial buffer size, the allocation is optimized by iterating over decreasing buffer size until the allocation succeeds (each iteration is allowed to fail fast using the __GFP_NORETRY flag). This ensures forward progress for zone reports and avoids failures of zones revalidation under memory pressure. While at it, also replace the hard coded 512 B sector size with the SECTOR_SIZE macro. Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Acked-by: Martin K. Petersen --- drivers/scsi/sd_zbc.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 7c4690f26698..663608d1003b 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -104,11 +104,6 @@ static int sd_zbc_do_report_zones(struct scsi_disk *sdkp, unsigned char *buf, return 0; } -/* - * Maximum number of zones to get with one report zones command. - */ -#define SD_ZBC_REPORT_MAX_ZONES 8192U - /** * Allocate a buffer for report zones reply. * @sdkp: The target disk @@ -138,17 +133,24 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp, * sure that the allocated buffer can always be mapped by limiting the * number of pages allocated to the HBA max segments limit. */ - nr_zones = min(nr_zones, SD_ZBC_REPORT_MAX_ZONES); - bufsize = roundup((nr_zones + 1) * 64, 512); + nr_zones = min(nr_zones, sdkp->nr_zones); + bufsize = roundup((nr_zones + 1) * 64, SECTOR_SIZE); bufsize = min_t(size_t, bufsize, queue_max_hw_sectors(q) << SECTOR_SHIFT); bufsize = min_t(size_t, bufsize, queue_max_segments(q) << PAGE_SHIFT); - buf = vzalloc(bufsize); - if (buf) - *buflen = bufsize; + while (bufsize >= SECTOR_SIZE) { + buf = __vmalloc(bufsize, + GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY, + PAGE_KERNEL); + if (buf) { + *buflen = bufsize; + return buf; + } + bufsize >>= 1; + } - return buf; + return NULL; } /** From patchwork Mon Nov 11 02:39:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 11236495 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D4BE817E6 for ; Mon, 11 Nov 2019 02:39:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AA2232067B for ; Mon, 11 Nov 2019 02:39:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="FQxvF1Hs" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726952AbfKKCjt (ORCPT ); Sun, 10 Nov 2019 21:39:49 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:52028 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726804AbfKKCjt (ORCPT ); Sun, 10 Nov 2019 21:39:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1573439988; x=1604975988; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=J4UiU1mX+B3tiKo6TIiY/hU71073tFHJx3wsNcPOeKs=; b=FQxvF1HsThusDdnqt7pjM5cEQHMiRhYefOg2itmSG8t/9urbZ7TCLqa8 P+GzrUch/2Wq4pb0NPm3Igy5Mp4jPtI2LZX7EZ8deL/WI0h4JFWXLGkBZ 400XQ1lmgG0dmLYIJ5JhwY5Gr5iZpPI3++xZpLmjZtKvsUZvJRsPELOIB JhaREQPBe0UsQTTSk+04l3JLghgPD+nSoE3mQ2R4KTTvJeG5+OgbN5e58 3ak/nVBZ8SU41NyAl92aO3Se8BrWF3m++OAE7VOkcr4w1hpan79GKTJ+w 1PdxN6QMsP3gRbONRTCwBSUdZGTXqq61FwOtR5KXDdaXkLWbT62QSklDB g==; IronPort-SDR: EcieQqsArJgIh+EmNyWyUAss3ai1M4USIc5QqryQSDlNOkal+a3/aQMHjupEOU6V9Ac7Hkbbje UWMOmE2+mvv4u+X/NyfAUWy8RsqZxTPqHW9PKQB3tZN2WKluyn/hmBLusxegT109oqDlIkokcz 1ixhETL9GpIb/fOwW4ONVIeKoY/0Z4l0l52sHP/pYIjO9TOOPp+wHPLLW/XUDTC8SYR8e0sEcd 6Zg/p/s54hiC6f4lYypF3YBPmdN4kuPNEIEgKEBEczrzRwVTS9MN0YmjQ48TZ18AWwC9wjEX9O J44= X-IronPort-AV: E=Sophos;i="5.68,291,1569254400"; d="scan'208";a="127062987" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 11 Nov 2019 10:39:48 +0800 IronPort-SDR: oTzD8EhruGLfSFhOqWVHy9jRHkzRCVWnNFgN4DhE2EGVBhUdhbEpAbc4MA8BOlCJWA5WBNFEy7 jKuB2OVrf8tzYXB8GPZW29UA7T5+TLw8KjesTm5tt/1TWOfL3dg46hDRC5aOXEIzvjlfxbEB0Z x0Ftef/b4aK3iIemSPYjfk62cxFJj342aVnu5Lj+vTK953Ggh4TFYgQaKbWiUDh/Zypg25D2OT OKVfPQGfR9Vxo3NyGnnF/pbb2yYoY7FVwZVRCA1pNod72YpV7TVmUQATnBsxoSCPi1va3FEXNT Kk7B1bT9hysLaCpa1tEEmqk/ Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Nov 2019 18:34:52 -0800 IronPort-SDR: TivfsMgmaloc03B6QsuJPP+lcEC7sFz2CPhkOS4azMdddwVnu0Gm+8LulK7r+REwTmIV0y1TJt NqzxNY5McMwKupWbSLmBndC3bk58ewc8QmyJFPQw9d0UDd4/fG8ttNdhN/ThfjyQTBZGfbqgra 2src2QwO6d/eGaZvFTVV9dtOAWMub2rS3pCnJEuZoJHy2RmkGSsRmuDCpCq1hc4q0QQIdkFW0e mzEykqw8sUaUvq1r6Dw9yWlz6BmkEIS/brEFnexjS8lcqkWRPR2nisPBRWZny8v5B5hr+C6i96 JCE= WDCIronportException: Internal Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 10 Nov 2019 18:39:47 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Jens Axboe , linux-scsi@vger.kernel.org, "Martin K . Petersen" , dm-devel@redhat.com, Mike Snitzer , linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim , Chao Yu Subject: [PATCH v2 9/9] block: rework zone reporting Date: Mon, 11 Nov 2019 11:39:30 +0900 Message-Id: <20191111023930.638129-10-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191111023930.638129-1-damien.lemoal@wdc.com> References: <20191111023930.638129-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org From: Christoph Hellwig Avoid the need to allocate a potentially large array of struct blk_zone in the block layer by switching the ->report_zones method interface to a callback model. Now the caller simply supplies a callback that is executed on each reported zone, and private data for it. Signed-off-by: Christoph Hellwig Signed-off-by: Shin'ichiro Kawasaki Signed-off-by: Damien Le Moal Reviewed-by: Hannes Reinecke Reviewed-by: Mike Snitzer --- block/blk-zoned.c | 253 +++++++++++++-------------------- drivers/block/null_blk.h | 2 +- drivers/block/null_blk_zoned.c | 31 ++-- drivers/md/dm-flakey.c | 18 +-- drivers/md/dm-linear.c | 20 +-- drivers/md/dm-zoned-metadata.c | 131 +++++++---------- drivers/md/dm.c | 121 +++++++--------- drivers/scsi/sd.h | 4 +- drivers/scsi/sd_zbc.c | 106 +++++++------- fs/f2fs/super.c | 51 +++---- include/linux/blkdev.h | 15 +- include/linux/device-mapper.h | 24 +++- 12 files changed, 329 insertions(+), 447 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index ae665e490858..6fad6f3f6980 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -101,44 +101,35 @@ EXPORT_SYMBOL_GPL(blkdev_nr_zones); * blkdev_report_zones - Get zones information * @bdev: Target block device * @sector: Sector from which to report zones - * @zones: Array of zone structures where to return the zones information - * @nr_zones: Number of zone structures in the zone array + * @nr_zones: Maximum number of zones to report + * @cb: Callback function called for each reported zone + * @data: Private data for the callback * * Description: - * Get zone information starting from the zone containing @sector. - * The number of zone information reported may be less than the number - * requested by @nr_zones. The number of zones actually reported is - * returned in @nr_zones. - * The caller must use memalloc_noXX_save/restore() calls to control - * memory allocations done within this function (zone array and command - * buffer allocation by the device driver). + * Get zone information starting from the zone containing @sector for at most + * @nr_zones, and call @cb for each zone reported by the device. + * To report all zones in a device starting from @sector, the BLK_ALL_ZONES + * constant can be passed to @nr_zones. + * Returns the number of zones reported by the device, or a negative errno + * value in case of failure. + * + * Note: The caller must use memalloc_noXX_save/restore() calls to control + * memory allocations done within this function. */ int blkdev_report_zones(struct block_device *bdev, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones) + unsigned int nr_zones, report_zones_cb cb, void *data) { - struct request_queue *q = bdev_get_queue(bdev); struct gendisk *disk = bdev->bd_disk; sector_t capacity = get_capacity(disk); - if (!blk_queue_is_zoned(q)) - return -EOPNOTSUPP; - - /* - * A block device that advertized itself as zoned must have a - * report_zones method. If it does not have one defined, the device - * driver has a bug. So warn about that. - */ - if (WARN_ON_ONCE(!disk->fops->report_zones)) + if (!blk_queue_is_zoned(bdev_get_queue(bdev)) || + WARN_ON_ONCE(!disk->fops->report_zones)) return -EOPNOTSUPP; - if (!*nr_zones || sector >= capacity) { - *nr_zones = 0; + if (!nr_zones || sector >= capacity) return 0; - } - *nr_zones = min(*nr_zones, __blkdev_nr_zones(q, capacity - sector)); - - return disk->fops->report_zones(disk, sector, zones, nr_zones); + return disk->fops->report_zones(disk, sector, nr_zones, cb, data); } EXPORT_SYMBOL_GPL(blkdev_report_zones); @@ -232,6 +223,20 @@ int blkdev_zone_mgmt(struct block_device *bdev, enum req_opf op, } EXPORT_SYMBOL_GPL(blkdev_zone_mgmt); +struct zone_report_args { + struct blk_zone __user *zones; +}; + +static int blkdev_copy_zone_to_user(struct blk_zone *zone, unsigned int idx, + void *data) +{ + struct zone_report_args *args = data; + + if (copy_to_user(&args->zones[idx], zone, sizeof(struct blk_zone))) + return -EFAULT; + return 0; +} + /* * BLKREPORTZONE ioctl processing. * Called from blkdev_ioctl. @@ -240,9 +245,9 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; + struct zone_report_args args; struct request_queue *q; struct blk_zone_report rep; - struct blk_zone *zones; int ret; if (!argp) @@ -264,32 +269,16 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, if (!rep.nr_zones) return -EINVAL; - rep.nr_zones = min(blkdev_nr_zones(bdev), rep.nr_zones); - - zones = kvmalloc_array(rep.nr_zones, sizeof(struct blk_zone), - GFP_KERNEL | __GFP_ZERO); - if (!zones) - return -ENOMEM; - - ret = blkdev_report_zones(bdev, rep.sector, zones, &rep.nr_zones); - if (ret) - goto out; - - if (copy_to_user(argp, &rep, sizeof(struct blk_zone_report))) { - ret = -EFAULT; - goto out; - } - - if (rep.nr_zones) { - if (copy_to_user(argp + sizeof(struct blk_zone_report), zones, - sizeof(struct blk_zone) * rep.nr_zones)) - ret = -EFAULT; - } + args.zones = argp + sizeof(struct blk_zone_report); + ret = blkdev_report_zones(bdev, rep.sector, rep.nr_zones, + blkdev_copy_zone_to_user, &args); + if (ret < 0) + return ret; - out: - kvfree(zones); - - return ret; + rep.nr_zones = ret; + if (copy_to_user(argp, &rep, sizeof(struct blk_zone_report))) + return -EFAULT; + return 0; } /* @@ -351,31 +340,6 @@ static inline unsigned long *blk_alloc_zone_bitmap(int node, GFP_NOIO, node); } -/* - * Allocate an array of struct blk_zone to get nr_zones zone information. - * The allocated array may be smaller than nr_zones. - */ -static struct blk_zone *blk_alloc_zones(unsigned int *nr_zones) -{ - struct blk_zone *zones; - size_t nrz = min(*nr_zones, BLK_ZONED_REPORT_MAX_ZONES); - - /* - * GFP_KERNEL here is meaningless as the caller task context has - * the PF_MEMALLOC_NOIO flag set in blk_revalidate_disk_zones() - * with memalloc_noio_save(). - */ - zones = kvcalloc(nrz, sizeof(struct blk_zone), GFP_KERNEL); - if (!zones) { - *nr_zones = 0; - return NULL; - } - - *nr_zones = nrz; - - return zones; -} - void blk_queue_free_zone_bitmaps(struct request_queue *q) { kfree(q->seq_zones_bitmap); @@ -384,12 +348,21 @@ void blk_queue_free_zone_bitmaps(struct request_queue *q) q->seq_zones_wlock = NULL; } +struct blk_revalidate_zone_args { + struct gendisk *disk; + unsigned long *seq_zones_bitmap; + unsigned long *seq_zones_wlock; + sector_t sector; +}; + /* * Helper function to check the validity of zones of a zoned block device. */ -static bool blk_zone_valid(struct gendisk *disk, struct blk_zone *zone, - sector_t *sector) +static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, + void *data) { + struct blk_revalidate_zone_args *args = data; + struct gendisk *disk = args->disk; struct request_queue *q = disk->queue; sector_t zone_sectors = blk_queue_zone_sectors(q); sector_t capacity = get_capacity(disk); @@ -409,14 +382,14 @@ static bool blk_zone_valid(struct gendisk *disk, struct blk_zone *zone, zone->len > zone_sectors) { pr_warn("%s: Invalid zoned device with larger last zone size\n", disk->disk_name); - return false; + return -ENODEV; } /* Check for holes in the zone report */ - if (zone->start != *sector) { + if (zone->start != args->sector) { pr_warn("%s: Zone gap at sectors %llu..%llu\n", - disk->disk_name, *sector, zone->start); - return false; + disk->disk_name, args->sector, zone->start); + return -ENODEV; } /* Check zone type */ @@ -428,12 +401,38 @@ static bool blk_zone_valid(struct gendisk *disk, struct blk_zone *zone, default: pr_warn("%s: Invalid zone type 0x%x at sectors %llu\n", disk->disk_name, (int)zone->type, zone->start); - return false; + return -ENODEV; } - *sector += zone->len; + if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) + set_bit(idx, args->seq_zones_bitmap); - return true; + args->sector += zone->len; + return 0; +} + +static int blk_update_zone_info(struct gendisk *disk, unsigned int nr_zones, + struct blk_revalidate_zone_args *args) +{ + /* + * Ensure that all memory allocations in this context are done as + * if GFP_NOIO was specified. + */ + unsigned int noio_flag = memalloc_noio_save(); + struct request_queue *q = disk->queue; + int ret; + + args->seq_zones_wlock = blk_alloc_zone_bitmap(q->node, nr_zones); + if (!args->seq_zones_wlock) + return -ENOMEM; + args->seq_zones_bitmap = blk_alloc_zone_bitmap(q->node, nr_zones); + if (!args->seq_zones_bitmap) + return -ENOMEM; + + ret = disk->fops->report_zones(disk, 0, nr_zones, + blk_revalidate_zone_cb, args); + memalloc_noio_restore(noio_flag); + return ret; } /** @@ -449,11 +448,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk) { struct request_queue *q = disk->queue; unsigned int nr_zones = __blkdev_nr_zones(q, get_capacity(disk)); - unsigned long *seq_zones_wlock = NULL, *seq_zones_bitmap = NULL; - unsigned int i, rep_nr_zones = 0, z = 0, nrz; - struct blk_zone *zones = NULL; - unsigned int noio_flag; - sector_t sector = 0; + struct blk_revalidate_zone_args args = { .disk = disk }; int ret = 0; if (WARN_ON_ONCE(!blk_queue_is_zoned(q))) @@ -468,82 +463,28 @@ int blk_revalidate_disk_zones(struct gendisk *disk) return 0; } - /* - * Ensure that all memory allocations in this context are done as - * if GFP_NOIO was specified. - */ - noio_flag = memalloc_noio_save(); - - if (!nr_zones) - goto update; - - /* Allocate bitmaps */ - ret = -ENOMEM; - seq_zones_wlock = blk_alloc_zone_bitmap(q->node, nr_zones); - if (!seq_zones_wlock) - goto out; - seq_zones_bitmap = blk_alloc_zone_bitmap(q->node, nr_zones); - if (!seq_zones_bitmap) - goto out; - - /* - * Get zone information to check the zones and initialize - * seq_zones_bitmap. - */ - rep_nr_zones = nr_zones; - zones = blk_alloc_zones(&rep_nr_zones); - if (!zones) - goto out; - - while (z < nr_zones) { - nrz = min(nr_zones - z, rep_nr_zones); - ret = disk->fops->report_zones(disk, sector, zones, &nrz); - if (ret) - goto out; - if (!nrz) - break; - for (i = 0; i < nrz; i++) { - if (!blk_zone_valid(disk, &zones[i], §or)) { - ret = -ENODEV; - goto out; - } - if (zones[i].type != BLK_ZONE_TYPE_CONVENTIONAL) - set_bit(z, seq_zones_bitmap); - z++; - } - } - - if (WARN_ON(z != nr_zones)) { - ret = -EIO; - goto out; - } + if (nr_zones) + ret = blk_update_zone_info(disk, nr_zones, &args); -update: /* * Install the new bitmaps, making sure the queue is stopped and * all I/Os are completed (i.e. a scheduler is not referencing the * bitmaps). */ blk_mq_freeze_queue(q); - q->nr_zones = nr_zones; - swap(q->seq_zones_wlock, seq_zones_wlock); - swap(q->seq_zones_bitmap, seq_zones_bitmap); - blk_mq_unfreeze_queue(q); - -out: - memalloc_noio_restore(noio_flag); - - kvfree(zones); - kfree(seq_zones_wlock); - kfree(seq_zones_bitmap); - - if (ret) { + if (ret >= 0) { + q->nr_zones = nr_zones; + swap(q->seq_zones_wlock, args.seq_zones_wlock); + swap(q->seq_zones_bitmap, args.seq_zones_bitmap); + ret = 0; + } else { pr_warn("%s: failed to revalidate zones\n", disk->disk_name); - blk_mq_freeze_queue(q); blk_queue_free_zone_bitmaps(q); - blk_mq_unfreeze_queue(q); } + blk_mq_unfreeze_queue(q); + kfree(args.seq_zones_wlock); + kfree(args.seq_zones_bitmap); return ret; } EXPORT_SYMBOL_GPL(blk_revalidate_disk_zones); diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h index 9bf56fbab091..bc837862b767 100644 --- a/drivers/block/null_blk.h +++ b/drivers/block/null_blk.h @@ -92,7 +92,7 @@ struct nullb { int null_zone_init(struct nullb_device *dev); void null_zone_exit(struct nullb_device *dev); int null_report_zones(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones); + unsigned int nr_zones, report_zones_cb cb, void *data); blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op, sector_t sector, sector_t nr_sectors); diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c index 00696f16664b..d4d88b581822 100644 --- a/drivers/block/null_blk_zoned.c +++ b/drivers/block/null_blk_zoned.c @@ -67,21 +67,34 @@ void null_zone_exit(struct nullb_device *dev) } int null_report_zones(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones) + unsigned int nr_zones, report_zones_cb cb, void *data) { struct nullb *nullb = disk->private_data; struct nullb_device *dev = nullb->dev; - unsigned int zno, nrz = 0; + unsigned int first_zone, i; + struct blk_zone zone; + int error; - zno = null_zone_no(dev, sector); - if (zno < dev->nr_zones) { - nrz = min_t(unsigned int, *nr_zones, dev->nr_zones - zno); - memcpy(zones, &dev->zones[zno], nrz * sizeof(struct blk_zone)); - } + first_zone = null_zone_no(dev, sector); + if (first_zone >= dev->nr_zones) + return 0; - *nr_zones = nrz; + nr_zones = min(nr_zones, dev->nr_zones - first_zone); + for (i = 0; i < nr_zones; i++) { + /* + * Stacked DM target drivers will remap the zone information by + * modifying the zone information passed to the report callback. + * So use a local copy to avoid corruption of the device zone + * array. + */ + memcpy(&zone, &dev->zones[first_zone + i], + sizeof(struct blk_zone)); + error = cb(&zone, i, data); + if (error) + return error; + } - return 0; + return nr_zones; } size_t null_zone_valid_read_len(struct nullb *nullb, diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index 76587e9af0ef..a2cc9e45cbba 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -459,21 +459,15 @@ static int flakey_prepare_ioctl(struct dm_target *ti, struct block_device **bdev } #ifdef CONFIG_BLK_DEV_ZONED -static int flakey_report_zones(struct dm_target *ti, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones) +static int flakey_report_zones(struct dm_target *ti, + struct dm_report_zones_args *args, unsigned int nr_zones) { struct flakey_c *fc = ti->private; - int ret; + sector_t sector = flakey_map_sector(ti, args->next_sector); - /* Do report and remap it */ - ret = blkdev_report_zones(fc->dev->bdev, flakey_map_sector(ti, sector), - zones, nr_zones); - if (ret != 0) - return ret; - - if (*nr_zones) - dm_remap_zone_report(ti, fc->start, zones, nr_zones); - return 0; + args->start = fc->start; + return blkdev_report_zones(fc->dev->bdev, sector, nr_zones, + dm_report_zones_cb, args); } #endif diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 97acafd48c85..8d07fdf63a47 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -136,21 +136,15 @@ static int linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev } #ifdef CONFIG_BLK_DEV_ZONED -static int linear_report_zones(struct dm_target *ti, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones) +static int linear_report_zones(struct dm_target *ti, + struct dm_report_zones_args *args, unsigned int nr_zones) { - struct linear_c *lc = (struct linear_c *) ti->private; - int ret; - - /* Do report and remap it */ - ret = blkdev_report_zones(lc->dev->bdev, linear_map_sector(ti, sector), - zones, nr_zones); - if (ret != 0) - return ret; + struct linear_c *lc = ti->private; + sector_t sector = linear_map_sector(ti, args->next_sector); - if (*nr_zones) - dm_remap_zone_report(ti, lc->start, zones, nr_zones); - return 0; + args->start = lc->start; + return blkdev_report_zones(lc->dev->bdev, sector, nr_zones, + dm_report_zones_cb, args); } #endif diff --git a/drivers/md/dm-zoned-metadata.c b/drivers/md/dm-zoned-metadata.c index feb4718ce6a6..069e4675da6b 100644 --- a/drivers/md/dm-zoned-metadata.c +++ b/drivers/md/dm-zoned-metadata.c @@ -1080,9 +1080,10 @@ static int dmz_load_sb(struct dmz_metadata *zmd) /* * Initialize a zone descriptor. */ -static int dmz_init_zone(struct dmz_metadata *zmd, struct dm_zone *zone, - struct blk_zone *blkz) +static int dmz_init_zone(struct blk_zone *blkz, unsigned int idx, void *data) { + struct dmz_metadata *zmd = data; + struct dm_zone *zone = &zmd->zones[idx]; struct dmz_dev *dev = zmd->dev; /* Ignore the eventual last runt (smaller) zone */ @@ -1096,26 +1097,29 @@ static int dmz_init_zone(struct dmz_metadata *zmd, struct dm_zone *zone, atomic_set(&zone->refcount, 0); zone->chunk = DMZ_MAP_UNMAPPED; - if (blkz->type == BLK_ZONE_TYPE_CONVENTIONAL) { + switch (blkz->type) { + case BLK_ZONE_TYPE_CONVENTIONAL: set_bit(DMZ_RND, &zone->flags); zmd->nr_rnd_zones++; - } else if (blkz->type == BLK_ZONE_TYPE_SEQWRITE_REQ || - blkz->type == BLK_ZONE_TYPE_SEQWRITE_PREF) { + break; + case BLK_ZONE_TYPE_SEQWRITE_REQ: + case BLK_ZONE_TYPE_SEQWRITE_PREF: set_bit(DMZ_SEQ, &zone->flags); - } else + break; + default: return -ENXIO; - - if (blkz->cond == BLK_ZONE_COND_OFFLINE) - set_bit(DMZ_OFFLINE, &zone->flags); - else if (blkz->cond == BLK_ZONE_COND_READONLY) - set_bit(DMZ_READ_ONLY, &zone->flags); + } if (dmz_is_rnd(zone)) zone->wp_block = 0; else zone->wp_block = dmz_sect2blk(blkz->wp - blkz->start); - if (!dmz_is_offline(zone) && !dmz_is_readonly(zone)) { + if (blkz->cond == BLK_ZONE_COND_OFFLINE) + set_bit(DMZ_OFFLINE, &zone->flags); + else if (blkz->cond == BLK_ZONE_COND_READONLY) + set_bit(DMZ_READ_ONLY, &zone->flags); + else { zmd->nr_useable_zones++; if (dmz_is_rnd(zone)) { zmd->nr_rnd_zones++; @@ -1138,12 +1142,6 @@ static void dmz_drop_zones(struct dmz_metadata *zmd) zmd->zones = NULL; } -/* - * The size of a zone report in number of zones. - * This results in 4096*64B=256KB report zones commands. - */ -#define DMZ_REPORT_NR_ZONES 4096 - /* * Allocate and initialize zone descriptors using the zone * information from disk. @@ -1151,11 +1149,7 @@ static void dmz_drop_zones(struct dmz_metadata *zmd) static int dmz_init_zones(struct dmz_metadata *zmd) { struct dmz_dev *dev = zmd->dev; - struct dm_zone *zone; - struct blk_zone *blkz; - unsigned int nr_blkz; - sector_t sector = 0; - int i, ret = 0; + int ret; /* Init */ zmd->zone_bitmap_size = dev->zone_nr_blocks >> 3; @@ -1169,54 +1163,38 @@ static int dmz_init_zones(struct dmz_metadata *zmd) dmz_dev_info(dev, "Using %zu B for zone information", sizeof(struct dm_zone) * dev->nr_zones); - /* Get zone information */ - nr_blkz = DMZ_REPORT_NR_ZONES; - blkz = kcalloc(nr_blkz, sizeof(struct blk_zone), GFP_KERNEL); - if (!blkz) { - ret = -ENOMEM; - goto out; - } - /* - * Get zone information and initialize zone descriptors. - * At the same time, determine where the super block - * should be: first block of the first randomly writable - * zone. + * Get zone information and initialize zone descriptors. At the same + * time, determine where the super block should be: first block of the + * first randomly writable zone. */ - zone = zmd->zones; - while (sector < dev->capacity) { - /* Get zone information */ - nr_blkz = DMZ_REPORT_NR_ZONES; - ret = blkdev_report_zones(dev->bdev, sector, blkz, &nr_blkz); - if (ret) { - dmz_dev_err(dev, "Report zones failed %d", ret); - goto out; - } + ret = blkdev_report_zones(dev->bdev, 0, BLK_ALL_ZONES, dmz_init_zone, + zmd); + if (ret < 0) { + dmz_drop_zones(zmd); + return ret; + } - if (!nr_blkz) - break; + return 0; +} - /* Process report */ - for (i = 0; i < nr_blkz; i++) { - ret = dmz_init_zone(zmd, zone, &blkz[i]); - if (ret) - goto out; - sector += dev->zone_nr_sectors; - zone++; - } - } +static int dmz_update_zone_cb(struct blk_zone *blkz, unsigned int idx, + void *data) +{ + struct dm_zone *zone = data; - /* The entire zone configuration of the disk should now be known */ - if (sector < dev->capacity) { - dmz_dev_err(dev, "Failed to get correct zone information"); - ret = -ENXIO; - } -out: - kfree(blkz); - if (ret) - dmz_drop_zones(zmd); + clear_bit(DMZ_OFFLINE, &zone->flags); + clear_bit(DMZ_READ_ONLY, &zone->flags); + if (blkz->cond == BLK_ZONE_COND_OFFLINE) + set_bit(DMZ_OFFLINE, &zone->flags); + else if (blkz->cond == BLK_ZONE_COND_READONLY) + set_bit(DMZ_READ_ONLY, &zone->flags); - return ret; + if (dmz_is_seq(zone)) + zone->wp_block = dmz_sect2blk(blkz->wp - blkz->start); + else + zone->wp_block = 0; + return 0; } /* @@ -1224,9 +1202,7 @@ static int dmz_init_zones(struct dmz_metadata *zmd) */ static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone) { - unsigned int nr_blkz = 1; unsigned int noio_flag; - struct blk_zone blkz; int ret; /* @@ -1236,29 +1212,18 @@ static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone) * GFP_NOIO was specified. */ noio_flag = memalloc_noio_save(); - ret = blkdev_report_zones(zmd->dev->bdev, dmz_start_sect(zmd, zone), - &blkz, &nr_blkz); + ret = blkdev_report_zones(zmd->dev->bdev, dmz_start_sect(zmd, zone), 1, + dmz_update_zone_cb, zone); memalloc_noio_restore(noio_flag); - if (!nr_blkz) + + if (ret == 0) ret = -EIO; - if (ret) { + if (ret < 0) { dmz_dev_err(zmd->dev, "Get zone %u report failed", dmz_id(zmd, zone)); return ret; } - clear_bit(DMZ_OFFLINE, &zone->flags); - clear_bit(DMZ_READ_ONLY, &zone->flags); - if (blkz.cond == BLK_ZONE_COND_OFFLINE) - set_bit(DMZ_OFFLINE, &zone->flags); - else if (blkz.cond == BLK_ZONE_COND_READONLY) - set_bit(DMZ_READ_ONLY, &zone->flags); - - if (dmz_is_seq(zone)) - zone->wp_block = dmz_sect2blk(blkz.wp - blkz.start); - else - zone->wp_block = 0; - return 0; } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 76f4cfdd6b41..e8f9661a10a1 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -440,14 +440,48 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) return dm_get_geometry(md, geo); } +#ifdef CONFIG_BLK_DEV_ZONED +int dm_report_zones_cb(struct blk_zone *zone, unsigned int idx, void *data) +{ + struct dm_report_zones_args *args = data; + sector_t sector_diff = args->tgt->begin - args->start; + + /* + * Ignore zones beyond the target range. + */ + if (zone->start >= args->start + args->tgt->len) + return 0; + + /* + * Remap the start sector and write pointer position of the zone + * to match its position in the target range. + */ + zone->start += sector_diff; + if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) { + if (zone->cond == BLK_ZONE_COND_FULL) + zone->wp = zone->start + zone->len; + else if (zone->cond == BLK_ZONE_COND_EMPTY) + zone->wp = zone->start; + else + zone->wp += sector_diff; + } + + args->next_sector = zone->start + zone->len; + return args->orig_cb(zone, args->zone_idx++, args->orig_data); +} +EXPORT_SYMBOL_GPL(dm_report_zones_cb); + static int dm_blk_report_zones(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones) + unsigned int nr_zones, report_zones_cb cb, void *data) { -#ifdef CONFIG_BLK_DEV_ZONED struct mapped_device *md = disk->private_data; - struct dm_target *tgt; struct dm_table *map; int srcu_idx, ret; + struct dm_report_zones_args args = { + .next_sector = sector, + .orig_data = data, + .orig_cb = cb, + }; if (dm_suspended_md(md)) return -EAGAIN; @@ -456,32 +490,30 @@ static int dm_blk_report_zones(struct gendisk *disk, sector_t sector, if (!map) return -EIO; - tgt = dm_table_find_target(map, sector); - if (!tgt) { - ret = -EIO; - goto out; - } + do { + struct dm_target *tgt; - /* - * If we are executing this, we already know that the block device - * is a zoned device and so each target should have support for that - * type of drive. A missing report_zones method means that the target - * driver has a problem. - */ - if (WARN_ON(!tgt->type->report_zones)) { - ret = -EIO; - goto out; - } + tgt = dm_table_find_target(map, args.next_sector); + if (WARN_ON_ONCE(!tgt->type->report_zones)) { + ret = -EIO; + goto out; + } - ret = tgt->type->report_zones(tgt, sector, zones, nr_zones); + args.tgt = tgt; + ret = tgt->type->report_zones(tgt, &args, nr_zones); + if (ret < 0) + goto out; + } while (args.zone_idx < nr_zones && + args.next_sector < get_capacity(disk)); + ret = args.zone_idx; out: dm_put_live_table(md, srcu_idx); return ret; -#else - return -ENOTSUPP; -#endif } +#else +#define dm_blk_report_zones NULL +#endif /* CONFIG_BLK_DEV_ZONED */ static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx, struct block_device **bdev) @@ -1207,51 +1239,6 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors) } EXPORT_SYMBOL_GPL(dm_accept_partial_bio); -/* - * The zone descriptors obtained with a zone report indicate - * zone positions within the underlying device of the target. The zone - * descriptors must be remapped to match their position within the dm device. - */ -void dm_remap_zone_report(struct dm_target *ti, sector_t start, - struct blk_zone *zones, unsigned int *nr_zones) -{ -#ifdef CONFIG_BLK_DEV_ZONED - struct blk_zone *zone; - unsigned int nrz = *nr_zones; - int i; - - /* - * Remap the start sector and write pointer position of the zones in - * the array. Since we may have obtained from the target underlying - * device more zones that the target size, also adjust the number - * of zones. - */ - for (i = 0; i < nrz; i++) { - zone = zones + i; - if (zone->start >= start + ti->len) { - memset(zone, 0, sizeof(struct blk_zone) * (nrz - i)); - break; - } - - zone->start = zone->start + ti->begin - start; - if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) - continue; - - if (zone->cond == BLK_ZONE_COND_FULL) - zone->wp = zone->start + zone->len; - else if (zone->cond == BLK_ZONE_COND_EMPTY) - zone->wp = zone->start; - else - zone->wp = zone->wp + ti->begin - start; - } - - *nr_zones = i; -#else /* !CONFIG_BLK_DEV_ZONED */ - *nr_zones = 0; -#endif -} -EXPORT_SYMBOL_GPL(dm_remap_zone_report); - static blk_qc_t __map_bio(struct dm_target_io *tio) { int r; diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index bf2102a749bc..42fd3f00e4a5 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -213,8 +213,8 @@ blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd, unsigned char op, bool all); extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes, struct scsi_sense_hdr *sshdr); -extern int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones); +int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, + unsigned int nr_zones, report_zones_cb cb, void *data); #else /* CONFIG_BLK_DEV_ZONED */ diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c index 663608d1003b..23281825ec38 100644 --- a/drivers/scsi/sd_zbc.c +++ b/drivers/scsi/sd_zbc.c @@ -19,34 +19,27 @@ #include "sd.h" -/** - * sd_zbc_parse_report - Convert a zone descriptor to a struct blk_zone, - * @sdkp: The disk the report originated from - * @buf: Address of the report zone descriptor - * @zone: the destination zone structure - * - * All LBA sized values are converted to 512B sectors unit. - */ -static void sd_zbc_parse_report(struct scsi_disk *sdkp, u8 *buf, - struct blk_zone *zone) +static int sd_zbc_parse_report(struct scsi_disk *sdkp, u8 *buf, + unsigned int idx, report_zones_cb cb, void *data) { struct scsi_device *sdp = sdkp->device; + struct blk_zone zone = { 0 }; - memset(zone, 0, sizeof(struct blk_zone)); - - zone->type = buf[0] & 0x0f; - zone->cond = (buf[1] >> 4) & 0xf; + zone.type = buf[0] & 0x0f; + zone.cond = (buf[1] >> 4) & 0xf; if (buf[1] & 0x01) - zone->reset = 1; + zone.reset = 1; if (buf[1] & 0x02) - zone->non_seq = 1; - - zone->len = logical_to_sectors(sdp, get_unaligned_be64(&buf[8])); - zone->start = logical_to_sectors(sdp, get_unaligned_be64(&buf[16])); - zone->wp = logical_to_sectors(sdp, get_unaligned_be64(&buf[24])); - if (zone->type != ZBC_ZONE_TYPE_CONV && - zone->cond == ZBC_ZONE_COND_FULL) - zone->wp = zone->start + zone->len; + zone.non_seq = 1; + + zone.len = logical_to_sectors(sdp, get_unaligned_be64(&buf[8])); + zone.start = logical_to_sectors(sdp, get_unaligned_be64(&buf[16])); + zone.wp = logical_to_sectors(sdp, get_unaligned_be64(&buf[24])); + if (zone.type != ZBC_ZONE_TYPE_CONV && + zone.cond == ZBC_ZONE_COND_FULL) + zone.wp = zone.start + zone.len; + + return cb(&zone, idx, data); } /** @@ -154,60 +147,61 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp, } /** - * sd_zbc_report_zones - Disk report zones operation. - * @disk: The target disk - * @sector: Start 512B sector of the report - * @zones: Array of zone descriptors - * @nr_zones: Number of descriptors in the array - * - * Execute a report zones command on the target disk. + * sd_zbc_zone_sectors - Get the device zone size in number of 512B sectors. + * @sdkp: The target disk */ +static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp) +{ + return logical_to_sectors(sdkp->device, sdkp->zone_blocks); +} + int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones) + unsigned int nr_zones, report_zones_cb cb, void *data) { struct scsi_disk *sdkp = scsi_disk(disk); - unsigned int i, nrz = *nr_zones; + unsigned int nr, i; unsigned char *buf; - size_t buflen = 0, offset = 0; - int ret = 0; + size_t offset, buflen = 0; + int zone_idx = 0; + int ret; if (!sd_is_zoned(sdkp)) /* Not a zoned device */ return -EOPNOTSUPP; - buf = sd_zbc_alloc_report_buffer(sdkp, nrz, &buflen); + buf = sd_zbc_alloc_report_buffer(sdkp, nr_zones, &buflen); if (!buf) return -ENOMEM; - ret = sd_zbc_do_report_zones(sdkp, buf, buflen, - sectors_to_logical(sdkp->device, sector), true); - if (ret) - goto out; + while (zone_idx < nr_zones && sector < get_capacity(disk)) { + ret = sd_zbc_do_report_zones(sdkp, buf, buflen, + sectors_to_logical(sdkp->device, sector), true); + if (ret) + goto out; + + offset = 0; + nr = min(nr_zones, get_unaligned_be32(&buf[0]) / 64); + if (!nr) + break; + + for (i = 0; i < nr && zone_idx < nr_zones; i++) { + offset += 64; + ret = sd_zbc_parse_report(sdkp, buf + offset, zone_idx, + cb, data); + if (ret) + goto out; + zone_idx++; + } - nrz = min(nrz, get_unaligned_be32(&buf[0]) / 64); - for (i = 0; i < nrz; i++) { - offset += 64; - sd_zbc_parse_report(sdkp, buf + offset, zones); - zones++; + sector += sd_zbc_zone_sectors(sdkp) * i; } - *nr_zones = nrz; - + ret = zone_idx; out: kvfree(buf); - return ret; } -/** - * sd_zbc_zone_sectors - Get the device zone size in number of 512B sectors. - * @sdkp: The target disk - */ -static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp) -{ - return logical_to_sectors(sdkp->device, sdkp->zone_blocks); -} - /** * sd_zbc_setup_zone_mgmt_cmnd - Prepare a zone ZBC_OUT command. The operations * can be RESET WRITE POINTER, OPEN, CLOSE or FINISH. diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1443cee15863..95761740cf1f 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2857,15 +2857,21 @@ static int init_percpu_info(struct f2fs_sb_info *sbi) } #ifdef CONFIG_BLK_DEV_ZONED +static int f2fs_report_zone_cb(struct blk_zone *zone, unsigned int idx, + void *data) +{ + struct f2fs_dev_info *dev = data; + + if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) + set_bit(idx, dev->blkz_seq); + return 0; +} + static int init_blkz_info(struct f2fs_sb_info *sbi, int devi) { struct block_device *bdev = FDEV(devi).bdev; sector_t nr_sectors = bdev->bd_part->nr_sects; - sector_t sector = 0; - struct blk_zone *zones; - unsigned int i, nr_zones; - unsigned int n = 0; - int err = -EIO; + int ret; if (!f2fs_sb_has_blkzoned(sbi)) return 0; @@ -2890,38 +2896,13 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi) if (!FDEV(devi).blkz_seq) return -ENOMEM; -#define F2FS_REPORT_NR_ZONES 4096 - - zones = f2fs_kzalloc(sbi, - array_size(F2FS_REPORT_NR_ZONES, - sizeof(struct blk_zone)), - GFP_KERNEL); - if (!zones) - return -ENOMEM; - /* Get block zones type */ - while (zones && sector < nr_sectors) { - - nr_zones = F2FS_REPORT_NR_ZONES; - err = blkdev_report_zones(bdev, sector, zones, &nr_zones); - if (err) - break; - if (!nr_zones) { - err = -EIO; - break; - } - - for (i = 0; i < nr_zones; i++) { - if (zones[i].type != BLK_ZONE_TYPE_CONVENTIONAL) - set_bit(n, FDEV(devi).blkz_seq); - sector += zones[i].len; - n++; - } - } - - kvfree(zones); + ret = blkdev_report_zones(bdev, 0, BLK_ALL_ZONES, f2fs_report_zone_cb, + &FDEV(devi)); + if (ret < 0) + return ret; - return err; + return 0; } #endif diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index dbef541c2530..17e384aa5a94 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -349,17 +349,16 @@ struct queue_limits { enum blk_zoned_model zoned; }; +typedef int (*report_zones_cb)(struct blk_zone *zone, unsigned int idx, + void *data); + #ifdef CONFIG_BLK_DEV_ZONED -/* - * Maximum number of zones to report with a single report zones command. - */ -#define BLK_ZONED_REPORT_MAX_ZONES 8192U +#define BLK_ALL_ZONES ((unsigned int)-1) +int blkdev_report_zones(struct block_device *bdev, sector_t sector, + unsigned int nr_zones, report_zones_cb cb, void *data); extern unsigned int blkdev_nr_zones(struct block_device *bdev); -extern int blkdev_report_zones(struct block_device *bdev, - sector_t sector, struct blk_zone *zones, - unsigned int *nr_zones); extern int blkdev_zone_mgmt(struct block_device *bdev, enum req_opf op, sector_t sectors, sector_t nr_sectors, gfp_t gfp_mask); @@ -1710,7 +1709,7 @@ struct block_device_operations { /* this callback is with swap_lock and sometimes page table lock held */ void (*swap_slot_free_notify) (struct block_device *, unsigned long); int (*report_zones)(struct gendisk *, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones); + unsigned int nr_zones, report_zones_cb cb, void *data); struct module *owner; const struct pr_ops *pr_ops; }; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 399ad8632356..a164cc81b710 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -17,6 +17,7 @@ struct dm_dev; struct dm_target; struct dm_table; +struct dm_report_zones_args; struct mapped_device; struct bio_vec; @@ -93,9 +94,9 @@ typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv, typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti, struct block_device **bdev); -typedef int (*dm_report_zones_fn) (struct dm_target *ti, sector_t sector, - struct blk_zone *zones, - unsigned int *nr_zones); +typedef int (*dm_report_zones_fn) (struct dm_target *ti, + struct dm_report_zones_args *args, + unsigned int nr_zones); /* * These iteration functions are typically used to check (and combine) @@ -422,10 +423,23 @@ struct gendisk *dm_disk(struct mapped_device *md); int dm_suspended(struct dm_target *ti); int dm_noflush_suspending(struct dm_target *ti); void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors); -void dm_remap_zone_report(struct dm_target *ti, sector_t start, - struct blk_zone *zones, unsigned int *nr_zones); union map_info *dm_get_rq_mapinfo(struct request *rq); +#ifdef CONFIG_BLK_DEV_ZONED +struct dm_report_zones_args { + struct dm_target *tgt; + sector_t next_sector; + + void *orig_data; + report_zones_cb orig_cb; + unsigned int zone_idx; + + /* must be filled by ->report_zones before calling dm_report_zones_cb */ + sector_t start; +}; +int dm_report_zones_cb(struct blk_zone *zone, unsigned int idx, void *data); +#endif /* CONFIG_BLK_DEV_ZONED */ + /* * Device mapper functions to parse and create devices specified by the * parameter "dm-mod.create="