Skip to content

Commit 3ed05a9

Browse files
stancheffaxboe
authored andcommitted
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 <[email protected]> Signed-off-by: Damien Le Moal <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Martin K. Petersen <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 6a0cb1b commit 3ed05a9

File tree

5 files changed

+162
-0
lines changed

5 files changed

+162
-0
lines changed

block/blk-zoned.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,96 @@ int blkdev_reset_zones(struct block_device *bdev,
255255
return 0;
256256
}
257257
EXPORT_SYMBOL_GPL(blkdev_reset_zones);
258+
259+
/**
260+
* BLKREPORTZONE ioctl processing.
261+
* Called from blkdev_ioctl.
262+
*/
263+
int 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+
*/
322+
int 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+
}

block/ioctl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,10 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
519519
BLKDEV_DISCARD_SECURE);
520520
case BLKZEROOUT:
521521
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);
522526
case HDIO_GETGEO:
523527
return blkdev_getgeo(bdev, argp);
524528
case BLKRAGET:

include/linux/blkdev.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,27 @@ extern int blkdev_report_zones(struct block_device *bdev,
316316
extern int blkdev_reset_zones(struct block_device *bdev, sector_t sectors,
317317
sector_t nr_sectors, gfp_t gfp_mask);
318318

319+
extern int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
320+
unsigned int cmd, unsigned long arg);
321+
extern 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+
326+
static 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+
333+
static 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+
319340
#endif /* CONFIG_BLK_DEV_ZONED */
320341

321342
struct request_queue {

include/uapi/linux/blkzoned.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define _UAPI_BLKZONED_H
1717

1818
#include <linux/types.h>
19+
#include <linux/ioctl.h>
1920

2021
/**
2122
* enum blk_zone_type - Types of zones allowed in a zoned device.
@@ -100,4 +101,43 @@ struct blk_zone {
100101
__u8 reserved[36];
101102
};
102103

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+
*/
114+
struct 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+
*/
126+
struct 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+
103143
#endif /* _UAPI_BLKZONED_H */

include/uapi/linux/fs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,10 @@ struct fsxattr {
225225
#define BLKSECDISCARD _IO(0x12,125)
226226
#define BLKROTATIONAL _IO(0x12,126)
227227
#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+
*/
228232

229233
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
230234
#define FIBMAP _IO(0x00,1) /* bmap access */

0 commit comments

Comments
 (0)