From patchwork Wed Aug 24 20:25:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shaun Tancheff X-Patchwork-Id: 9298277 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 B9684608A7 for ; Wed, 24 Aug 2016 20:25:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A8E6C2910C for ; Wed, 24 Aug 2016 20:25:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 93CD52910E; Wed, 24 Aug 2016 20:25:56 +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=unavailable 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 F007F2910E for ; Wed, 24 Aug 2016 20:25:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755878AbcHXUZz (ORCPT ); Wed, 24 Aug 2016 16:25:55 -0400 Received: from mail-it0-f66.google.com ([209.85.214.66]:34166 "EHLO mail-it0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755865AbcHXUZw (ORCPT ); Wed, 24 Aug 2016 16:25:52 -0400 Received: by mail-it0-f66.google.com with SMTP id e63so3563613ith.1; Wed, 24 Aug 2016 13:25:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=i/GWQlxRo2ZG3c8u9f4MBVMq+VFCb+jlDQZj2WEOCM8=; b=zupjd4UykPJ+iiBD5pQozp1Y4RXQyO4dhnSJOVkHslPOh1MpavnsJp8QbGzXkRgFjr d3GXyqitHGBXAZD8BZbx5+67Q7WX0dF3l6j96dC6xObQ6MduBa5nMCraZL6ofBERYKQg jd8Hf5K27lBLelI5DzJhB7gtjiaS52quB6mGLY683Q7zWt36zpWlYoLBXE3lFtNOky7A gZkJKBRlxdN/+d8X5aL6hlfWRAzrSNbfNpzRqFAW7vSNvV1L1NRDdAFLsxdOXkhqtoRs ibgCqZd1uvF4xQFV+ax2IHVn1eBSAjNbnfvuSUfzmXuSnS09ROJBESYV7aW0lvmohOsO d/Yw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=i/GWQlxRo2ZG3c8u9f4MBVMq+VFCb+jlDQZj2WEOCM8=; b=NMfX2RUD0sTS9JPi6rAjl8j13myx+cKhjIypFe8SVzpzu3NwDPIoIkqECLIqHkOv9V FRsZaL2UbCNKur43cKzR6gqpxgnyo1a+qntZPgVYIy/DS7BTVQdj+5+r6jE0z+dQPpl1 2xbpK21h46ztw/THwOi61SAsPVFTkJy+TLTuH6nTL+thaaGdwbqF+9AkZ0G3aIyQKwzP ZHMwfxmE1NGqANtWn4rW3+hIxiDWcBeLzciweYNeW8BW4zPOwgyENadl7ePi6VMjsJ/p HBtqfCNOhggpr5AB3hV5VJr/AeASMGddrbiIliKD+xEwKDoW7awCNOwjlNDu+bTugXex KBqw== X-Gm-Message-State: AEkoousE29XPLSZqyd9xoNPf6f9X7te2msdwIcjAqi2Ph5h18ZiyN03+y9o9XSArAxdxSQ== X-Received: by 10.36.213.131 with SMTP id a125mr957756itg.14.1472070342381; Wed, 24 Aug 2016 13:25:42 -0700 (PDT) Received: from helios.aeonazure.com (173-16-223-93.client.mchsi.com. [173.16.223.93]) by smtp.gmail.com with ESMTPSA id r188sm12305033ith.7.2016.08.24.13.25.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Aug 2016 13:25:41 -0700 (PDT) From: Shaun Tancheff To: linux-block@vger.kernel.org, linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Shaun Tancheff , Jens Axboe , Christoph Hellwig , "James E . J . Bottomley" , "Martin K . Petersen" , Damien Le Moal , Hannes Reinecke , Josh Bingaman , "David S . Miller" , Geert Uytterhoeven , Andrew Morton , Greg Kroah-Hartman , Mauro Carvalho Chehab , Guenter Roeck , Ming Lei , Mike Christie , Keith Busch , Mike Snitzer , Johannes Thumshirn , Shaohua Li , Dan Williams , Sagi Grimberg , stephen hemminger , Jarkko Sakkinen , Alexandre Bounine , Asias He , Sabrina Dubroca , Mike Frysinger , Andrea Arcangeli , Linus Walleij , Jeff Layton , "J . Bruce Fields" , linux-f2fs-devel@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, dm-devel@redhat.com, Jaegeuk Kim , Shaun Tancheff Subject: [PATCH v8 2/2 RESEND] Add ioctl to issue ZBC/ZAC commands via block layer Date: Wed, 24 Aug 2016 15:25:37 -0500 Message-Id: <20160824202537.30415-1-shaun@tancheff.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20160822042010.32416-3-shaun@tancheff.com> References: <20160822042010.32416-3-shaun@tancheff.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP (RESENDING to include f2fs, fs-devel and dm-devel) Add support for ZBC ioctl's BLKREPORT - Issue Report Zones to device. BLKZONEACTION - Issue a Zone Action (Close, Finish, Open, or Reset) Signed-off-by: Shaun Tancheff --- v8: - Changed ioctl for zone actions to a single ioctl that takes a structure including the zone, zone action, all flag, and force option - Mapped REQ_META flag to 'force unit access' for zone operations v6: - Added GFP_DMA to gfp mask. v4: - Rebase on linux-next tag next-20160617. - Change bio flags to bio op's block/ioctl.c | 149 ++++++++++++++++++++++++++++++++++++++ include/uapi/linux/blkzoned_api.h | 30 +++++++- include/uapi/linux/fs.h | 1 + 3 files changed, 179 insertions(+), 1 deletion(-) diff --git a/block/ioctl.c b/block/ioctl.c index ed2397f..d760523 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -194,6 +194,151 @@ int blkdev_reread_part(struct block_device *bdev) } EXPORT_SYMBOL(blkdev_reread_part); +static int blk_zoned_report_ioctl(struct block_device *bdev, fmode_t mode, + void __user *parg) +{ + int error = -EFAULT; + gfp_t gfp = GFP_KERNEL | GFP_DMA; + void *iopg = NULL; + struct bdev_zone_report_io *bzrpt = NULL; + int order = 0; + struct page *pgs = NULL; + u32 alloc_size = PAGE_SIZE; + unsigned int op_flags = 0; + u8 opt = 0; + + if (!(mode & FMODE_READ)) + return -EBADF; + + iopg = (void *)get_zeroed_page(gfp); + if (!iopg) { + error = -ENOMEM; + goto report_zones_out; + } + bzrpt = iopg; + if (copy_from_user(bzrpt, parg, sizeof(*bzrpt))) { + error = -EFAULT; + goto report_zones_out; + } + if (bzrpt->data.in.return_page_count > alloc_size) { + int npages; + + alloc_size = bzrpt->data.in.return_page_count; + npages = (alloc_size + PAGE_SIZE - 1) >> PAGE_SHIFT; + pgs = alloc_pages(gfp, ilog2(npages)); + if (pgs) { + void *mem = page_address(pgs); + + if (!mem) { + error = -ENOMEM; + goto report_zones_out; + } + order = ilog2(npages); + memset(mem, 0, alloc_size); + memcpy(mem, bzrpt, sizeof(*bzrpt)); + bzrpt = mem; + } else { + /* Result requires DMA capable memory */ + pr_err("Not enough memory available for request.\n"); + error = -ENOMEM; + goto report_zones_out; + } + } else { + alloc_size = bzrpt->data.in.return_page_count; + } + if (bzrpt->data.in.force_unit_access) + op_flags |= REQ_META; + opt = bzrpt->data.in.report_option; + error = blkdev_issue_zone_report(bdev, op_flags, + bzrpt->data.in.zone_locator_lba, opt, + pgs ? pgs : virt_to_page(iopg), + alloc_size, GFP_KERNEL); + if (error) + goto report_zones_out; + + if (pgs) { + void *src = bzrpt; + u32 off = 0; + + /* + * When moving a multi-order page with GFP_DMA + * the copy to user can trap "" + * so instead we copy out 1 page at a time. + */ + while (off < alloc_size && !error) { + u32 len = min_t(u32, PAGE_SIZE, alloc_size - off); + + memcpy(iopg, src + off, len); + if (copy_to_user(parg + off, iopg, len)) + error = -EFAULT; + off += len; + } + } else { + if (copy_to_user(parg, iopg, alloc_size)) + error = -EFAULT; + } + +report_zones_out: + if (pgs) + __free_pages(pgs, order); + if (iopg) + free_page((unsigned long)iopg); + return error; +} + +static int blk_zoned_action_ioctl(struct block_device *bdev, fmode_t mode, + void __user *parg) +{ + unsigned int op = 0; + unsigned int op_flags = 0; + sector_t lba; + struct bdev_zone_action za; + + if (!(mode & FMODE_WRITE)) + return -EBADF; + + /* When acting on zones we explicitly disallow using a partition. */ + if (bdev != bdev->bd_contains) { + pr_err("%s: All zone operations disallowed on this device\n", + __func__); + return -EFAULT; + } + + if (copy_from_user(&za, parg, sizeof(za))) + return -EFAULT; + + switch (za.action) { + case ZONE_ACTION_CLOSE: + op = REQ_OP_ZONE_CLOSE; + break; + case ZONE_ACTION_FINISH: + op = REQ_OP_ZONE_FINISH; + break; + case ZONE_ACTION_OPEN: + op = REQ_OP_ZONE_OPEN; + break; + case ZONE_ACTION_RESET: + op = REQ_OP_ZONE_RESET; + break; + default: + pr_err("%s: Unknown action: %u\n", __func__, za.action); + return -EINVAL; + } + + lba = za.zone_locator_lba; + if (za.all_zones) { + if (lba) { + pr_err("%s: if all_zones, LBA must be 0.\n", __func__); + return -EINVAL; + } + lba = ~0ul; + } + if (za.force_unit_access || lba == ~0ul) + op_flags |= REQ_META; + + return blkdev_issue_zone_action(bdev, op, op_flags, lba, GFP_KERNEL); +} + static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode, unsigned long arg, unsigned long flags) { @@ -568,6 +713,10 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, case BLKTRACESETUP: case BLKTRACETEARDOWN: return blk_trace_ioctl(bdev, cmd, argp); + case BLKREPORT: + return blk_zoned_report_ioctl(bdev, mode, argp); + case BLKZONEACTION: + return blk_zoned_action_ioctl(bdev, mode, argp); case IOC_PR_REGISTER: return blkdev_pr_register(bdev, argp); case IOC_PR_RESERVE: diff --git a/include/uapi/linux/blkzoned_api.h b/include/uapi/linux/blkzoned_api.h index d2bdba5..cd81a9f 100644 --- a/include/uapi/linux/blkzoned_api.h +++ b/include/uapi/linux/blkzoned_api.h @@ -115,6 +115,7 @@ enum bdev_zone_same { * @zone_locator_lba: starting lba for first [reported] zone * @return_page_count: number of *bytes* allocated for result * @report_option: see: zone_report_option enum + * @force_unit_access: Force report from media * * Used to issue report zones command to connected device */ @@ -122,6 +123,25 @@ struct bdev_zone_get_report { __u64 zone_locator_lba; __u32 return_page_count; __u8 report_option; + __u8 force_unit_access; +} __packed; + +/** + * struct bdev_zone_action - ioctl: Perform Zone Action + * + * @zone_locator_lba: starting lba for first [reported] zone + * @return_page_count: number of *bytes* allocated for result + * @action: One of the ZONE_ACTION_*'s Close,Finish,Open, or Reset + * @all_zones: Flag to indicate if command should apply to all zones. + * @force_unit_access: Force command to media and update zone cache on success + * + * Used to issue report zones command to connected device + */ +struct bdev_zone_action { + __u64 zone_locator_lba; + __u32 action; + __u8 all_zones; + __u8 force_unit_access; } __packed; /** @@ -134,7 +154,6 @@ struct bdev_zone_get_report { * @lba_start: lba where the zone starts. * @lba_wptr: lba of the current write pointer. * @reserved: padding - * */ struct bdev_zone_descriptor { __u8 type; @@ -179,4 +198,13 @@ struct bdev_zone_report_io { } data; } __packed; +/* continuing from uapi/linux/fs.h: */ +#define BLKREPORT _IOWR(0x12, 130, struct bdev_zone_report_io) +#define BLKZONEACTION _IOW(0x12, 131, struct bdev_zone_action) + +#define ZONE_ACTION_CLOSE 0x01 +#define ZONE_ACTION_FINISH 0x02 +#define ZONE_ACTION_OPEN 0x03 +#define ZONE_ACTION_RESET 0x04 + #endif /* _UAPI_BLKZONED_API_H */ diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 3b00f7c..350fb3f2 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -222,6 +222,7 @@ struct fsxattr { #define BLKSECDISCARD _IO(0x12,125) #define BLKROTATIONAL _IO(0x12,126) #define BLKZEROOUT _IO(0x12,127) +/* A jump here: See blkzoned_api.h, Reserving 130 and 131. */ #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ #define FIBMAP _IO(0x00,1) /* bmap access */