@@ -420,9 +420,12 @@ static int ublk_queue_init(struct ublk_queue *q)
420420 q -> cmd_inflight = 0 ;
421421 q -> tid = gettid ();
422422
423- if (dev -> dev_info .flags & UBLK_F_SUPPORT_ZERO_COPY ) {
423+ if (dev -> dev_info .flags & ( UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_AUTO_BUF_REG ) ) {
424424 q -> state |= UBLKSRV_NO_BUF ;
425- q -> state |= UBLKSRV_ZC ;
425+ if (dev -> dev_info .flags & UBLK_F_SUPPORT_ZERO_COPY )
426+ q -> state |= UBLKSRV_ZC ;
427+ if (dev -> dev_info .flags & UBLK_F_AUTO_BUF_REG )
428+ q -> state |= UBLKSRV_AUTO_BUF_REG ;
426429 }
427430
428431 cmd_buf_size = ublk_queue_cmd_buf_sz (q );
@@ -461,7 +464,7 @@ static int ublk_queue_init(struct ublk_queue *q)
461464 goto fail ;
462465 }
463466
464- if (dev -> dev_info .flags & UBLK_F_SUPPORT_ZERO_COPY ) {
467+ if (dev -> dev_info .flags & ( UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_AUTO_BUF_REG ) ) {
465468 ret = io_uring_register_buffers_sparse (& q -> ring , q -> q_depth );
466469 if (ret ) {
467470 ublk_err ("ublk dev %d queue %d register spare buffers failed %d" ,
@@ -525,6 +528,18 @@ static void ublk_dev_unprep(struct ublk_dev *dev)
525528 close (dev -> fds [0 ]);
526529}
527530
531+ static void ublk_set_auto_buf_reg (struct io_uring_sqe * sqe ,
532+ unsigned short buf_idx ,
533+ unsigned char flags )
534+ {
535+ struct ublk_auto_buf_reg buf = {
536+ .index = buf_idx ,
537+ .flags = flags ,
538+ };
539+
540+ sqe -> addr = ublk_auto_buf_reg_to_sqe_addr (& buf );
541+ }
542+
528543int ublk_queue_io_cmd (struct ublk_queue * q , struct ublk_io * io , unsigned tag )
529544{
530545 struct ublksrv_io_cmd * cmd ;
@@ -579,6 +594,9 @@ int ublk_queue_io_cmd(struct ublk_queue *q, struct ublk_io *io, unsigned tag)
579594 else
580595 cmd -> addr = 0 ;
581596
597+ if (q -> state & UBLKSRV_AUTO_BUF_REG )
598+ ublk_set_auto_buf_reg (sqe [0 ], tag , 0 );
599+
582600 user_data = build_user_data (tag , _IOC_NR (cmd_op ), 0 , 0 );
583601 io_uring_sqe_set_data64 (sqe [0 ], user_data );
584602
@@ -1206,6 +1224,7 @@ static int cmd_dev_get_features(void)
12061224 [const_ilog2 (UBLK_F_USER_COPY )] = "USER_COPY" ,
12071225 [const_ilog2 (UBLK_F_ZONED )] = "ZONED" ,
12081226 [const_ilog2 (UBLK_F_USER_RECOVERY_FAIL_IO )] = "RECOVERY_FAIL_IO" ,
1227+ [const_ilog2 (UBLK_F_AUTO_BUF_REG )] = "AUTO_BUF_REG" ,
12091228 };
12101229 struct ublk_dev * dev ;
12111230 __u64 features = 0 ;
@@ -1245,7 +1264,7 @@ static void __cmd_create_help(char *exe, bool recovery)
12451264
12461265 printf ("%s %s -t [null|loop|stripe|fault_inject] [-q nr_queues] [-d depth] [-n dev_id]\n" ,
12471266 exe , recovery ? "recover" : "add" );
1248- printf ("\t[--foreground] [--quiet] [-z] [--debug_mask mask] [-r 0|1 ] [-g]\n" );
1267+ printf ("\t[--foreground] [--quiet] [-z] [--auto_zc] [-- debug_mask mask] [-r 0|1 ] [-g]\n" );
12491268 printf ("\t[-e 0|1 ] [-i 0|1]\n" );
12501269 printf ("\t[target options] [backfile1] [backfile2] ...\n" );
12511270 printf ("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n" );
@@ -1300,6 +1319,7 @@ int main(int argc, char *argv[])
13001319 { "recovery_fail_io" , 1 , NULL , 'e' },
13011320 { "recovery_reissue" , 1 , NULL , 'i' },
13021321 { "get_data" , 1 , NULL , 'g' },
1322+ { "auto_zc" , 0 , NULL , 0 },
13031323 { 0 , 0 , 0 , 0 }
13041324 };
13051325 const struct ublk_tgt_ops * ops = NULL ;
@@ -1368,6 +1388,8 @@ int main(int argc, char *argv[])
13681388 ublk_dbg_mask = 0 ;
13691389 if (!strcmp (longopts [option_idx ].name , "foreground" ))
13701390 ctx .fg = 1 ;
1391+ if (!strcmp (longopts [option_idx ].name , "auto_zc" ))
1392+ ctx .flags |= UBLK_F_AUTO_BUF_REG ;
13711393 break ;
13721394 case '?' :
13731395 /*
0 commit comments