@@ -5238,23 +5238,29 @@ static int ublk_char_dev_permission(struct ublk_device *ub,
52385238}
52395239
52405240/*
5241- * Drain inflight I/O and quiesce the queue. Freeze drains all inflight
5242- * requests, quiesce_nowait marks the queue so no new requests dispatch,
5243- * then unfreeze allows new submissions (which won't dispatch due to
5244- * quiesce). This keeps freeze and ub->mutex non-nested.
5245- */
5246- static void ublk_quiesce_and_release (struct gendisk * disk )
5241+ * Lock for maple tree modification: acquire ub->mutex, then freeze queue
5242+ * if device is started. If device is not yet started, only mutex is
5243+ * needed since no I/O path can access the tree.
5244+ *
5245+ * This ordering (mutex -> freeze) is safe because ublk_stop_dev_unlocked()
5246+ * already holds ub->mutex when calling del_gendisk() which freezes the queue.
5247+ */
5248+ static unsigned int ublk_lock_buf_tree (struct ublk_device * ub )
52475249{
5248- unsigned int memflags ;
5250+ unsigned int memflags = 0 ;
5251+
5252+ mutex_lock (& ub -> mutex );
5253+ if (ub -> ub_disk )
5254+ memflags = blk_mq_freeze_queue (ub -> ub_disk -> queue );
52495255
5250- memflags = blk_mq_freeze_queue (disk -> queue );
5251- blk_mq_quiesce_queue_nowait (disk -> queue );
5252- blk_mq_unfreeze_queue (disk -> queue , memflags );
5256+ return memflags ;
52535257}
52545258
5255- static void ublk_unquiesce_and_resume (struct gendisk * disk )
5259+ static void ublk_unlock_buf_tree (struct ublk_device * ub , unsigned int memflags )
52565260{
5257- blk_mq_unquiesce_queue (disk -> queue );
5261+ if (ub -> ub_disk )
5262+ blk_mq_unfreeze_queue (ub -> ub_disk -> queue , memflags );
5263+ mutex_unlock (& ub -> mutex );
52585264}
52595265
52605266/* Erase coalesced PFN ranges from the maple tree matching buf_index */
@@ -5327,7 +5333,7 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
53275333 unsigned long addr , size , nr_pages ;
53285334 struct page * * pages = NULL ;
53295335 unsigned int gup_flags ;
5330- struct gendisk * disk ;
5336+ unsigned int memflags ;
53315337 long pinned ;
53325338 int index ;
53335339 int ret ;
@@ -5354,16 +5360,10 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
53545360 !PAGE_ALIGNED (size ) || !PAGE_ALIGNED (addr ))
53555361 return - EINVAL ;
53565362
5357- disk = ublk_get_disk (ub );
5358- if (!disk )
5359- return - ENODEV ;
5360-
5361- /* Pin pages before quiescing (may sleep) */
5363+ /* Pin pages before any locks (may sleep) */
53625364 pages = kvmalloc_array (nr_pages , sizeof (* pages ), GFP_KERNEL );
5363- if (!pages ) {
5364- ret = - ENOMEM ;
5365- goto put_disk ;
5366- }
5365+ if (!pages )
5366+ return - ENOMEM ;
53675367
53685368 gup_flags = FOLL_LONGTERM ;
53695369 if (!(buf_reg .flags & UBLK_SHMEM_BUF_READ_ONLY ))
@@ -5379,14 +5379,7 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
53795379 goto err_unpin ;
53805380 }
53815381
5382- /*
5383- * Drain inflight I/O and quiesce the queue so no new requests
5384- * are dispatched while we modify the maple tree. Keep freeze
5385- * and mutex non-nested to avoid lock dependency.
5386- */
5387- ublk_quiesce_and_release (disk );
5388-
5389- mutex_lock (& ub -> mutex );
5382+ memflags = ublk_lock_buf_tree (ub );
53905383
53915384 index = ida_alloc_max (& ub -> buf_ida , USHRT_MAX , GFP_KERNEL );
53925385 if (index < 0 ) {
@@ -5400,22 +5393,16 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
54005393 goto err_unlock ;
54015394 }
54025395
5403- mutex_unlock (& ub -> mutex );
5404-
5396+ ublk_unlock_buf_tree (ub , memflags );
54055397 kvfree (pages );
5406- ublk_unquiesce_and_resume (disk );
5407- ublk_put_disk (disk );
54085398 return index ;
54095399
54105400err_unlock :
5411- mutex_unlock (& ub -> mutex );
5412- ublk_unquiesce_and_resume (disk );
5401+ ublk_unlock_buf_tree (ub , memflags );
54135402err_unpin :
54145403 unpin_user_pages (pages , pinned );
54155404err_free_pages :
54165405 kvfree (pages );
5417- put_disk :
5418- ublk_put_disk (disk );
54195406 return ret ;
54205407}
54215408
@@ -5459,7 +5446,7 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54595446 struct ublksrv_ctrl_cmd * header )
54605447{
54615448 int index = (int )header -> data [0 ];
5462- struct gendisk * disk ;
5449+ unsigned int memflags ;
54635450 int ret ;
54645451
54655452 if (!ublk_dev_support_shmem_zc (ub ))
@@ -5468,23 +5455,13 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54685455 if (index < 0 || index > USHRT_MAX )
54695456 return - EINVAL ;
54705457
5471- disk = ublk_get_disk (ub );
5472- if (!disk )
5473- return - ENODEV ;
5474-
5475- /* Drain inflight I/O before modifying the maple tree */
5476- ublk_quiesce_and_release (disk );
5477-
5478- mutex_lock (& ub -> mutex );
5458+ memflags = ublk_lock_buf_tree (ub );
54795459
54805460 ret = __ublk_ctrl_unreg_buf (ub , index );
54815461 if (!ret )
54825462 ida_free (& ub -> buf_ida , index );
54835463
5484- mutex_unlock (& ub -> mutex );
5485-
5486- ublk_unquiesce_and_resume (disk );
5487- ublk_put_disk (disk );
5464+ ublk_unlock_buf_tree (ub , memflags );
54885465 return ret ;
54895466}
54905467
0 commit comments