@@ -432,7 +432,7 @@ static void ublk_thread_deinit(struct ublk_thread *t)
432432 }
433433}
434434
435- static int ublk_queue_init (struct ublk_queue * q , unsigned extra_flags )
435+ static int ublk_queue_init (struct ublk_queue * q , unsigned long long extra_flags )
436436{
437437 struct ublk_dev * dev = q -> dev ;
438438 int depth = dev -> dev_info .queue_depth ;
@@ -446,6 +446,9 @@ static int ublk_queue_init(struct ublk_queue *q, unsigned extra_flags)
446446 q -> flags = dev -> dev_info .flags ;
447447 q -> flags |= extra_flags ;
448448
449+ /* Cache fd in queue for fast path access */
450+ q -> ublk_fd = dev -> fds [0 ];
451+
449452 cmd_buf_size = ublk_queue_cmd_buf_sz (q );
450453 off = UBLKSRV_CMD_BUF_OFFSET + q -> q_id * ublk_queue_max_cmd_buf_sz ();
451454 q -> io_cmd_buf = mmap (0 , cmd_buf_size , PROT_READ ,
@@ -481,9 +484,10 @@ static int ublk_queue_init(struct ublk_queue *q, unsigned extra_flags)
481484 return - ENOMEM ;
482485}
483486
484- static int ublk_thread_init (struct ublk_thread * t )
487+ static int ublk_thread_init (struct ublk_thread * t , unsigned long long extra_flags )
485488{
486489 struct ublk_dev * dev = t -> dev ;
490+ unsigned long long flags = dev -> dev_info .flags | extra_flags ;
487491 int ring_depth = dev -> tgt .sq_depth , cq_depth = dev -> tgt .cq_depth ;
488492 int ret ;
489493
@@ -512,7 +516,17 @@ static int ublk_thread_init(struct ublk_thread *t)
512516
513517 io_uring_register_ring_fd (& t -> ring );
514518
515- ret = io_uring_register_files (& t -> ring , dev -> fds , dev -> nr_fds );
519+ if (flags & UBLKS_Q_NO_UBLK_FIXED_FD ) {
520+ /* Register only backing files starting from index 1, exclude ublk control device */
521+ if (dev -> nr_fds > 1 ) {
522+ ret = io_uring_register_files (& t -> ring , & dev -> fds [1 ], dev -> nr_fds - 1 );
523+ } else {
524+ /* No backing files to register, skip file registration */
525+ ret = 0 ;
526+ }
527+ } else {
528+ ret = io_uring_register_files (& t -> ring , dev -> fds , dev -> nr_fds );
529+ }
516530 if (ret ) {
517531 ublk_err ("ublk dev %d thread %d register files failed %d\n" ,
518532 t -> dev -> dev_info .dev_id , t -> idx , ret );
@@ -626,9 +640,12 @@ int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
626640
627641 /* These fields should be written once, never change */
628642 ublk_set_sqe_cmd_op (sqe [0 ], cmd_op );
629- sqe [0 ]-> fd = 0 ; /* dev->fds[0] */
643+ sqe [0 ]-> fd = ublk_get_registered_fd ( q , 0 ) ; /* dev->fds[0] */
630644 sqe [0 ]-> opcode = IORING_OP_URING_CMD ;
631- sqe [0 ]-> flags = IOSQE_FIXED_FILE ;
645+ if (q -> flags & UBLKS_Q_NO_UBLK_FIXED_FD )
646+ sqe [0 ]-> flags = 0 ; /* Use raw FD, not fixed file */
647+ else
648+ sqe [0 ]-> flags = IOSQE_FIXED_FILE ;
632649 sqe [0 ]-> rw_flags = 0 ;
633650 cmd -> tag = io -> tag ;
634651 cmd -> q_id = q -> q_id ;
@@ -832,6 +849,7 @@ struct ublk_thread_info {
832849 unsigned idx ;
833850 sem_t * ready ;
834851 cpu_set_t * affinity ;
852+ unsigned long long extra_flags ;
835853};
836854
837855static void * ublk_io_handler_fn (void * data )
@@ -844,7 +862,7 @@ static void *ublk_io_handler_fn(void *data)
844862 t -> dev = info -> dev ;
845863 t -> idx = info -> idx ;
846864
847- ret = ublk_thread_init (t );
865+ ret = ublk_thread_init (t , info -> extra_flags );
848866 if (ret ) {
849867 ublk_err ("ublk dev %d thread %u init failed\n" ,
850868 dev_id , t -> idx );
@@ -934,6 +952,8 @@ static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev)
934952
935953 if (ctx -> auto_zc_fallback )
936954 extra_flags = UBLKS_Q_AUTO_BUF_REG_FALLBACK ;
955+ if (ctx -> no_ublk_fixed_fd )
956+ extra_flags |= UBLKS_Q_NO_UBLK_FIXED_FD ;
937957
938958 for (i = 0 ; i < dinfo -> nr_hw_queues ; i ++ ) {
939959 dev -> q [i ].dev = dev ;
@@ -951,6 +971,7 @@ static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev)
951971 tinfo [i ].dev = dev ;
952972 tinfo [i ].idx = i ;
953973 tinfo [i ].ready = & ready ;
974+ tinfo [i ].extra_flags = extra_flags ;
954975
955976 /*
956977 * If threads are not tied 1:1 to queues, setting thread
@@ -1471,7 +1492,7 @@ static void __cmd_create_help(char *exe, bool recovery)
14711492 printf ("%s %s -t [null|loop|stripe|fault_inject] [-q nr_queues] [-d depth] [-n dev_id]\n" ,
14721493 exe , recovery ? "recover" : "add" );
14731494 printf ("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1 ] [-g]\n" );
1474- printf ("\t[-e 0|1 ] [-i 0|1]\n" );
1495+ printf ("\t[-e 0|1 ] [-i 0|1] [--no_ublk_fixed_fd] \n" );
14751496 printf ("\t[--nthreads threads] [--per_io_tasks]\n" );
14761497 printf ("\t[target options] [backfile1] [backfile2] ...\n" );
14771498 printf ("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n" );
@@ -1534,6 +1555,7 @@ int main(int argc, char *argv[])
15341555 { "size" , 1 , NULL , 's' },
15351556 { "nthreads" , 1 , NULL , 0 },
15361557 { "per_io_tasks" , 0 , NULL , 0 },
1558+ { "no_ublk_fixed_fd" , 0 , NULL , 0 },
15371559 { 0 , 0 , 0 , 0 }
15381560 };
15391561 const struct ublk_tgt_ops * ops = NULL ;
@@ -1613,6 +1635,8 @@ int main(int argc, char *argv[])
16131635 ctx .nthreads = strtol (optarg , NULL , 10 );
16141636 if (!strcmp (longopts [option_idx ].name , "per_io_tasks" ))
16151637 ctx .per_io_tasks = 1 ;
1638+ if (!strcmp (longopts [option_idx ].name , "no_ublk_fixed_fd" ))
1639+ ctx .no_ublk_fixed_fd = 1 ;
16161640 break ;
16171641 case '?' :
16181642 /*
0 commit comments