aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShaun Tancheff <shaun@tancheff.com>2016-10-18 02:40:35 -0400
committerJens Axboe <axboe@fb.com>2016-10-18 12:05:42 -0400
commit3ed05a987e0f63b21e634101e0b460d32f3581c3 (patch)
tree5c5e4166fcba2cf6ceb8bc7d88e586ac752f1094
parent6a0cb1bc106fc07ce0443303bcdb7f7da5131e5c (diff)
blk-zoned: implement ioctls
Adds the new BLKREPORTZONE and BLKRESETZONE ioctls for respectively obtaining the zone configuration of a zoned block device and resetting the write pointer of sequential zones of a zoned block device. The BLKREPORTZONE ioctl maps directly to a single call of the function blkdev_report_zones. The zone information result is passed as an array of struct blk_zone identical to the structure used internally for processing the REQ_OP_ZONE_REPORT operation. The BLKRESETZONE ioctl maps to a single call of the blkdev_reset_zones function. Signed-off-by: Shaun Tancheff <shaun.tancheff@seagate.com> Signed-off-by: Damien Le Moal <damien.lemoal@hgst.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--block/blk-zoned.c93
-rw-r--r--block/ioctl.c4
-rw-r--r--include/linux/blkdev.h21
-rw-r--r--include/uapi/linux/blkzoned.h40
-rw-r--r--include/uapi/linux/fs.h4
5 files changed, 162 insertions, 0 deletions
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index 1603573f9605..667f95d86695 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -255,3 +255,96 @@ int blkdev_reset_zones(struct block_device *bdev,
255 return 0; 255 return 0;
256} 256}
257EXPORT_SYMBOL_GPL(blkdev_reset_zones); 257EXPORT_SYMBOL_GPL(blkdev_reset_zones);
258
259/**
260 * BLKREPORTZONE ioctl processing.
261 * Called from blkdev_ioctl.
262 */
263int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
264 unsigned int cmd, unsigned long arg)
265{
266 void __user *argp = (void __user *)arg;
267 struct request_queue *q;
268 struct blk_zone_report rep;
269 struct blk_zone *zones;
270 int ret;
271
272 if (!argp)
273 return -EINVAL;
274
275 q = bdev_get_queue(bdev);
276 if (!q)
277 return -ENXIO;
278
279 if (!blk_queue_is_zoned(q))
280 return -ENOTTY;
281
282 if (!capable(CAP_SYS_ADMIN))
283 return -EACCES;
284
285 if (copy_from_user(&rep, argp, sizeof(struct blk_zone_report)))
286 return -EFAULT;
287
288 if (!rep.nr_zones)
289 return -EINVAL;
290
291 zones = kcalloc(rep.nr_zones, sizeof(struct blk_zone), GFP_KERNEL);
292 if (!zones)
293 return -ENOMEM;
294
295 ret = blkdev_report_zones(bdev, rep.sector,
296 zones, &rep.nr_zones,
297 GFP_KERNEL);
298 if (ret)
299 goto out;
300
301 if (copy_to_user(argp, &rep, sizeof(struct blk_zone_report))) {
302 ret = -EFAULT;
303 goto out;
304 }
305
306 if (rep.nr_zones) {
307 if (copy_to_user(argp + sizeof(struct blk_zone_report), zones,
308 sizeof(struct blk_zone) * rep.nr_zones))
309 ret = -EFAULT;
310 }
311
312 out:
313 kfree(zones);
314
315 return ret;
316}
317
318/**
319 * BLKRESETZONE ioctl processing.
320 * Called from blkdev_ioctl.
321 */
322int blkdev_reset_zones_ioctl(struct block_device *bdev, fmode_t mode,
323 unsigned int cmd, unsigned long arg)
324{
325 void __user *argp = (void __user *)arg;
326 struct request_queue *q;
327 struct blk_zone_range zrange;
328
329 if (!argp)
330 return -EINVAL;
331
332 q = bdev_get_queue(bdev);
333 if (!q)
334 return -ENXIO;
335
336 if (!blk_queue_is_zoned(q))
337 return -ENOTTY;
338
339 if (!capable(CAP_SYS_ADMIN))
340 return -EACCES;
341
342 if (!(mode & FMODE_WRITE))
343 return -EBADF;
344
345 if (copy_from_user(&zrange, argp, sizeof(struct blk_zone_range)))
346 return -EFAULT;
347
348 return blkdev_reset_zones(bdev, zrange.sector, zrange.nr_sectors,
349 GFP_KERNEL);
350}
diff --git a/block/ioctl.c b/block/ioctl.c
index 755119c3c1b9..f856963204f4 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -519,6 +519,10 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
519 BLKDEV_DISCARD_SECURE); 519 BLKDEV_DISCARD_SECURE);
520 case BLKZEROOUT: 520 case BLKZEROOUT:
521 return blk_ioctl_zeroout(bdev, mode, arg); 521 return blk_ioctl_zeroout(bdev, mode, arg);
522 case BLKREPORTZONE:
523 return blkdev_report_zones_ioctl(bdev, mode, cmd, arg);
524 case BLKRESETZONE:
525 return blkdev_reset_zones_ioctl(bdev, mode, cmd, arg);
522 case HDIO_GETGEO: 526 case HDIO_GETGEO:
523 return blkdev_getgeo(bdev, argp); 527 return blkdev_getgeo(bdev, argp);
524 case BLKRAGET: 528 case BLKRAGET:
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 252043f7cd2c..90097dd8b8ed 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -316,6 +316,27 @@ extern int blkdev_report_zones(struct block_device *bdev,
316extern int blkdev_reset_zones(struct block_device *bdev, sector_t sectors, 316extern int blkdev_reset_zones(struct block_device *bdev, sector_t sectors,
317 sector_t nr_sectors, gfp_t gfp_mask); 317 sector_t nr_sectors, gfp_t gfp_mask);
318 318
319extern int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
320 unsigned int cmd, unsigned long arg);
321extern int blkdev_reset_zones_ioctl(struct block_device *bdev, fmode_t mode,
322 unsigned int cmd, unsigned long arg);
323
324#else /* CONFIG_BLK_DEV_ZONED */
325
326static inline int blkdev_report_zones_ioctl(struct block_device *bdev,
327 fmode_t mode, unsigned int cmd,
328 unsigned long arg)
329{
330 return -ENOTTY;
331}
332
333static inline int blkdev_reset_zones_ioctl(struct block_device *bdev,
334 fmode_t mode, unsigned int cmd,
335 unsigned long arg)
336{
337 return -ENOTTY;
338}
339
319#endif /* CONFIG_BLK_DEV_ZONED */ 340#endif /* CONFIG_BLK_DEV_ZONED */
320 341
321struct request_queue { 342struct request_queue {
diff --git a/include/uapi/linux/blkzoned.h b/include/uapi/linux/blkzoned.h
index a3817214b0e0..40d1d7bff537 100644
--- a/include/uapi/linux/blkzoned.h
+++ b/include/uapi/linux/blkzoned.h
@@ -16,6 +16,7 @@
16#define _UAPI_BLKZONED_H 16#define _UAPI_BLKZONED_H
17 17
18#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/ioctl.h>
19 20
20/** 21/**
21 * enum blk_zone_type - Types of zones allowed in a zoned device. 22 * enum blk_zone_type - Types of zones allowed in a zoned device.
@@ -100,4 +101,43 @@ struct blk_zone {
100 __u8 reserved[36]; 101 __u8 reserved[36];
101}; 102};
102 103
104/**
105 * struct blk_zone_report - BLKREPORTZONE ioctl request/reply
106 *
107 * @sector: starting sector of report
108 * @nr_zones: IN maximum / OUT actual
109 * @reserved: padding to 16 byte alignment
110 * @zones: Space to hold @nr_zones @zones entries on reply.
111 *
112 * The array of at most @nr_zones must follow this structure in memory.
113 */
114struct blk_zone_report {
115 __u64 sector;
116 __u32 nr_zones;
117 __u8 reserved[4];
118 struct blk_zone zones[0];
119} __packed;
120
121/**
122 * struct blk_zone_range - BLKRESETZONE ioctl request
123 * @sector: starting sector of the first zone to issue reset write pointer
124 * @nr_sectors: Total number of sectors of 1 or more zones to reset
125 */
126struct blk_zone_range {
127 __u64 sector;
128 __u64 nr_sectors;
129};
130
131/**
132 * Zoned block device ioctl's:
133 *
134 * @BLKREPORTZONE: Get zone information. Takes a zone report as argument.
135 * The zone report will start from the zone containing the
136 * sector specified in the report request structure.
137 * @BLKRESETZONE: Reset the write pointer of the zones in the specified
138 * sector range. The sector range must be zone aligned.
139 */
140#define BLKREPORTZONE _IOWR(0x12, 130, struct blk_zone_report)
141#define BLKRESETZONE _IOW(0x12, 131, struct blk_zone_range)
142
103#endif /* _UAPI_BLKZONED_H */ 143#endif /* _UAPI_BLKZONED_H */
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index acb2b6152ba0..c1d11df07b28 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -225,6 +225,10 @@ struct fsxattr {
225#define BLKSECDISCARD _IO(0x12,125) 225#define BLKSECDISCARD _IO(0x12,125)
226#define BLKROTATIONAL _IO(0x12,126) 226#define BLKROTATIONAL _IO(0x12,126)
227#define BLKZEROOUT _IO(0x12,127) 227#define BLKZEROOUT _IO(0x12,127)
228/*
229 * A jump here: 130-131 are reserved for zoned block devices
230 * (see uapi/linux/blkzoned.h)
231 */
228 232
229#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ 233#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
230#define FIBMAP _IO(0x00,1) /* bmap access */ 234#define FIBMAP _IO(0x00,1) /* bmap access */