History

ublk: enable zoned storage support

Add zoned storage support to ublk: report_zones and operations: - REQ_OP_ZONE_OPEN - REQ_OP_ZONE_CLOSE - REQ_OP_ZONE_FINISH - REQ_OP_ZONE_RESET - REQ_OP_ZONE_APPEND The zone append feature uses the `addr` field of `struct ublksrv_io_cmd` to communicate ALBA back to the kernel. Therefore ublk must be used with the user copy feature (UBLK_F_USER_COPY) for zoned storage support to be available. Without this feature, ublk will not allow zoned storage support.

Andreas Hindborg committed 3 years ago

Commit 29802d71 parent 1a6e88b2 files · +370 −24Browse files

Unified · Split

2 files
  1. drivers/block/ublk_drv.c +316 −15
  2. include/uapi/linux/ublk_cmd.h +54 −9
drivers/block/ublk_drv.c+316−15
@@ -56,16 +56,21 @@ · 55 unmodified lines
56 | UBLK_F_USER_RECOVERY_REISSUE \56 | UBLK_F_USER_RECOVERY_REISSUE \
57 | UBLK_F_UNPRIVILEGED_DEV \57 | UBLK_F_UNPRIVILEGED_DEV \
58 | UBLK_F_CMD_IOCTL_ENCODE \58 | UBLK_F_CMD_IOCTL_ENCODE \
59 | UBLK_F_USER_COPY)59 | UBLK_F_USER_COPY \
60 | UBLK_F_ZONED)
60 61
61/* All UBLK_PARAM_TYPE_* should be included here */62/* All UBLK_PARAM_TYPE_* should be included here */
62#define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | \63#define UBLK_PARAM_TYPE_ALL \
63 UBLK_PARAM_TYPE_DISCARD | UBLK_PARAM_TYPE_DEVT)64 (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD | \
65 UBLK_PARAM_TYPE_DEVT | UBLK_PARAM_TYPE_ZONED)
64 66
65struct ublk_rq_data {67struct ublk_rq_data {
66 struct llist_node node;68 struct llist_node node;
67 69
68 struct kref ref;70 struct kref ref;
71 __u64 sector;
72 __u32 operation;
73 __u32 nr_zones;
69};74};
70 75
71struct ublk_uring_cmd_pdu {76struct ublk_uring_cmd_pdu {
@@ -185,11 +190,263 @@ struct ublk_params_header { · 113 unmodified lines
185 __u32 types;190 __u32 types;
186};191};
187 192
193static inline unsigned int ublk_req_build_flags(struct request *req);
194static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
195 int tag);
196
188static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)197static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)
189{198{
190 return ub->dev_info.flags & UBLK_F_USER_COPY;199 return ub->dev_info.flags & UBLK_F_USER_COPY;
191}200}
192 201
202static inline bool ublk_dev_is_zoned(const struct ublk_device *ub)
203{
204 return ub->dev_info.flags & UBLK_F_ZONED;
205}
206
207static inline bool ublk_queue_is_zoned(struct ublk_queue *ubq)
208{
209 return ubq->flags & UBLK_F_ZONED;
210}
211
212#ifdef CONFIG_BLK_DEV_ZONED
213
214static int ublk_get_nr_zones(const struct ublk_device *ub)
215{
216 const struct ublk_param_basic *p = &ub->params.basic;
217
218 /* Zone size is a power of 2 */
219 return p->dev_sectors >> ilog2(p->chunk_sectors);
220}
221
222static int ublk_revalidate_disk_zones(struct ublk_device *ub)
223{
224 return blk_revalidate_disk_zones(ub->ub_disk, NULL);
225}
226
227static int ublk_dev_param_zoned_validate(const struct ublk_device *ub)
228{
229 const struct ublk_param_zoned *p = &ub->params.zoned;
230 int nr_zones;
231
232 if (!ublk_dev_is_zoned(ub))
233 return -EINVAL;
234
235 if (!p->max_zone_append_sectors)
236 return -EINVAL;
237
238 nr_zones = ublk_get_nr_zones(ub);
239
240 if (p->max_active_zones > nr_zones)
241 return -EINVAL;
242
243 if (p->max_open_zones > nr_zones)
244 return -EINVAL;
245
246 return 0;
247}
248
249static int ublk_dev_param_zoned_apply(struct ublk_device *ub)
250{
251 const struct ublk_param_zoned *p = &ub->params.zoned;
252
253 disk_set_zoned(ub->ub_disk, BLK_ZONED_HM);
254 blk_queue_required_elevator_features(ub->ub_disk->queue,
255 ELEVATOR_F_ZBD_SEQ_WRITE);
256 disk_set_max_active_zones(ub->ub_disk, p->max_active_zones);
257 disk_set_max_open_zones(ub->ub_disk, p->max_open_zones);
258 blk_queue_max_zone_append_sectors(ub->ub_disk->queue, p->max_zone_append_sectors);
259
260 ub->ub_disk->nr_zones = ublk_get_nr_zones(ub);
261
262 return 0;
263}
264
265/* Based on virtblk_alloc_report_buffer */
266static void *ublk_alloc_report_buffer(struct ublk_device *ublk,
267 unsigned int nr_zones, size_t *buflen)
268{
269 struct request_queue *q = ublk->ub_disk->queue;
270 size_t bufsize;
271 void *buf;
272
273 nr_zones = min_t(unsigned int, nr_zones,
274 ublk->ub_disk->nr_zones);
275
276 bufsize = nr_zones * sizeof(struct blk_zone);
277 bufsize =
278 min_t(size_t, bufsize, queue_max_hw_sectors(q) << SECTOR_SHIFT);
279
280 while (bufsize >= sizeof(struct blk_zone)) {
281 buf = kvmalloc(bufsize, GFP_KERNEL | __GFP_NORETRY);
282 if (buf) {
283 *buflen = bufsize;
284 return buf;
285 }
286 bufsize >>= 1;
287 }
288
289 *buflen = 0;
290 return NULL;
291}
292
293static int ublk_report_zones(struct gendisk *disk, sector_t sector,
294 unsigned int nr_zones, report_zones_cb cb, void *data)
295{
296 struct ublk_device *ub = disk->private_data;
297 unsigned int zone_size_sectors = disk->queue->limits.chunk_sectors;
298 unsigned int first_zone = sector >> ilog2(zone_size_sectors);
299 unsigned int done_zones = 0;
300 unsigned int max_zones_per_request;
301 int ret;
302 struct blk_zone *buffer;
303 size_t buffer_length;
304
305 nr_zones = min_t(unsigned int, ub->ub_disk->nr_zones - first_zone,
306 nr_zones);
307
308 buffer = ublk_alloc_report_buffer(ub, nr_zones, &buffer_length);
309 if (!buffer)
310 return -ENOMEM;
311
312 max_zones_per_request = buffer_length / sizeof(struct blk_zone);
313
314 while (done_zones < nr_zones) {
315 unsigned int remaining_zones = nr_zones - done_zones;
316 unsigned int zones_in_request =
317 min_t(unsigned int, remaining_zones, max_zones_per_request);
318 struct request *req;
319 struct ublk_rq_data *pdu;
320 blk_status_t status;
321
322 memset(buffer, 0, buffer_length);
323
324 req = blk_mq_alloc_request(disk->queue, REQ_OP_DRV_IN, 0);
325 if (IS_ERR(req)) {
326 ret = PTR_ERR(req);
327 goto out;
328 }
329
330 pdu = blk_mq_rq_to_pdu(req);
331 pdu->operation = UBLK_IO_OP_REPORT_ZONES;
332 pdu->sector = sector;
333 pdu->nr_zones = zones_in_request;
334
335 ret = blk_rq_map_kern(disk->queue, req, buffer, buffer_length,
336 GFP_KERNEL);
337 if (ret) {
338 blk_mq_free_request(req);
339 goto out;
340 }
341
342 status = blk_execute_rq(req, 0);
343 ret = blk_status_to_errno(status);
344 blk_mq_free_request(req);
345 if (ret)
346 goto out;
347
348 for (unsigned int i = 0; i < zones_in_request; i++) {
349 struct blk_zone *zone = buffer + i;
350
351 /* A zero length zone means no more zones in this response */
352 if (!zone->len)
353 break;
354
355 ret = cb(zone, i, data);
356 if (ret)
357 goto out;
358
359 done_zones++;
360 sector += zone_size_sectors;
361
362 }
363 }
364
365 ret = done_zones;
366
367out:
368 kvfree(buffer);
369 return ret;
370}
371
372static blk_status_t ublk_setup_iod_zoned(struct ublk_queue *ubq,
373 struct request *req)
374{
375 struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
376 struct ublk_io *io = &ubq->ios[req->tag];
377 struct ublk_rq_data *pdu = blk_mq_rq_to_pdu(req);
378 u32 ublk_op;
379
380 switch (req_op(req)) {
381 case REQ_OP_ZONE_OPEN:
382 ublk_op = UBLK_IO_OP_ZONE_OPEN;
383 break;
384 case REQ_OP_ZONE_CLOSE:
385 ublk_op = UBLK_IO_OP_ZONE_CLOSE;
386 break;
387 case REQ_OP_ZONE_FINISH:
388 ublk_op = UBLK_IO_OP_ZONE_FINISH;
389 break;
390 case REQ_OP_ZONE_RESET:
391 ublk_op = UBLK_IO_OP_ZONE_RESET;
392 break;
393 case REQ_OP_ZONE_APPEND:
394 ublk_op = UBLK_IO_OP_ZONE_APPEND;
395 break;
396 case REQ_OP_DRV_IN:
397 ublk_op = pdu->operation;
398 switch (ublk_op) {
399 case UBLK_IO_OP_REPORT_ZONES:
400 iod->op_flags = ublk_op | ublk_req_build_flags(req);
401 iod->nr_zones = pdu->nr_zones;
402 iod->start_sector = pdu->sector;
403 return BLK_STS_OK;
404 default:
405 return BLK_STS_IOERR;
406 }
407 case REQ_OP_ZONE_RESET_ALL:
408 case REQ_OP_DRV_OUT:
409 /* We do not support reset_all and drv_out */
410 return BLK_STS_NOTSUPP;
411 default:
412 return BLK_STS_IOERR;
413 }
414
415 iod->op_flags = ublk_op | ublk_req_build_flags(req);
416 iod->nr_sectors = blk_rq_sectors(req);
417 iod->start_sector = blk_rq_pos(req);
418 iod->addr = io->addr;
419
420 return BLK_STS_OK;
421}
422
423#else
424
425#define ublk_report_zones (NULL)
426
427static int ublk_dev_param_zoned_validate(const struct ublk_device *ub)
428{
429 return -EOPNOTSUPP;
430}
431
432static int ublk_dev_param_zoned_apply(struct ublk_device *ub)
433{
434 return -EOPNOTSUPP;
435}
436
437static int ublk_revalidate_disk_zones(struct ublk_device *ub)
438{
439 return 0;
440}
441
442static blk_status_t ublk_setup_iod_zoned(struct ublk_queue *ubq,
443 struct request *req)
444{
445 return -EOPNOTSUPP;
446}
447
448#endif
449
193static inline void __ublk_complete_rq(struct request *req);450static inline void __ublk_complete_rq(struct request *req);
194static void ublk_complete_rq(struct kref *ref);451static void ublk_complete_rq(struct kref *ref);
195 452
@@ -286,6 +543,9 @@ static int ublk_validate_params(const struct ublk_device *ub) · 90 unmodified lines
286 543
287 if (p->max_sectors > (ub->dev_info.max_io_buf_bytes >> 9))544 if (p->max_sectors > (ub->dev_info.max_io_buf_bytes >> 9))
288 return -EINVAL;545 return -EINVAL;
546
547 if (ublk_dev_is_zoned(ub) && !p->chunk_sectors)
548 return -EINVAL;
289 } else549 } else
290 return -EINVAL;550 return -EINVAL;
291 551
@@ -304,6 +564,11 @@ static int ublk_validate_params(const struct ublk_device *ub) · 12 unmodified lines
304 if (ub->params.types & UBLK_PARAM_TYPE_DEVT)564 if (ub->params.types & UBLK_PARAM_TYPE_DEVT)
305 return -EINVAL;565 return -EINVAL;
306 566
567 if (ub->params.types & UBLK_PARAM_TYPE_ZONED)
568 return ublk_dev_param_zoned_validate(ub);
569 else if (ublk_dev_is_zoned(ub))
570 return -EINVAL;
571
307 return 0;572 return 0;
308}573}
309 574
@@ -317,6 +582,9 @@ static int ublk_apply_params(struct ublk_device *ub) · 7 unmodified lines
317 if (ub->params.types & UBLK_PARAM_TYPE_DISCARD)582 if (ub->params.types & UBLK_PARAM_TYPE_DISCARD)
318 ublk_dev_param_discard_apply(ub);583 ublk_dev_param_discard_apply(ub);
319 584
585 if (ub->params.types & UBLK_PARAM_TYPE_ZONED)
586 return ublk_dev_param_zoned_apply(ub);
587
320 return 0;588 return 0;
321}589}
322 590
@@ -487,6 +755,7 @@ static const struct block_device_operations ub_fops = { · 164 unmodified lines
487 .owner = THIS_MODULE,755 .owner = THIS_MODULE,
488 .open = ublk_open,756 .open = ublk_open,
489 .free_disk = ublk_free_disk,757 .free_disk = ublk_free_disk,
758 .report_zones = ublk_report_zones,
490};759};
491 760
492#define UBLK_MAX_PIN_PAGES 32761#define UBLK_MAX_PIN_PAGES 32
@@ -601,7 +870,8 @@ static inline bool ublk_need_map_req(const struct request *req) · 108 unmodified lines
601 870
602static inline bool ublk_need_unmap_req(const struct request *req)871static inline bool ublk_need_unmap_req(const struct request *req)
603{872{
604 return ublk_rq_has_data(req) && req_op(req) == REQ_OP_READ;873 return ublk_rq_has_data(req) &&
874 (req_op(req) == REQ_OP_READ || req_op(req) == REQ_OP_DRV_IN);
605}875}
606 876
607static int ublk_map_io(const struct ublk_queue *ubq, const struct request *req,877static int ublk_map_io(const struct ublk_queue *ubq, const struct request *req,
@@ -685,8 +955,13 @@ static blk_status_t ublk_setup_iod(struct ublk_queue *ubq, struct request *req) · 77 unmodified lines
685{955{
686 struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);956 struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
687 struct ublk_io *io = &ubq->ios[req->tag];957 struct ublk_io *io = &ubq->ios[req->tag];
958 enum req_op op = req_op(req);
688 u32 ublk_op;959 u32 ublk_op;
689 960
961 if (!ublk_queue_is_zoned(ubq) &&
962 (op_is_zone_mgmt(op) || op == REQ_OP_ZONE_APPEND))
963 return -EIO;
964
690 switch (req_op(req)) {965 switch (req_op(req)) {
691 case REQ_OP_READ:966 case REQ_OP_READ:
692 ublk_op = UBLK_IO_OP_READ;967 ublk_op = UBLK_IO_OP_READ;
@@ -704,6 +979,8 @@ static blk_status_t ublk_setup_iod(struct ublk_queue *ubq, struct request *req) · 11 unmodified lines
704 ublk_op = UBLK_IO_OP_WRITE_ZEROES;979 ublk_op = UBLK_IO_OP_WRITE_ZEROES;
705 break;980 break;
706 default:981 default:
982 if (ublk_queue_is_zoned(ubq))
983 return ublk_setup_iod_zoned(ubq, req);
707 return BLK_STS_IOERR;984 return BLK_STS_IOERR;
708 }985 }
709 986
@@ -756,7 +1033,8 @@ static inline void __ublk_complete_rq(struct request *req) · 46 unmodified lines
756 *1033 *
757 * Both the two needn't unmap.1034 * Both the two needn't unmap.
758 */1035 */
759 if (req_op(req) != REQ_OP_READ && req_op(req) != REQ_OP_WRITE)1036 if (req_op(req) != REQ_OP_READ && req_op(req) != REQ_OP_WRITE &&
1037 req_op(req) != REQ_OP_DRV_IN)
760 goto exit;1038 goto exit;
761 1039
762 /* for READ request, writing data in iod->addr to rq buffers */1040 /* for READ request, writing data in iod->addr to rq buffers */
@@ -1120,6 +1398,9 @@ static void ublk_commit_completion(struct ublk_device *ub, · 357 unmodified lines
1120 /* find the io request and complete */1398 /* find the io request and complete */
1121 req = blk_mq_tag_to_rq(ub->tag_set.tags[qid], tag);1399 req = blk_mq_tag_to_rq(ub->tag_set.tags[qid], tag);
1122 1400
1401 if (req_op(req) == REQ_OP_ZONE_APPEND)
1402 req->__sector = ub_cmd->zone_append_lba;
1403
1123 if (req && likely(!blk_should_fake_timeout(req->q)))1404 if (req && likely(!blk_should_fake_timeout(req->q)))
1124 ublk_put_req_ref(ubq, req);1405 ublk_put_req_ref(ubq, req);
1125}1406}
@@ -1468,8 +1749,11 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, · 342 unmodified lines
1468 if (!ub_cmd->addr && (!ublk_need_get_data(ubq) ||1749 if (!ub_cmd->addr && (!ublk_need_get_data(ubq) ||
1469 req_op(req) == REQ_OP_READ))1750 req_op(req) == REQ_OP_READ))
1470 goto out;1751 goto out;
1471 } else if (ub_cmd->addr) {1752 } else if (req_op(req) != REQ_OP_ZONE_APPEND && ub_cmd->addr) {
1472 /* User copy requires addr to be unset */1753 /*
1754 * User copy requires addr to be unset when command is
1755 * not zone append
1756 */
1473 ret = -EINVAL;1757 ret = -EINVAL;
1474 goto out;1758 goto out;
1475 }1759 }
@@ -1546,11 +1830,14 @@ static inline bool ublk_check_ubuf_dir(const struct request *req, · 70 unmodified lines
1546 int ubuf_dir)1830 int ubuf_dir)
1547{1831{
1548 /* copy ubuf to request pages */1832 /* copy ubuf to request pages */
1549 if (req_op(req) == REQ_OP_READ && ubuf_dir == ITER_SOURCE)1833 if ((req_op(req) == REQ_OP_READ || req_op(req) == REQ_OP_DRV_IN) &&
1834 ubuf_dir == ITER_SOURCE)
1550 return true;1835 return true;
1551 1836
1552 /* copy request pages to ubuf */1837 /* copy request pages to ubuf */
1553 if (req_op(req) == REQ_OP_WRITE && ubuf_dir == ITER_DEST)1838 if ((req_op(req) == REQ_OP_WRITE ||
1839 req_op(req) == REQ_OP_ZONE_APPEND) &&
1840 ubuf_dir == ITER_DEST)
1554 return true;1841 return true;
1555 1842
1556 return false;1843 return false;
@@ -1889,17 +2176,24 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd) · 332 unmodified lines
1889 2176
1890 get_device(&ub->cdev_dev);2177 get_device(&ub->cdev_dev);
1891 ub->dev_info.state = UBLK_S_DEV_LIVE;2178 ub->dev_info.state = UBLK_S_DEV_LIVE;
2179
2180 if (ublk_dev_is_zoned(ub)) {
2181 ret = ublk_revalidate_disk_zones(ub);
2182 if (ret)
2183 goto out_put_cdev;
2184 }
2185
1892 ret = add_disk(disk);2186 ret = add_disk(disk);
2187 if (ret)
2188 goto out_put_cdev;
2189
2190 set_bit(UB_STATE_USED, &ub->state);
2191
2192out_put_cdev:
1893 if (ret) {2193 if (ret) {
1894 /*
1895 * Has to drop the reference since ->free_disk won't be
1896 * called in case of add_disk failure.
1897 */
1898 ub->dev_info.state = UBLK_S_DEV_DEAD;2194 ub->dev_info.state = UBLK_S_DEV_DEAD;
1899 ublk_put_device(ub);2195 ublk_put_device(ub);
1900 goto out_put_disk;
1901 }2196 }
1902 set_bit(UB_STATE_USED, &ub->state);
1903out_put_disk:2197out_put_disk:
1904 if (ret)2198 if (ret)
1905 put_disk(disk);2199 put_disk(disk);
@@ -2049,6 +2343,13 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd) · 143 unmodified lines
2049 if (ublk_dev_is_user_copy(ub))2343 if (ublk_dev_is_user_copy(ub))
2050 ub->dev_info.flags &= ~UBLK_F_NEED_GET_DATA;2344 ub->dev_info.flags &= ~UBLK_F_NEED_GET_DATA;
2051 2345
2346 /* Zoned storage support requires user copy feature */
2347 if (ublk_dev_is_zoned(ub) &&
2348 (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) || !ublk_dev_is_user_copy(ub))) {
2349 ret = -EINVAL;
2350 goto out_free_dev_number;
2351 }
2352
2052 /* We are not ready to support zero copy */2353 /* We are not ready to support zero copy */
2053 ub->dev_info.flags &= ~UBLK_F_SUPPORT_ZERO_COPY;2354 ub->dev_info.flags &= ~UBLK_F_SUPPORT_ZERO_COPY;
2054 2355
include/uapi/linux/ublk_cmd.h+54−9
@@ -176,6 +176,12 @@ · 175 unmodified lines
176/* Copy between request and user buffer by pread()/pwrite() */176/* Copy between request and user buffer by pread()/pwrite() */
177#define UBLK_F_USER_COPY (1UL << 7)177#define UBLK_F_USER_COPY (1UL << 7)
178 178
179/*
180 * User space sets this flag when setting up the device to request zoned storage support. Kernel may
181 * deny the request by returning an error.
182 */
183#define UBLK_F_ZONED (1ULL << 8)
184
179/* device state */185/* device state */
180#define UBLK_S_DEV_DEAD 0186#define UBLK_S_DEV_DEAD 0
181#define UBLK_S_DEV_LIVE 1187#define UBLK_S_DEV_LIVE 1
@@ -232,9 +238,26 @@ struct ublksrv_ctrl_dev_info { · 50 unmodified lines
232#define UBLK_IO_OP_READ 0238#define UBLK_IO_OP_READ 0
233#define UBLK_IO_OP_WRITE 1239#define UBLK_IO_OP_WRITE 1
234#define UBLK_IO_OP_FLUSH 2240#define UBLK_IO_OP_FLUSH 2
235#define UBLK_IO_OP_DISCARD 3241#define UBLK_IO_OP_DISCARD 3
236#define UBLK_IO_OP_WRITE_SAME 4242#define UBLK_IO_OP_WRITE_SAME 4
237#define UBLK_IO_OP_WRITE_ZEROES 5243#define UBLK_IO_OP_WRITE_ZEROES 5
244#define UBLK_IO_OP_ZONE_OPEN 10
245#define UBLK_IO_OP_ZONE_CLOSE 11
246#define UBLK_IO_OP_ZONE_FINISH 12
247#define UBLK_IO_OP_ZONE_APPEND 13
248#define UBLK_IO_OP_ZONE_RESET 15
249/*
250 * Construct a zone report. The report request is carried in `struct
251 * ublksrv_io_desc`. The `start_sector` field must be the first sector of a zone
252 * and shall indicate the first zone of the report. The `nr_zones` shall
253 * indicate how many zones should be reported at most. The report shall be
254 * delivered as a `struct blk_zone` array. To report fewer zones than requested,
255 * zero the last entry of the returned array.
256 *
257 * Related definitions(blk_zone, blk_zone_cond, blk_zone_type, ...) in
258 * include/uapi/linux/blkzoned.h are part of ublk UAPI.
259 */
260#define UBLK_IO_OP_REPORT_ZONES 18
238 261
239#define UBLK_IO_F_FAILFAST_DEV (1U << 8)262#define UBLK_IO_F_FAILFAST_DEV (1U << 8)
240#define UBLK_IO_F_FAILFAST_TRANSPORT (1U << 9)263#define UBLK_IO_F_FAILFAST_TRANSPORT (1U << 9)
@@ -255,7 +278,10 @@ struct ublksrv_io_desc { · 14 unmodified lines
255 /* op: bit 0-7, flags: bit 8-31 */278 /* op: bit 0-7, flags: bit 8-31 */
256 __u32 op_flags;279 __u32 op_flags;
257 280
258 __u32 nr_sectors;281 union {
282 __u32 nr_sectors;
283 __u32 nr_zones; /* for UBLK_IO_OP_REPORT_ZONES */
284 };
259 285
260 /* start sector for this io */286 /* start sector for this io */
261 __u64 start_sector;287 __u64 start_sector;
@@ -284,11 +310,21 @@ struct ublksrv_io_cmd { · 22 unmodified lines
284 /* io result, it is valid for COMMIT* command only */310 /* io result, it is valid for COMMIT* command only */
285 __s32 result;311 __s32 result;
286 312
287 /*313 union {
288 * userspace buffer address in ublksrv daemon process, valid for314 /*
289 * FETCH* command only315 * userspace buffer address in ublksrv daemon process, valid for
290 */316 * FETCH* command only
291 __u64 addr;317 *
318 * `addr` should not be used when UBLK_F_USER_COPY is enabled,
319 * because userspace handles data copy by pread()/pwrite() over
320 * /dev/ublkcN. But in case of UBLK_F_ZONED, this union is
321 * re-used to pass back the allocated LBA for
322 * UBLK_IO_OP_ZONE_APPEND which actually depends on
323 * UBLK_F_USER_COPY
324 */
325 __u64 addr;
326 __u64 zone_append_lba;
327 };
292};328};
293 329
294struct ublk_param_basic {330struct ublk_param_basic {
@@ -331,6 +367,13 @@ struct ublk_param_devt { · 36 unmodified lines
331 __u32 disk_minor;367 __u32 disk_minor;
332};368};
333 369
370struct ublk_param_zoned {
371 __u32 max_open_zones;
372 __u32 max_active_zones;
373 __u32 max_zone_append_sectors;
374 __u8 reserved[20];
375};
376
334struct ublk_params {377struct ublk_params {
335 /*378 /*
336 * Total length of parameters, userspace has to set 'len' for both379 * Total length of parameters, userspace has to set 'len' for both
@@ -342,11 +385,13 @@ struct ublk_params { · 5 unmodified lines
342#define UBLK_PARAM_TYPE_BASIC (1 << 0)385#define UBLK_PARAM_TYPE_BASIC (1 << 0)
343#define UBLK_PARAM_TYPE_DISCARD (1 << 1)386#define UBLK_PARAM_TYPE_DISCARD (1 << 1)
344#define UBLK_PARAM_TYPE_DEVT (1 << 2)387#define UBLK_PARAM_TYPE_DEVT (1 << 2)
388#define UBLK_PARAM_TYPE_ZONED (1 << 3)
345 __u32 types; /* types of parameter included */389 __u32 types; /* types of parameter included */
346 390
347 struct ublk_param_basic basic;391 struct ublk_param_basic basic;
348 struct ublk_param_discard discard;392 struct ublk_param_discard discard;
349 struct ublk_param_devt devt;393 struct ublk_param_devt devt;
394 struct ublk_param_zoned zoned;
350};395};
351 396
352#endif397#endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t