|
51 | 51 | /* private ioctl command mirror */ |
52 | 52 | #define UBLK_CMD_DEL_DEV_ASYNC _IOC_NR(UBLK_U_CMD_DEL_DEV_ASYNC) |
53 | 53 |
|
| 54 | +#define UBLK_IO_REGISTER_IO_BUF _IOC_NR(UBLK_U_IO_REGISTER_IO_BUF) |
| 55 | +#define UBLK_IO_UNREGISTER_IO_BUF _IOC_NR(UBLK_U_IO_UNREGISTER_IO_BUF) |
| 56 | + |
54 | 57 | /* All UBLK_F_* have to be included into UBLK_F_ALL */ |
55 | 58 | #define UBLK_F_ALL (UBLK_F_SUPPORT_ZERO_COPY \ |
56 | 59 | | UBLK_F_URING_CMD_COMP_IN_TASK \ |
@@ -196,12 +199,14 @@ struct ublk_params_header { |
196 | 199 |
|
197 | 200 | static bool ublk_abort_requests(struct ublk_device *ub, struct ublk_queue *ubq); |
198 | 201 |
|
| 202 | +static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub, |
| 203 | + struct ublk_queue *ubq, int tag, size_t offset); |
199 | 204 | static inline unsigned int ublk_req_build_flags(struct request *req); |
200 | 205 | static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq, |
201 | 206 | int tag); |
202 | 207 | static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub) |
203 | 208 | { |
204 | | - return ub->dev_info.flags & UBLK_F_USER_COPY; |
| 209 | + return ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY); |
205 | 210 | } |
206 | 211 |
|
207 | 212 | static inline bool ublk_dev_is_zoned(const struct ublk_device *ub) |
@@ -581,7 +586,7 @@ static void ublk_apply_params(struct ublk_device *ub) |
581 | 586 |
|
582 | 587 | static inline bool ublk_support_user_copy(const struct ublk_queue *ubq) |
583 | 588 | { |
584 | | - return ubq->flags & UBLK_F_USER_COPY; |
| 589 | + return ubq->flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY); |
585 | 590 | } |
586 | 591 |
|
587 | 592 | static inline bool ublk_need_req_ref(const struct ublk_queue *ubq) |
@@ -1747,6 +1752,45 @@ static inline void ublk_prep_cancel(struct io_uring_cmd *cmd, |
1747 | 1752 | io_uring_cmd_mark_cancelable(cmd, issue_flags); |
1748 | 1753 | } |
1749 | 1754 |
|
| 1755 | +static void ublk_io_release(void *priv) |
| 1756 | +{ |
| 1757 | + struct request *rq = priv; |
| 1758 | + struct ublk_queue *ubq = rq->mq_hctx->driver_data; |
| 1759 | + |
| 1760 | + ublk_put_req_ref(ubq, rq); |
| 1761 | +} |
| 1762 | + |
| 1763 | +static int ublk_register_io_buf(struct io_uring_cmd *cmd, |
| 1764 | + struct ublk_queue *ubq, unsigned int tag, |
| 1765 | + const struct ublksrv_io_cmd *ub_cmd, |
| 1766 | + unsigned int issue_flags) |
| 1767 | +{ |
| 1768 | + struct ublk_device *ub = cmd->file->private_data; |
| 1769 | + int index = (int)ub_cmd->addr, ret; |
| 1770 | + struct request *req; |
| 1771 | + |
| 1772 | + req = __ublk_check_and_get_req(ub, ubq, tag, 0); |
| 1773 | + if (!req) |
| 1774 | + return -EINVAL; |
| 1775 | + |
| 1776 | + ret = io_buffer_register_bvec(cmd, req, ublk_io_release, index, |
| 1777 | + issue_flags); |
| 1778 | + if (ret) { |
| 1779 | + ublk_put_req_ref(ubq, req); |
| 1780 | + return ret; |
| 1781 | + } |
| 1782 | + |
| 1783 | + return 0; |
| 1784 | +} |
| 1785 | + |
| 1786 | +static int ublk_unregister_io_buf(struct io_uring_cmd *cmd, |
| 1787 | + const struct ublksrv_io_cmd *ub_cmd, |
| 1788 | + unsigned int issue_flags) |
| 1789 | +{ |
| 1790 | + io_buffer_unregister_bvec(cmd, ub_cmd->addr, issue_flags); |
| 1791 | + return 0; |
| 1792 | +} |
| 1793 | + |
1750 | 1794 | static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, |
1751 | 1795 | unsigned int issue_flags, |
1752 | 1796 | const struct ublksrv_io_cmd *ub_cmd) |
@@ -1798,6 +1842,10 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, |
1798 | 1842 |
|
1799 | 1843 | ret = -EINVAL; |
1800 | 1844 | switch (_IOC_NR(cmd_op)) { |
| 1845 | + case UBLK_IO_REGISTER_IO_BUF: |
| 1846 | + return ublk_register_io_buf(cmd, ubq, tag, ub_cmd, issue_flags); |
| 1847 | + case UBLK_IO_UNREGISTER_IO_BUF: |
| 1848 | + return ublk_unregister_io_buf(cmd, ub_cmd, issue_flags); |
1801 | 1849 | case UBLK_IO_FETCH_REQ: |
1802 | 1850 | /* UBLK_IO_FETCH_REQ is only allowed before queue is setup */ |
1803 | 1851 | if (ublk_queue_ready(ubq)) { |
@@ -2459,7 +2507,7 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd) |
2459 | 2507 | * buffer by pwrite() to ublk char device, which can't be |
2460 | 2508 | * used for unprivileged device |
2461 | 2509 | */ |
2462 | | - if (info.flags & UBLK_F_USER_COPY) |
| 2510 | + if (info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY)) |
2463 | 2511 | return -EINVAL; |
2464 | 2512 | } |
2465 | 2513 |
|
@@ -2527,9 +2575,6 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd) |
2527 | 2575 | goto out_free_dev_number; |
2528 | 2576 | } |
2529 | 2577 |
|
2530 | | - /* We are not ready to support zero copy */ |
2531 | | - ub->dev_info.flags &= ~UBLK_F_SUPPORT_ZERO_COPY; |
2532 | | - |
2533 | 2578 | ub->dev_info.nr_hw_queues = min_t(unsigned int, |
2534 | 2579 | ub->dev_info.nr_hw_queues, nr_cpu_ids); |
2535 | 2580 | ublk_align_max_io_size(ub); |
@@ -2860,7 +2905,7 @@ static int ublk_ctrl_get_features(struct io_uring_cmd *cmd) |
2860 | 2905 | { |
2861 | 2906 | const struct ublksrv_ctrl_cmd *header = io_uring_sqe_cmd(cmd->sqe); |
2862 | 2907 | void __user *argp = (void __user *)(unsigned long)header->addr; |
2863 | | - u64 features = UBLK_F_ALL & ~UBLK_F_SUPPORT_ZERO_COPY; |
| 2908 | + u64 features = UBLK_F_ALL; |
2864 | 2909 |
|
2865 | 2910 | if (header->len != UBLK_FEATURES_LEN || !header->addr) |
2866 | 2911 | return -EINVAL; |
|
0 commit comments