Thread (18 messages) 18 messages, 4 authors, 2016-09-20

Re: [PATCH 9/9] blk-zoned: Add ioctl interface for zone operations

flat view

From: Shaun Tancheff <hidden>
Date: 2016-09-20 06:02:01
Also in: linux-scsi

On Mon, Sep 19, 2016 at 4:27 PM, Damien Le Moal [off-list ref] wr=
ote:
From: Shaun Tancheff <redacted>

Adds the new BLKUPDATEZONES, BLKREPORTZONE, BLKRESETZONE,
BLKOPENZONE, BLKCLOSEZONE and BLKFINISHZONE ioctls.

BLKREPORTZONE implementation uses the device queue zone RB-tree by
default and no actual command is issued to the device. If the
application needs access to the untracked zone attributes (non-seq
flag or reset recommended flag, offline or read-only zone condition,
etc), BLKUPDATEZONES must be issued first to force an update of the
cached zone information.

Changelog (Damien):
* Simplified blkzone descriptor (removed bit-fields and use CPU
  endianness)
* Changed report ioctl to operate on single zone instead of an
  array of blkzone structures.
I think something with this degree of changes from what
I posted should not include my signed-off-by.

I also really don't like forcing the reply to be a single zone. I
think the user should be able to ask for as many or as few as
they would like.
Signed-off-by: Shaun Tancheff <redacted>
Signed-off-by: Damien Le Moal <redacted>
---
 block/blk-zoned.c             | 115 ++++++++++++++++++++++++++++++++++++=
++++++
quoted hunk ↗ jump to hunk
 block/ioctl.c                 |   8 +++
 include/linux/blkdev.h        |   7 +++
 include/uapi/linux/Kbuild     |   1 +
 include/uapi/linux/blkzoned.h |  91 +++++++++++++++++++++++++++++++++
 include/uapi/linux/fs.h       |   1 +
 6 files changed, 223 insertions(+)
 create mode 100644 include/uapi/linux/blkzoned.h
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index a107940..71205c8 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/rbtree.h>
 #include <linux/blkdev.h>
