47
47
#define UBLK_MINORS (1U << MINORBITS)
48
48
49
49
/* All UBLK_F_* have to be included into UBLK_F_ALL */
50
- #define UBLK_F_ALL (UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_URING_CMD_COMP_IN_TASK)
50
+ #define UBLK_F_ALL (UBLK_F_SUPPORT_ZERO_COPY \
51
+ | UBLK_F_URING_CMD_COMP_IN_TASK \
52
+ | UBLK_F_NEED_GET_DATA)
51
53
52
54
/* All UBLK_PARAM_TYPE_* should be included here */
53
55
#define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD)
@@ -89,6 +91,15 @@ struct ublk_uring_cmd_pdu {
89
91
*/
90
92
#define UBLK_IO_FLAG_ABORTED 0x04
91
93
94
+ /*
95
+ * UBLK_IO_FLAG_NEED_GET_DATA is set because IO command requires
96
+ * get data buffer address from ublksrv.
97
+ *
98
+ * Then, bio data could be copied into this data buffer for a WRITE request
99
+ * after the IO command is issued again and UBLK_IO_FLAG_NEED_GET_DATA is unset.
100
+ */
101
+ #define UBLK_IO_FLAG_NEED_GET_DATA 0x08
102
+
92
103
struct ublk_io {
93
104
/* userspace buffer address from io cmd */
94
105
__u64 addr ;
@@ -262,6 +273,13 @@ static inline bool ublk_can_use_task_work(const struct ublk_queue *ubq)
262
273
return false;
263
274
}
264
275
276
+ static inline bool ublk_need_get_data (const struct ublk_queue * ubq )
277
+ {
278
+ if (ubq -> flags & UBLK_F_NEED_GET_DATA )
279
+ return true;
280
+ return false;
281
+ }
282
+
265
283
static struct ublk_device * ublk_get_device (struct ublk_device * ub )
266
284
{
267
285
if (kobject_get_unless_zero (& ub -> cdev_dev .kobj ))
@@ -603,6 +621,21 @@ static void __ublk_fail_req(struct ublk_io *io, struct request *req)
603
621
}
604
622
}
605
623
624
+ static void ubq_complete_io_cmd (struct ublk_io * io , int res )
625
+ {
626
+ /* mark this cmd owned by ublksrv */
627
+ io -> flags |= UBLK_IO_FLAG_OWNED_BY_SRV ;
628
+
629
+ /*
630
+ * clear ACTIVE since we are done with this sqe/cmd slot
631
+ * We can only accept io cmd in case of being not active.
632
+ */
633
+ io -> flags &= ~UBLK_IO_FLAG_ACTIVE ;
634
+
635
+ /* tell ublksrv one io request is coming */
636
+ io_uring_cmd_done (io -> cmd , res , 0 );
637
+ }
638
+
606
639
#define UBLK_REQUEUE_DELAY_MS 3
607
640
608
641
static inline void __ublk_rq_task_work (struct request * req )
@@ -625,6 +658,30 @@ static inline void __ublk_rq_task_work(struct request *req)
625
658
return ;
626
659
}
627
660
661
+ if (ublk_need_get_data (ubq ) &&
662
+ (req_op (req ) == REQ_OP_WRITE ||
663
+ req_op (req ) == REQ_OP_FLUSH )) {
664
+ /*
665
+ * We have not handled UBLK_IO_NEED_GET_DATA command yet,
666
+ * so immepdately pass UBLK_IO_RES_NEED_GET_DATA to ublksrv
667
+ * and notify it.
668
+ */
669
+ if (!(io -> flags & UBLK_IO_FLAG_NEED_GET_DATA )) {
670
+ io -> flags |= UBLK_IO_FLAG_NEED_GET_DATA ;
671
+ pr_devel ("%s: need get data. op %d, qid %d tag %d io_flags %x\n" ,
672
+ __func__ , io -> cmd -> cmd_op , ubq -> q_id ,
673
+ req -> tag , io -> flags );
674
+ ubq_complete_io_cmd (io , UBLK_IO_RES_NEED_GET_DATA );
675
+ return ;
676
+ }
677
+ /*
678
+ * We have handled UBLK_IO_NEED_GET_DATA command,
679
+ * so clear UBLK_IO_FLAG_NEED_GET_DATA now and just
680
+ * do the copy work.
681
+ */
682
+ io -> flags &= ~UBLK_IO_FLAG_NEED_GET_DATA ;
683
+ }
684
+
628
685
mapped_bytes = ublk_map_io (ubq , req , io );
629
686
630
687
/* partially mapped, update io descriptor */
@@ -647,17 +704,7 @@ static inline void __ublk_rq_task_work(struct request *req)
647
704
mapped_bytes >> 9 ;
648
705
}
649
706
650
- /* mark this cmd owned by ublksrv */
651
- io -> flags |= UBLK_IO_FLAG_OWNED_BY_SRV ;
652
-
653
- /*
654
- * clear ACTIVE since we are done with this sqe/cmd slot
655
- * We can only accept io cmd in case of being not active.
656
- */
657
- io -> flags &= ~UBLK_IO_FLAG_ACTIVE ;
658
-
659
- /* tell ublksrv one io request is coming */
660
- io_uring_cmd_done (io -> cmd , UBLK_IO_RES_OK , 0 );
707
+ ubq_complete_io_cmd (io , UBLK_IO_RES_OK );
661
708
}
662
709
663
710
static void ublk_rq_task_work_cb (struct io_uring_cmd * cmd )
@@ -946,6 +993,25 @@ static void ublk_mark_io_ready(struct ublk_device *ub, struct ublk_queue *ubq)
946
993
mutex_unlock (& ub -> mutex );
947
994
}
948
995
996
+ static void ublk_handle_need_get_data (struct ublk_device * ub , int q_id ,
997
+ int tag , struct io_uring_cmd * cmd )
998
+ {
999
+ struct ublk_queue * ubq = ublk_get_queue (ub , q_id );
1000
+ struct request * req = blk_mq_tag_to_rq (ub -> tag_set .tags [q_id ], tag );
1001
+
1002
+ if (ublk_can_use_task_work (ubq )) {
1003
+ struct ublk_rq_data * data = blk_mq_rq_to_pdu (req );
1004
+
1005
+ /* should not fail since we call it just in ubq->ubq_daemon */
1006
+ task_work_add (ubq -> ubq_daemon , & data -> work , TWA_SIGNAL_NO_IPI );
1007
+ } else {
1008
+ struct ublk_uring_cmd_pdu * pdu = ublk_get_uring_cmd_pdu (cmd );
1009
+
1010
+ pdu -> req = req ;
1011
+ io_uring_cmd_complete_in_task (cmd , ublk_rq_task_work_cb );
1012
+ }
1013
+ }
1014
+
949
1015
static int ublk_ch_uring_cmd (struct io_uring_cmd * cmd , unsigned int issue_flags )
950
1016
{
951
1017
struct ublksrv_io_cmd * ub_cmd = (struct ublksrv_io_cmd * )cmd -> cmd ;
@@ -984,6 +1050,14 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
984
1050
goto out ;
985
1051
}
986
1052
1053
+ /*
1054
+ * ensure that the user issues UBLK_IO_NEED_GET_DATA
1055
+ * iff the driver have set the UBLK_IO_FLAG_NEED_GET_DATA.
1056
+ */
1057
+ if ((!!(io -> flags & UBLK_IO_FLAG_NEED_GET_DATA ))
1058
+ ^ (cmd_op == UBLK_IO_NEED_GET_DATA ))
1059
+ goto out ;
1060
+
987
1061
switch (cmd_op ) {
988
1062
case UBLK_IO_FETCH_REQ :
989
1063
/* UBLK_IO_FETCH_REQ is only allowed before queue is setup */
@@ -1017,6 +1091,14 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
1017
1091
io -> cmd = cmd ;
1018
1092
ublk_commit_completion (ub , ub_cmd );
1019
1093
break ;
1094
+ case UBLK_IO_NEED_GET_DATA :
1095
+ if (!(io -> flags & UBLK_IO_FLAG_OWNED_BY_SRV ))
1096
+ goto out ;
1097
+ io -> addr = ub_cmd -> addr ;
1098
+ io -> cmd = cmd ;
1099
+ io -> flags |= UBLK_IO_FLAG_ACTIVE ;
1100
+ ublk_handle_need_get_data (ub , ub_cmd -> q_id , ub_cmd -> tag , cmd );
1101
+ break ;
1020
1102
default :
1021
1103
goto out ;
1022
1104
}
0 commit comments