@@ -596,6 +596,38 @@ static void ublk_set_auto_buf_reg(const struct ublk_queue *q,
596596 sqe -> addr = ublk_auto_buf_reg_to_sqe_addr (& buf );
597597}
598598
599+ /* Copy in pieces to test the buffer offset logic */
600+ #define UBLK_USER_COPY_LEN 2048
601+
602+ static void ublk_user_copy (const struct ublk_io * io , __u8 match_ublk_op )
603+ {
604+ const struct ublk_queue * q = ublk_io_to_queue (io );
605+ const struct ublksrv_io_desc * iod = ublk_get_iod (q , io -> tag );
606+ __u64 off = ublk_user_copy_offset (q -> q_id , io -> tag );
607+ __u8 ublk_op = ublksrv_get_op (iod );
608+ __u32 len = iod -> nr_sectors << 9 ;
609+ void * addr = io -> buf_addr ;
610+
611+ if (ublk_op != match_ublk_op )
612+ return ;
613+
614+ while (len ) {
615+ __u32 copy_len = min (len , UBLK_USER_COPY_LEN );
616+ ssize_t copied ;
617+
618+ if (ublk_op == UBLK_IO_OP_WRITE )
619+ copied = pread (q -> ublk_fd , addr , copy_len , off );
620+ else if (ublk_op == UBLK_IO_OP_READ )
621+ copied = pwrite (q -> ublk_fd , addr , copy_len , off );
622+ else
623+ assert (0 );
624+ assert (copied == (ssize_t )copy_len );
625+ addr += copy_len ;
626+ off += copy_len ;
627+ len -= copy_len ;
628+ }
629+ }
630+
599631int ublk_queue_io_cmd (struct ublk_thread * t , struct ublk_io * io )
600632{
601633 struct ublk_queue * q = ublk_io_to_queue (io );
@@ -618,9 +650,12 @@ int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
618650
619651 if (io -> flags & UBLKS_IO_NEED_GET_DATA )
620652 cmd_op = UBLK_U_IO_NEED_GET_DATA ;
621- else if (io -> flags & UBLKS_IO_NEED_COMMIT_RQ_COMP )
653+ else if (io -> flags & UBLKS_IO_NEED_COMMIT_RQ_COMP ) {
654+ if (ublk_queue_use_user_copy (q ))
655+ ublk_user_copy (io , UBLK_IO_OP_READ );
656+
622657 cmd_op = UBLK_U_IO_COMMIT_AND_FETCH_REQ ;
623- else if (io -> flags & UBLKS_IO_NEED_FETCH_RQ )
658+ } else if (io -> flags & UBLKS_IO_NEED_FETCH_RQ )
624659 cmd_op = UBLK_U_IO_FETCH_REQ ;
625660
626661 if (io_uring_sq_space_left (& t -> ring ) < 1 )
@@ -649,7 +684,7 @@ int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
649684 sqe [0 ]-> rw_flags = 0 ;
650685 cmd -> tag = io -> tag ;
651686 cmd -> q_id = q -> q_id ;
652- if (!ublk_queue_no_buf (q ))
687+ if (!ublk_queue_no_buf (q ) && ! ublk_queue_use_user_copy ( q ) )
653688 cmd -> addr = (__u64 ) (uintptr_t ) io -> buf_addr ;
654689 else
655690 cmd -> addr = 0 ;
@@ -751,6 +786,10 @@ static void ublk_handle_uring_cmd(struct ublk_thread *t,
751786
752787 if (cqe -> res == UBLK_IO_RES_OK ) {
753788 assert (tag < q -> q_depth );
789+
790+ if (ublk_queue_use_user_copy (q ))
791+ ublk_user_copy (io , UBLK_IO_OP_WRITE );
792+
754793 if (q -> tgt_ops -> queue_io )
755794 q -> tgt_ops -> queue_io (t , q , tag );
756795 } else if (cqe -> res == UBLK_IO_RES_NEED_GET_DATA ) {
@@ -1507,7 +1546,7 @@ static void __cmd_create_help(char *exe, bool recovery)
15071546
15081547 printf ("%s %s -t [null|loop|stripe|fault_inject] [-q nr_queues] [-d depth] [-n dev_id]\n" ,
15091548 exe , recovery ? "recover" : "add" );
1510- printf ("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1 ] [-g]\n" );
1549+ printf ("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1] [-g] [-u ]\n" );
15111550 printf ("\t[-e 0|1 ] [-i 0|1] [--no_ublk_fixed_fd]\n" );
15121551 printf ("\t[--nthreads threads] [--per_io_tasks]\n" );
15131552 printf ("\t[target options] [backfile1] [backfile2] ...\n" );
@@ -1568,6 +1607,7 @@ int main(int argc, char *argv[])
15681607 { "get_data" , 1 , NULL , 'g' },
15691608 { "auto_zc" , 0 , NULL , 0 },
15701609 { "auto_zc_fallback" , 0 , NULL , 0 },
1610+ { "user_copy" , 0 , NULL , 'u' },
15711611 { "size" , 1 , NULL , 's' },
15721612 { "nthreads" , 1 , NULL , 0 },
15731613 { "per_io_tasks" , 0 , NULL , 0 },
@@ -1593,7 +1633,7 @@ int main(int argc, char *argv[])
15931633
15941634 opterr = 0 ;
15951635 optind = 2 ;
1596- while ((opt = getopt_long (argc , argv , "t:n:d:q:r:e:i:s:gaz " ,
1636+ while ((opt = getopt_long (argc , argv , "t:n:d:q:r:e:i:s:gazu " ,
15971637 longopts , & option_idx )) != -1 ) {
15981638 switch (opt ) {
15991639 case 'a' :
@@ -1633,6 +1673,9 @@ int main(int argc, char *argv[])
16331673 case 'g' :
16341674 ctx .flags |= UBLK_F_NEED_GET_DATA ;
16351675 break ;
1676+ case 'u' :
1677+ ctx .flags |= UBLK_F_USER_COPY ;
1678+ break ;
16361679 case 's' :
16371680 ctx .size = strtoull (optarg , NULL , 10 );
16381681 break ;
0 commit comments