+#include <linux/blkzoned.h>

 void blk_init_zones(struct request_queue *q)
 {
@@ -336,3 +337,117 @@ int blkdev_finish_zone(struct block_device *bdev,
        return blkdev_issue_zone_action(bdev, sector, REQ_OP_ZONE_FINISH,
                                        gfp_mask);
 }
+
+static int blkdev_report_zone_ioctl(struct block_device *bdev,
+                                   void __user *argp)
+{
+       struct blk_zone *zone;
+       struct blkzone z;
+
+       if (copy_from_user(&z, argp, sizeof(struct blkzone)))
+               return -EFAULT;
+
+       zone =3D blk_lookup_zone(bdev_get_queue(bdev), z.start);
+       if (!zone)
+               return -EINVAL;
+
+       memset(&z, 0, sizeof(struct blkzone));
+
+       blk_lock_zone(zone);
+
+       blk_wait_for_zone_update(zone);
+
+       z.len =3D zone->len;
+       z.start =3D zone->start;
+       z.wp =3D zone->wp;
+       z.type =3D zone->type;
+       z.cond =3D zone->cond;
+       z.non_seq =3D zone->non_seq;
+       z.reset =3D zone->reset;
+
+       blk_unlock_zone(zone);
+
+       if (copy_to_user(argp, &z, sizeof(struct blkzone)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int blkdev_zone_action_ioctl(struct block_device *bdev,
+                                   unsigned cmd, void __user *argp)
+{
+       unsigned int op;
+       u64 sector;
+
+       if (get_user(sector, (u64 __user *)argp))
+               return -EFAULT;
+
+       switch (cmd) {
+       case BLKRESETZONE:
+               op =3D REQ_OP_ZONE_RESET;
+               break;
+       case BLKOPENZONE:
+               op =3D REQ_OP_ZONE_OPEN;
+               break;
+       case BLKCLOSEZONE:
+               op =3D REQ_OP_ZONE_CLOSE;
+               break;
+       case BLKFINISHZONE:
+               op =3D REQ_OP_ZONE_FINISH;
+               break;
+       }
+
+       return blkdev_issue_zone_action(bdev, sector, op, GFP_KERNEL);
+}
+
+/**
+ * Called from blkdev_ioctl.
+ */
+int blkdev_zone_ioctl(struct block_device *bdev, fmode_t mode,
+                     unsigned cmd, unsigned long arg)
+{
+       void __user *argp =3D (void __user *)arg;
+       struct request_queue *q;
+       int ret;
+
+       if (!argp)
+               return -EINVAL;
+
+       q =3D bdev_get_queue(bdev);
+       if (!q)
+               return -ENXIO;
+
+       if (!blk_queue_zoned(q))
+               return -ENOTTY;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       switch (cmd) {
+       case BLKREPORTZONE:
+               ret =3D blkdev_report_zone_ioctl(bdev, argp);
+               break;
+       case BLKUPDATEZONES:
+               if (!(mode & FMODE_WRITE)) {
+                       ret =3D -EBADF;
+                       break;
+               }
+               ret =3D blkdev_update_zones(bdev, GFP_KERNEL);
+               break;
+       case BLKRESETZONE:
+       case BLKOPENZONE:
+       case BLKCLOSEZONE:
+       case BLKFINISHZONE:
+               if (!(mode & FMODE_WRITE)) {
+                       ret =3D -EBADF;
+                       break;
+               }
+               ret =3D blkdev_zone_action_ioctl(bdev, cmd, argp);
+               break;
+       default:
+               ret =3D -ENOTTY;
+               break;
+       }
+
+       return ret;
+}
diff --git a/block/ioctl.c b/block/ioctl.c
index ed2397f..f09679a 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -3,6 +3,7 @@
 #include <linux/export.h>
 #include <linux/gfp.h>
 #include <linux/blkpg.h>
+#include <linux/blkzoned.h>
 #include <linux/hdreg.h>
 #include <linux/backing-dev.h>
 #include <linux/fs.h>
@@ -513,6 +514,13 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t =
mode, unsigned cmd,
quoted hunk ↗ jump to hunk
                                BLKDEV_DISCARD_SECURE);
        case BLKZEROOUT:
                return blk_ioctl_zeroout(bdev, mode, arg);
+       case BLKUPDATEZONES:
+       case BLKREPORTZONE:
+       case BLKRESETZONE:
+       case BLKOPENZONE:
+       case BLKCLOSEZONE:
+       case BLKFINISHZONE:
+               return blkdev_zone_ioctl(bdev, mode, cmd, arg);
        case HDIO_GETGEO:
                return blkdev_getgeo(bdev, argp);
        case BLKRAGET:
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index a85f95b..0299d41 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -405,9 +405,16 @@ extern int blkdev_reset_zone(struct block_device *, =
sector_t, gfp_t);
quoted hunk ↗ jump to hunk
 extern int blkdev_open_zone(struct block_device *, sector_t, gfp_t);
 extern int blkdev_close_zone(struct block_device *, sector_t, gfp_t);
 extern int blkdev_finish_zone(struct block_device *, sector_t, gfp_t);
+extern int blkdev_zone_ioctl(struct block_device *, fmode_t, unsigned in=
t,
quoted hunk ↗ jump to hunk
+                            unsigned long);
 #else /* CONFIG_BLK_DEV_ZONED */
 static inline void blk_init_zones(struct request_queue *q) { };
 static inline void blk_drop_zones(struct request_queue *q) { };
+static inline int blkdev_zone_ioctl(struct block_device *bdev, fmode_t m=
ode,
quoted hunk ↗ jump to hunk
+                                   unsigned cmd, unsigned long arg)
+{
+       return -ENOTTY;
+}
 #endif /* CONFIG_BLK_DEV_ZONED */

 struct request_queue {
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 185f8ea..a2a7522 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -70,6 +70,7 @@ header-y +=3D bfs_fs.h
 header-y +=3D binfmts.h
 header-y +=3D blkpg.h
 header-y +=3D blktrace_api.h
+header-y +=3D blkzoned.h
 header-y +=3D bpf_common.h
 header-y +=3D bpf.h
 header-y +=3D bpqether.h
diff --git a/include/uapi/linux/blkzoned.h b/include/uapi/linux/blkzoned.=
h
quoted hunk ↗ jump to hunk
new file mode 100644
index 0000000..23a2702
--- /dev/null
+++ b/include/uapi/linux/blkzoned.h
@@ -0,0 +1,91 @@
+/*
+ * Zoned block devices handling.
+ *
+ * Copyright (C) 2015 Seagate Technology PLC
+ *
+ * Written by: Shaun Tancheff <shaun.tancheff@seagate.com>
+ *
+ * Modified by: Damien Le Moal <damien.lemoal@hgst.com>
+ * Copyright (C) 2016 Western Digital
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#ifndef _UAPI_BLKZONED_H
+#define _UAPI_BLKZONED_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/*
+ * Zone type.
+ */
+enum blkzone_type {
+       BLKZONE_TYPE_UNKNOWN,
+       BLKZONE_TYPE_CONVENTIONAL,
+       BLKZONE_TYPE_SEQWRITE_REQ,
+       BLKZONE_TYPE_SEQWRITE_PREF,
+};
+
+/*
+ * Zone condition.
+ */
+enum blkzone_cond {
+       BLKZONE_COND_NO_WP,
+       BLKZONE_COND_EMPTY,
+       BLKZONE_COND_IMP_OPEN,
+       BLKZONE_COND_EXP_OPEN,
+       BLKZONE_COND_CLOSED,
+       BLKZONE_COND_READONLY =3D 0xd,
+       BLKZONE_COND_FULL,
+       BLKZONE_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 blkzone {
+       __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 =
*/
quoted hunk ↗ jump to hunk
+       __u8    reset;          /* Reset write pointer recommended */
+       __u8    reserved[36];
+};
+
+/*
+ * Zone ioctl's:
+ *
+ * BLKUPDATEZONES      : Force update of all zones information
+ * BLKREPORTZONE       : Get a zone descriptor. Takes a zone descriptor =
as
+ *                        argument. The zone to report is the one
+ *                        containing the sector initially specified in t=
he
+ *                        descriptor start field.
+ * BLKRESETZONE                : Reset the write pointer of the zone con=
taining the
+ *                        specified sector, or of all written zones if t=
he
quoted hunk ↗ jump to hunk
+ *                        sector is ~0ull.
+ * BLKOPENZONE         : Explicitely open the zone containing the
+ *                        specified sector, or all possible zones if the
+ *                        sector is ~0ull (the drive determines which zo=
ne
+ *                        to open in this case).
+ * BLKCLOSEZONE                : Close the zone containing the specified=
 sector, or
quoted hunk ↗ jump to hunk
+ *                        all open zones if the sector is ~0ull.
+ * BLKFINISHZONE       : Finish the zone (make it full) containing the
+ *                        specified sector, or all open and closed zones=
 if
quoted hunk ↗ jump to hunk
+ *                        the sector is ~0ull.
+ */
+#define BLKUPDATEZONES _IO(0x12,130)
+#define BLKREPORTZONE  _IOWR(0x12,131,struct blkzone)
+#define BLKRESETZONE   _IOW(0x12,132,unsigned long long)
+#define BLKOPENZONE    _IOW(0x12,133,unsigned long long)
+#define BLKCLOSEZONE   _IOW(0x12,134,unsigned long long)
+#define BLKFINISHZONE  _IOW(0x12,135,unsigned long long)
+
+#endif /* _UAPI_BLKZONED_H */
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 3b00f7c..1db6d66 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: 130-135 are used for zoned block devices (see uapi/linux=
/blkzoned.h) */
 #define BMAP_IOCTL 1           /* obsolete - kept for compatibility */
 #define FIBMAP    _IO(0x00,1)  /* bmap access */
--
2.7.4

Western Digital Corporation (and its subsidiaries) E-mail Confidentiality=
 Notice & Disclaimer:
This e-mail and any files transmitted with it may contain confidential or=
 legally privileged information of WDC and/or its affiliates, and are inten=
ded solely for the use of the individual or entity to which they are addres=
sed. If you are not the intended recipient, any disclosure, copying, distri=
bution or any action taken or omitted to be taken in reliance on it, is pro=
hibited. If you have received this e-mail in error, please notify the sende=
r immediately and delete the e-mail in its entirety from your system.


--=20
Shaun Tancheff
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help