@@ -201,15 +201,10 @@ struct ublk_params_header {
201201static void ublk_stop_dev_unlocked (struct ublk_device * ub );
202202static void ublk_abort_queue (struct ublk_device * ub , struct ublk_queue * ubq );
203203static inline struct request * __ublk_check_and_get_req (struct ublk_device * ub ,
204- struct ublk_queue * ubq , int tag , size_t offset );
204+ const struct ublk_queue * ubq , int tag , size_t offset );
205205static inline unsigned int ublk_req_build_flags (struct request * req );
206206static inline struct ublksrv_io_desc * ublk_get_iod (struct ublk_queue * ubq ,
207207 int tag );
208- static inline bool ublk_dev_is_user_copy (const struct ublk_device * ub )
209- {
210- return ub -> dev_info .flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY );
211- }
212-
213208static inline bool ublk_dev_is_zoned (const struct ublk_device * ub )
214209{
215210 return ub -> dev_info .flags & UBLK_F_ZONED ;
@@ -609,23 +604,31 @@ static void ublk_apply_params(struct ublk_device *ub)
609604 ublk_dev_param_zoned_apply (ub );
610605}
611606
607+ static inline bool ublk_support_zero_copy (const struct ublk_queue * ubq )
608+ {
609+ return ubq -> flags & UBLK_F_SUPPORT_ZERO_COPY ;
610+ }
611+
612612static inline bool ublk_support_user_copy (const struct ublk_queue * ubq )
613613{
614- return ubq -> flags & ( UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY ) ;
614+ return ubq -> flags & UBLK_F_USER_COPY ;
615615}
616616
617617static inline bool ublk_need_map_io (const struct ublk_queue * ubq )
618618{
619- return !ublk_support_user_copy (ubq );
619+ return !ublk_support_user_copy (ubq ) && ! ublk_support_zero_copy ( ubq ) ;
620620}
621621
622622static inline bool ublk_need_req_ref (const struct ublk_queue * ubq )
623623{
624624 /*
625625 * read()/write() is involved in user copy, so request reference
626626 * has to be grabbed
627+ *
628+ * for zero copy, request buffer need to be registered to io_uring
629+ * buffer table, so reference is needed
627630 */
628- return ublk_support_user_copy (ubq );
631+ return ublk_support_user_copy (ubq ) || ublk_support_zero_copy ( ubq ) ;
629632}
630633
631634static inline void ublk_init_req_ref (const struct ublk_queue * ubq ,
@@ -1946,13 +1949,20 @@ static void ublk_io_release(void *priv)
19461949}
19471950
19481951static int ublk_register_io_buf (struct io_uring_cmd * cmd ,
1949- struct ublk_queue * ubq , unsigned int tag ,
1952+ const struct ublk_queue * ubq , unsigned int tag ,
19501953 unsigned int index , unsigned int issue_flags )
19511954{
19521955 struct ublk_device * ub = cmd -> file -> private_data ;
1956+ const struct ublk_io * io = & ubq -> ios [tag ];
19531957 struct request * req ;
19541958 int ret ;
19551959
1960+ if (!ublk_support_zero_copy (ubq ))
1961+ return - EINVAL ;
1962+
1963+ if (!(io -> flags & UBLK_IO_FLAG_OWNED_BY_SRV ))
1964+ return - EINVAL ;
1965+
19561966 req = __ublk_check_and_get_req (ub , ubq , tag , 0 );
19571967 if (!req )
19581968 return - EINVAL ;
@@ -1968,8 +1978,17 @@ static int ublk_register_io_buf(struct io_uring_cmd *cmd,
19681978}
19691979
19701980static int ublk_unregister_io_buf (struct io_uring_cmd * cmd ,
1981+ const struct ublk_queue * ubq , unsigned int tag ,
19711982 unsigned int index , unsigned int issue_flags )
19721983{
1984+ const struct ublk_io * io = & ubq -> ios [tag ];
1985+
1986+ if (!ublk_support_zero_copy (ubq ))
1987+ return - EINVAL ;
1988+
1989+ if (!(io -> flags & UBLK_IO_FLAG_OWNED_BY_SRV ))
1990+ return - EINVAL ;
1991+
19731992 return io_buffer_unregister_bvec (cmd , index , issue_flags );
19741993}
19751994
@@ -2073,7 +2092,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
20732092 case UBLK_IO_REGISTER_IO_BUF :
20742093 return ublk_register_io_buf (cmd , ubq , tag , ub_cmd -> addr , issue_flags );
20752094 case UBLK_IO_UNREGISTER_IO_BUF :
2076- return ublk_unregister_io_buf (cmd , ub_cmd -> addr , issue_flags );
2095+ return ublk_unregister_io_buf (cmd , ubq , tag , ub_cmd -> addr , issue_flags );
20772096 case UBLK_IO_FETCH_REQ :
20782097 ret = ublk_fetch (cmd , ubq , io , ub_cmd -> addr );
20792098 if (ret )
@@ -2125,13 +2144,10 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
21252144}
21262145
21272146static inline struct request * __ublk_check_and_get_req (struct ublk_device * ub ,
2128- struct ublk_queue * ubq , int tag , size_t offset )
2147+ const struct ublk_queue * ubq , int tag , size_t offset )
21292148{
21302149 struct request * req ;
21312150
2132- if (!ublk_need_req_ref (ubq ))
2133- return NULL ;
2134-
21352151 req = blk_mq_tag_to_rq (ub -> tag_set .tags [ubq -> q_id ], tag );
21362152 if (!req )
21372153 return NULL ;
@@ -2245,6 +2261,9 @@ static struct request *ublk_check_and_get_req(struct kiocb *iocb,
22452261 if (!ubq )
22462262 return ERR_PTR (- EINVAL );
22472263
2264+ if (!ublk_support_user_copy (ubq ))
2265+ return ERR_PTR (- EACCES );
2266+
22482267 if (tag >= ubq -> q_depth )
22492268 return ERR_PTR (- EINVAL );
22502269
@@ -2783,13 +2802,18 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
27832802 ub -> dev_info .flags |= UBLK_F_CMD_IOCTL_ENCODE |
27842803 UBLK_F_URING_CMD_COMP_IN_TASK ;
27852804
2786- /* GET_DATA isn't needed any more with USER_COPY */
2787- if (ublk_dev_is_user_copy ( ub ))
2805+ /* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */
2806+ if (ub -> dev_info . flags & ( UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY ))
27882807 ub -> dev_info .flags &= ~UBLK_F_NEED_GET_DATA ;
27892808
2790- /* Zoned storage support requires user copy feature */
2809+ /*
2810+ * Zoned storage support requires reuse `ublksrv_io_cmd->addr` for
2811+ * returning write_append_lba, which is only allowed in case of
2812+ * user copy or zero copy
2813+ */
27912814 if (ublk_dev_is_zoned (ub ) &&
2792- (!IS_ENABLED (CONFIG_BLK_DEV_ZONED ) || !ublk_dev_is_user_copy (ub ))) {
2815+ (!IS_ENABLED (CONFIG_BLK_DEV_ZONED ) || !(ub -> dev_info .flags &
2816+ (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY )))) {
27932817 ret = - EINVAL ;
27942818 goto out_free_dev_number ;
27952819 }
0 commit comments