From patchwork Mon Sep 26 11:14:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 9350497 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 949A86077A for ; Mon, 26 Sep 2016 11:15:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 84C8528AAE for ; Mon, 26 Sep 2016 11:15:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7893D28AD4; Mon, 26 Sep 2016 11:15:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 95C7328AB4 for ; Mon, 26 Sep 2016 11:15:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965622AbcIZLP3 (ORCPT ); Mon, 26 Sep 2016 07:15:29 -0400 Received: from esa2.hgst.iphmx.com ([68.232.143.124]:54467 "EHLO esa2.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934759AbcIZLPS (ORCPT ); Mon, 26 Sep 2016 07:15:18 -0400 X-IronPort-AV: E=Sophos;i="5.30,399,1470672000"; d="scan'208";a="18123042" Received: from mail-cys01nam02lp0056.outbound.protection.outlook.com (HELO NAM02-CY1-obe.outbound.protection.outlook.com) ([207.46.163.56]) by ob1.hgst.iphmx.com with ESMTP; 26 Sep 2016 19:15:17 +0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sharedspace.onmicrosoft.com; s=selector1-hgst-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=2NuH9/KtfWSnitb6N2vcnuREpvvkbonUSI2hLwTMKTI=; b=qGB7ppuejERFuL7NlwElh2qOJxhrTpemTeE6MANzKjjX1SLxDgAlDpm1H6LtnLqqK0GgPuvio1u9vwiutLz2617w77lNReiQnuLfsSZKCSUDdYxkmOnJQJaLQm1hPf+bnKS2sg776E7cukH+l7HJ0sfZ227JPQU6AQSC0mNQ5i8= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Damien.LeMoal@hgst.com; Received: from washi.fujisawa.hgst.com (199.255.47.8) by BY2PR04MB1976.namprd04.prod.outlook.com (10.166.111.16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.639.5; Mon, 26 Sep 2016 11:15:14 +0000 From: Damien Le Moal To: Jens Axboe CC: , , Christoph Hellwig , "Martin K . Petersen" , Hannes Reinecke , Damien Le Moal Subject: [PATCH v2 5/7] block: Implement support for zoned block devices Date: Mon, 26 Sep 2016 20:14:41 +0900 Message-ID: <1474888483-29762-6-git-send-email-damien.lemoal@hgst.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1474888483-29762-1-git-send-email-damien.lemoal@hgst.com> References: <1474888483-29762-1-git-send-email-damien.lemoal@hgst.com> MIME-Version: 1.0 X-Originating-IP: [199.255.47.8] X-ClientProxiedBy: BY1PR0201CA0007.namprd02.prod.outlook.com (10.160.191.145) To BY2PR04MB1976.namprd04.prod.outlook.com (10.166.111.16) X-MS-Office365-Filtering-Correlation-Id: 14b8760d-e03f-4536-d006-08d3e5fe6441 X-Microsoft-Exchange-Diagnostics: 1; BY2PR04MB1976; 2:7fy8wyGLsXQ4R5152Fiwm1HTUXS4sxEAYJhkD6BhYkxhSo/Kz1QIsYVMOKvwZvksAoLPx/7culzEGLQEaGLZXcc8FHGBUJSvrgcOygVPxDxUT0gOi8Y+qXRmu/Woi9F5WTViVaPT4lxuWlAThL0OEbqPYHQnuZQIU3aOWbwmv7TL5m+ioFQAOXBNbD43rfXb; 3:o3hoeYKghSrf7jRYRzxz389OSV/3qop6dG7iXlDtDlLWKlB8h+akcVqfAg4s/7Uac23Xk0/zKct5HWhVEt36fENirOsYvfCELal9M/YARNt0EyMmUpRJbx+q8fUiehvy X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2PR04MB1976; X-Microsoft-Exchange-Diagnostics: 1; BY2PR04MB1976; 25:URjGPCo15QeObUhMOcERZFSWZzDA0qZUt7XG2u6mKfCyxoaAO/gYkxn1DO/LO7p2JohntA3b5WcP/9G61jkppOtPuhnBYlOWPO9QE1teg+gIWstjYxk4LzdLt/us2iZh/L8P4e9lw2hCNfbKqkezCXxkAdNU9tU1ELeuCOBIGzWDF1NaTum6owGiXOH9l27zNfaZOALc0eEWHNKLCxnAZJm7x2PDBXz+neJP/e0Lb2aFMum3gT/8Lr4CixNsTvIqrsX3fQw4t28wHyGRLnuG0vHmya4LwTBXqJzzIY8kwL3uFcf6t1Iqk3acrYipr86nMoVEN1FJOwtvs+xKbX8rQ4mlL8h8pldVrR92qHmJLXjLfOWKBbC5PplB3QsyEfdr44j6QzavgHUHJHcmdAIeya+00+GS4LQqxFL7QfB7+nJjhhx2HYdQvJv8uyLurDxlVnwifmn2Rhl/srYtHydPpFcBWdle+ukaRx4ML6JpIah97SKKg/QMsuBBPwKpXoiMPaJghRmT/VaB60jQR3GmLzW2+80jH7gncdYLiDag25vEVwtCNXetfm2Tvy2lOQ8rIplVMZ+TRswRQfQTVACGmClhtZ/dlLAefDdWiWsZiW60iFrI/iMdTUiwYXX66sws24fo/1J+6DLpV8NMiZkphaX77xvaKmdoIyeSKaZ3tGn6RWcMMoXzRkkxAwH9GEC+o6PdDiS8BSHfsJ0xtUz4Hh8sCnn4f0aoYssjRutTJ7U= X-Microsoft-Exchange-Diagnostics: 1; BY2PR04MB1976; 31:6VVZv1bJi+xxbVu06E0qnhVFl+piZBIPVPSDPZiFrckUDwEA3yeaGAJyETGl812I026RSqdprkNe5P5FccFTIiLojz1KIxaEsuV/vIEZ9de1Z0d6Q30dsz1E97bCpRcymWA8ptOGRpIo7/JXJsKYoRg17qIwXD7eBN+rPWEfXCt1vUKxsuAbn+MwIXHmjKUdeKzub7zu/gJyfMZTAayQe0UWvM5ytYLJ1kpqlzXQ0kM=; 20:Exfw01LqmXiPkXlRwLzJl4RNxzG0/5f93x4JIdQOm8Vtlj/zuFsxPm8JCHlbgYsiGOTdzI7nLbdnW4YE/wSDzban3plHO3wpkC5tBapd9qcJYHsGR2zb6PSR/XqBs/jILoMrsTHOOWzM/8gDHDgotaGHod4FiwoASDR6lMyW58KEbyg0ZAUwVdTUPevv0fsDJHplFI4kRDbbHpNnfjQ4lMu2M8T6fQmsC3bDmxZFASUoZdqSUO2nxMynr7KR/R//i6+RVosYhZyX5ic4dGl8IGPz3C7dvyWtqOdzgONlfq4EDdaXhmAC+JqQ5ZGMjxeb+/x8Ui0WOqjyo/+V9pNjfm0hH+4eOrJsON38TVFhl4wqebjHxDK91/nI85NCQ5OnGjVZw1koHle/sbiKW/A4wp6aQbAzAx+FoW0nc6oM9b1o5mt4Fhjf/YBBaw6DVVzeXqAziJR8ECZNJpSYrt86c+y1dfuipz/CXzkn46S/xA60NDqZ+cmWXMMnrfRXZlpd X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(79135771888625)(211171220733660); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(5005006)(8121501046)(3002001)(10201501046)(6055026); SRVR:BY2PR04MB1976; BCL:0; PCL:0; RULEID:; SRVR:BY2PR04MB1976; X-Microsoft-Exchange-Diagnostics: 1; BY2PR04MB1976; 4:vhwbfTfKJaq/i8Urqwfv7tsm43aAY1h0Q+k2sPTQiwYIuy6JiDadORBjGZk7bQxs9HM6L4dDsw+JdYO0EPvIfm4T3SqTvFO5Ku56mjBWH5bLnUiudmW0uO2zH/C+YZYL+GviiewUV2cNgY1gTJmUY34S4GGCkjFANJgWidDQISfDVfKVEW7bIzqqFDXFMpivyO4L1oaOXbaRwtpkDtpKj8/0pSu6m54tWeQ6KCTdpxO2VmUnXpGKtROf+RcrCp8258FVPT75gIBMgyGO4TFHNqA8Q/Z6rH1UBmlFMg1ih2/ftKWXAjYkgm4H2ZTFN+SOW1OWDV2VBQWkru/T5uOImNCMwTepGQoo+qsAFc6avyv29AEc1p2ejPAVbZZgbFZLPTl69sTnDsUFPYeGMLWwXOx0Eyw5ZU/3JhXxyWd1s8OEhA1MuvqPQN2Iy1SleQmaP/4TF9Nv4q918DQnv4AvtXhRotRpCghdPiQ+AP/h8J0= X-Forefront-PRVS: 00770C4423 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(7916002)(189002)(199003)(50944005)(2950100002)(77096005)(6916009)(575784001)(36756003)(86362001)(50466002)(101416001)(107886002)(4001430100002)(97736004)(561944003)(2906002)(50226002)(189998001)(68736007)(4326007)(19580405001)(50986999)(229853001)(66066001)(586003)(47776003)(7846002)(81166006)(81156014)(7736002)(106356001)(92566002)(305945005)(110136003)(5003940100001)(3846002)(48376002)(8676002)(105586002)(76176999)(5660300001)(33646002)(19580395003)(6116002)(42186005)(7099028); DIR:OUT; SFP:1102; SCL:1; SRVR:BY2PR04MB1976; H:washi.fujisawa.hgst.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: hgst.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR04MB1976; 23:siYA+7FH0dVzAtxo11E7W31Ofu60P7ruB1EmTAguZ?= =?us-ascii?Q?vKK3uVlmtZmCwdQMo1eYpvmDIcVivoKWKxnCTEAzbO37zRljA9wCLg/LcSME?= =?us-ascii?Q?phv4RgtunJW3A/XJnzLaoZ+GhjCL+t5ybeoh6Pk9Yh37t3q/ABu89FAtbBS8?= =?us-ascii?Q?fVFLa1P12ttis3CaeklLlSkhIjvuw3GCwpBx241i3McbZgR2JJWxCmTZ91LK?= =?us-ascii?Q?bQCmzPUjEJQpUQLXQbjL3T89hCrppF/sZIjnopRfXuIvx7FGILcJLw3+lpdb?= =?us-ascii?Q?NtIt7q5i/qNskEdRdAG5r/CG5c0JgQpaogylW2JjvV7PQgza5v9+H6ewh/Dj?= =?us-ascii?Q?QbjU3Z6EdgnLLksaTa23Q8BCXFKyYzJyI9/F7WY3TDXXmaG6A77gc4Jte+vG?= =?us-ascii?Q?TYWrkTrQtofPJ0AwoJWyCGr53ErAvin+9sejaMr28OJ564PHnp1jFE1iQ2xX?= =?us-ascii?Q?JUHm+0CAVdom2Y4zaaA30UQfIDMLWxqZBZbv9pkY0V6CcO+2jDHJCEa+hO6Q?= =?us-ascii?Q?H7d8gP3MAOoJnIoejv5B3+7GOr/zKHsur6XQyJiSCVk/7U0HIQjaN2Lrb4Td?= =?us-ascii?Q?+xVx2x9JXxiMrcsLZ1/b1xYDyIxg+p802YBsdhTmMCXwwdpy42PZrHFqeJyI?= =?us-ascii?Q?J0r5LqVcJDV+im7AqqOTXajxqh+NIZtB3jLzbs2btajFg4aDt33RRQi5Na7F?= =?us-ascii?Q?Hy1ZruqRKhIaANBNoEfsnBcecEtJ97zP7qk2oay4N2Q6+K7N4c6au73BlM39?= =?us-ascii?Q?g80FAgb68WfHR0o5zRAw/xlb1mcvxBF56J7re3f0CpG9hZY0rF0A7nWZU1bc?= =?us-ascii?Q?NpkNaEKc95qE2KEUP2urzi42RNjndE8kRwJUfn2yqyWF/OGAY+pUP2mu015k?= =?us-ascii?Q?i+c32VFzhRdRAZ0HHlNZaIjv1gYz+IQkk8wkxf9opSWwEAxCCefFqRy6f97e?= =?us-ascii?Q?chncRFLRlfW3Kff5+scMxXOnEyfBZVEVb2VmGuINItBEWNT51VMxCvVUHH2v?= =?us-ascii?Q?iCJfDX4AZZKJyVlufND3MmO+2/Sy48I/vsY8/cjljlHOrXVbPQnFxbEPA1aa?= =?us-ascii?Q?HIPdXFZRZjYKxG36RgAIraQtIDmY+1hTPddYaONHKNhy0lu1PFN3i0svi3Ec?= =?us-ascii?Q?CfsrxdooWx0RfRumxNH87F5tRvMjwPCLuXlHruHq2uN1ILft6NKNLw9BKU93?= =?us-ascii?Q?ow7FXqYK1G/MMGlvTrYfb7LOrKlhXhNF9ET?= X-Microsoft-Exchange-Diagnostics: 1; BY2PR04MB1976; 6:sVxQpgQNLH2wl2jYXklZ8M+i47/6Ekb7Vipo98VrD2KOUafS7M5zuquz3ZSTZhiD7bhCZHBm9MlJ3MKWpfLGLH5quEJzUh2NCCNg4CMgccAqUuEYNYVLyuX1k8XLvMYap3QWHSx0vImRCXwxy09PX8lMwqNMdMXvWMMhzbsfgv9SVPHQE4d9ETsx8xJzKrOoFpfKKtELFkOObKyuwC6w5wmxNK05eflhF2/JR9QMQnc0PwvFIdLFYa8cOTd9aW+9aCRgOqzRBe4bOWnw0vWzmiMhP5tV0IpI4faUmdO8fkk7Nnp05DN1JQTPxOxChh5kfqvnLjmMAvw/nMnvEDWMtA==; 5:3oObIx84HKQXtVIpO9m4whWIlYDSfQ1dJSsdPhstq5EbpiIYndZE940WzxCdpsPkyqvMmHgfDCSnOB5yp2sF61a2x/ORyYUL+iM0/vpc3xNcl28TCYBl+6cbVBY+9GUspoBiS++tB08f5FrUi154fg==; 24:dLwH30HwYuAT7X65UxOP7m8WfdI/ZScJmtMmRnPZPiRXmfCLOS3X9GNJVH55d/JB6t3dad9HbVGbPCq/s5IFno+/+Hutuytx236k+GG93F4=; 7:ehUsOXK7/Z7sePxV26+V6qOqi/Y8OORY9TCcypXQXekWdCnDhDjjhEQDU2R5iFagqDNQEmcP4Zno4FV30EJh+1fZQjYJIG2TAwc77IZEUn+xUa9gZUEKe8HSaHXnFX2xs//8fcEsWOQhhIL1++6Pw4yarrhJCpnwn6QXwJB437NCa4TQUUIy8WmtOzxU/8YQdc080VuSlQKimoLdn6Uan0O/QVgohNoBCz/JSpCcbvEdzsLhFFCct+R6nuD8xNRYEgSBKtQiTf5xC0nR0PNxmnFF2yGSdYxmn4qs8ZYkFCIhjUvp341oMsRLJ2MkH51i SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BY2PR04MB1976; 20:pKskzGRgEzGvd33vF0YH/jiFx+SUtVwqsoo8TEj6rR/Msj/N5TfNHN8mWeTF3X4PX0al25+S2u3D752yl1AV1LgqgD8jqIOJhz5leydwnBqLni3kEKgJ/MmVCzxwpEPvNZT/iOhNFBIPsibnSx4N1UFK+iHAvWnPcHKp9QvWmb512EEwBo2bbIbr+u/194C7EPgz46EwQEt2dKKOTuliUszLNXBMpHg52NC1nKYEMxxyaeZqtAfnctUTyZn9wnaQ X-OriginatorOrg: hgst.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Sep 2016 11:15:14.5041 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR04MB1976 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Hannes Reinecke Implement zoned block device zone information reporting and reset. Zone information are reported as struct blk_zone. This implementation does not differentiate between host-aware and host-managed device models and is valid for both. Two functions are provided: blkdev_report_zones for discovering the zone configuration of a zoned block device, and blkdev_reset_zones for resetting the write pointer of sequential zones. The helper function blk_queue_zone_size and bdev_zone_size are also provided for, as the name suggest, obtaining the zone size (in 512B sectors) of the zones of the device. Signed-off-by: Hannes Reinecke [Damien: * Removed the zone cache * Implement report zones operation based on earlier proposal by Shaun Tancheff ] Signed-off-by: Damien Le Moal --- block/Kconfig | 8 ++ block/Makefile | 1 + block/blk-zoned.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/blkdev.h | 71 +++++++++++++++ 4 files changed, 320 insertions(+) create mode 100644 block/blk-zoned.c diff --git a/block/Kconfig b/block/Kconfig index 1d4d624..6b0ad08 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -89,6 +89,14 @@ config BLK_DEV_INTEGRITY T10/SCSI Data Integrity Field or the T13/ATA External Path Protection. If in doubt, say N. +config BLK_DEV_ZONED + bool "Zoned block device support" + ---help--- + Block layer zoned block device support. This option enables + support for ZAC/ZBC host-managed and host-aware zoned block devices. + + Say yes here if you have a ZAC or ZBC storage device. + config BLK_DEV_THROTTLING bool "Block layer bio throttling support" depends on BLK_CGROUP=y diff --git a/block/Makefile b/block/Makefile index 36acdd7..9371bc7 100644 --- a/block/Makefile +++ b/block/Makefile @@ -22,4 +22,5 @@ obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o +obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned.o obj-$(CONFIG_BLK_MQ_PCI) += blk-mq-pci.o diff --git a/block/blk-zoned.c b/block/blk-zoned.c new file mode 100644 index 0000000..473cb0a --- /dev/null +++ b/block/blk-zoned.c @@ -0,0 +1,240 @@ +/* + * Zoned block device handling + * + * Copyright (c) 2015, Hannes Reinecke + * Copyright (c) 2015, SUSE Linux GmbH + * + * Copyright (c) 2016, Damien Le Moal + * Copyright (c) 2016, Western Digital + */ + +#include +#include +#include +#include + +static inline sector_t blk_zone_start(struct request_queue *q, + sector_t sector) +{ + sector_t zone_mask = blk_queue_zone_size(q) - 1; + + return sector & ~zone_mask; +} + +static inline void blkdev_report_to_zone(struct block_device *bdev, + void *rep, + struct blk_zone *zone) +{ + sector_t offset = get_start_sect(bdev); + + memcpy(zone, rep, sizeof(struct blk_zone)); + zone->start -= offset; + if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) + zone->wp = zone->start + zone->len; + else + zone->wp -= offset; +} + +/** + * 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 + * @gfp_mask: Memory allocation flags (for bio_alloc) + * + * 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. + */ +int blkdev_report_zones(struct block_device *bdev, + sector_t sector, + struct blk_zone *zones, + unsigned int *nr_zones, + gfp_t gfp_mask) +{ + struct request_queue *q = bdev_get_queue(bdev); + struct blk_zone_report_hdr *hdr; + unsigned int nrz = *nr_zones; + struct page *page; + unsigned int nr_rep; + size_t rep_bytes; + unsigned int nr_pages; + struct bio *bio; + struct bio_vec *bv; + unsigned int i, nz; + unsigned int ofst; + void *addr; + int ret = 0; + + if (!q) + return -ENXIO; + + if (!blk_queue_is_zoned(q)) + return -EOPNOTSUPP; + + if (!nrz) + return 0; + + if (sector > bdev->bd_part->nr_sects) { + *nr_zones = 0; + return 0; + } + + /* + * The zone report has a header. So make room for it in the + * payload. Also make sure that the report fits in a single BIO + * that will not be split down the stack. + */ + rep_bytes = sizeof(struct blk_zone_report_hdr) + + sizeof(struct blk_zone) * nrz; + rep_bytes = (rep_bytes + PAGE_SIZE - 1) & PAGE_MASK; + if (rep_bytes > (queue_max_sectors(q) << 9)) + rep_bytes = queue_max_sectors(q) << 9; + + nr_pages = min_t(unsigned int, BIO_MAX_PAGES, + rep_bytes >> PAGE_SHIFT); + nr_pages = min_t(unsigned int, nr_pages, + queue_max_segments(q)); + + bio = bio_alloc(gfp_mask, nr_pages); + if (!bio) + return -ENOMEM; + + bio->bi_bdev = bdev; + bio->bi_iter.bi_sector = blk_zone_start(q, sector); + bio_set_op_attrs(bio, REQ_OP_ZONE_REPORT, 0); + + for (i = 0; i < nr_pages; i++) { + page = alloc_page(gfp_mask); + if (!page) { + ret = -ENOMEM; + goto out; + } + if (!bio_add_page(bio, page, PAGE_SIZE, 0)) { + __free_page(page); + break; + } + } + + if (i == 0) + ret = -ENOMEM; + else + ret = submit_bio_wait(bio); + if (ret) + goto out; + + /* + * Process the report resukt: skip the header and go through the + * reported zones to fixup and fixup the zone information for + * partitions. At the same time, return the zone information into + * the zone array. + */ + nz = 0; + nr_rep = 0; + bio_for_each_segment_all(bv, bio, i) { + + if (!bv->bv_page) + break; + + addr = kmap_atomic(bv->bv_page); + + /* Get header in the first page */ + ofst = 0; + if (!nr_rep) { + hdr = (struct blk_zone_report_hdr *) addr; + nr_rep = hdr->nr_zones; + ofst = sizeof(struct blk_zone_report_hdr); + } + + /* Fixup and report zones */ + while (ofst < bv->bv_len && + nz < min_t(unsigned int, nr_rep, nrz)) { + blkdev_report_to_zone(bdev, addr + ofst, &zones[nz]); + ofst += sizeof(struct blk_zone); + nz++; + } + + kunmap_atomic(addr); + + if (!nr_rep) + break; + + } + +out: + bio_for_each_segment_all(bv, bio, i) + __free_page(bv->bv_page); + bio_put(bio); + + if (ret == 0) + *nr_zones = nz; + + return ret; +} + +/** + * blkdev_reset_zones - Reset zones write pointer + * @bdev: Target block device + * @sector: Start sector of the first zone to reset + * @nr_sectors: Number of sectors, at least the length of one zone + * @gfp_mask: Memory allocation flags (for bio_alloc) + * + * Description: + * Reset the write pointer of the zones contained in the range + * @sector..@sector+@nr_sectors. Specifying the entire disk sector range + * is valid, but the specified range should not contain conventional zones. + */ +int blkdev_reset_zones(struct block_device *bdev, + sector_t sector, sector_t nr_sectors, + gfp_t gfp_mask) +{ + struct request_queue *q = bdev_get_queue(bdev); + sector_t zone_sectors; + sector_t end_sector = sector + nr_sectors; + struct bio *bio; + int ret; + + if (!q) + return -ENXIO; + + if (!blk_queue_is_zoned(q)) + return -EOPNOTSUPP; + + if (end_sector > bdev->bd_part->nr_sects) + /* Out of range */ + return -EINVAL; + + /* Check alignement (handle eventual smaller last zone) */ + zone_sectors = blk_queue_zone_size(q); + if (sector & (zone_sectors - 1)) + return -EINVAL; + + if ((nr_sectors & (zone_sectors - 1)) && + end_sector != bdev->bd_part->nr_sects) + return -EINVAL; + + while (sector < end_sector) { + + bio = bio_alloc(gfp_mask, 0); + bio->bi_iter.bi_sector = sector; + bio->bi_bdev = bdev; + bio_set_op_attrs(bio, REQ_OP_ZONE_RESET, 0); + + ret = submit_bio_wait(bio); + bio_put(bio); + + if (ret) + return ret; + + sector += zone_sectors; + + /* This may take a while, so be nice to others */ + cond_resched(); + + } + + return 0; +} diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index f19e16b..6034f38 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -302,6 +302,62 @@ struct queue_limits { enum blk_zoned_model zoned; }; +#ifdef CONFIG_BLK_DEV_ZONED + +/* + * Zone type. + */ +enum blk_zone_type { + BLK_ZONE_TYPE_UNKNOWN, + BLK_ZONE_TYPE_CONVENTIONAL, + BLK_ZONE_TYPE_SEQWRITE_REQ, + BLK_ZONE_TYPE_SEQWRITE_PREF, +}; + +/* + * Zone condition. + */ +enum blk_zone_cond { + BLK_ZONE_COND_NO_WP, + BLK_ZONE_COND_EMPTY, + BLK_ZONE_COND_IMP_OPEN, + BLK_ZONE_COND_EXP_OPEN, + BLK_ZONE_COND_CLOSED, + BLK_ZONE_COND_READONLY = 0xd, + BLK_ZONE_COND_FULL, + BLK_ZONE_COND_OFFLINE, +}; + +/* + * Zone descriptor for BLKREPORTZONE. + * start, len and wp use the regulare 512 B sector unit, + * regardless of the device logical block size. The overall + * structure size is 64 B to match the ZBC/ZAC defined zone descriptor + * and allow support for future additional zone information. + */ +struct blk_zone { + u64 start; /* Zone start sector */ + u64 len; /* Zone length in number of sectors */ + u64 wp; /* Zone write pointer position */ + u8 type; /* Zone type */ + u8 cond; /* Zone condition */ + u8 non_seq; /* Non-sequential write resources active */ + u8 reset; /* Reset write pointer recommended */ + u8 reserved[36]; +}; + +struct blk_zone_report_hdr { + unsigned int nr_zones; + u8 padding[60]; +}; + +extern int blkdev_report_zones(struct block_device *, + sector_t, struct blk_zone *, + unsigned int *, gfp_t); +extern int blkdev_reset_zones(struct block_device *, sector_t, + sector_t, gfp_t); +#endif /* CONFIG_BLK_DEV_ZONED */ + struct request_queue { /* * Together with queue_head for cacheline sharing @@ -654,6 +710,11 @@ static inline bool blk_queue_is_zoned(struct request_queue *q) } } +static inline unsigned int blk_queue_zone_size(struct request_queue *q) +{ + return blk_queue_is_zoned(q) ? q->limits.chunk_sectors : 0; +} + /* * We regard a request as sync, if either a read or a sync write */ @@ -1401,6 +1462,16 @@ static inline bool bdev_is_zoned(struct block_device *bdev) return false; } +static inline unsigned int bdev_zone_size(struct block_device *bdev) +{ + struct request_queue *q = bdev_get_queue(bdev); + + if (q) + return blk_queue_zone_size(q); + + return 0; +} + static inline int queue_dma_alignment(struct request_queue *q) { return q ? q->dma_alignment : 511;