@@ -46,11 +46,20 @@ int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q)
4646 if (!dev -> zones )
4747 return - ENOMEM ;
4848
49- spin_lock_init (& dev -> zone_dev_lock );
50- dev -> zone_locks = bitmap_zalloc (dev -> nr_zones , GFP_KERNEL );
51- if (!dev -> zone_locks ) {
52- kvfree (dev -> zones );
53- return - ENOMEM ;
49+ /*
50+ * With memory backing, the zone_lock spinlock needs to be temporarily
51+ * released to avoid scheduling in atomic context. To guarantee zone
52+ * information protection, use a bitmap to lock zones with
53+ * wait_on_bit_lock_io(). Sleeping on the lock is OK as memory backing
54+ * implies that the queue is marked with BLK_MQ_F_BLOCKING.
55+ */
56+ spin_lock_init (& dev -> zone_lock );
57+ if (dev -> memory_backed ) {
58+ dev -> zone_locks = bitmap_zalloc (dev -> nr_zones , GFP_KERNEL );
59+ if (!dev -> zone_locks ) {
60+ kvfree (dev -> zones );
61+ return - ENOMEM ;
62+ }
5463 }
5564
5665 if (dev -> zone_nr_conv >= dev -> nr_zones ) {
@@ -137,12 +146,17 @@ void null_free_zoned_dev(struct nullb_device *dev)
137146
138147static inline void null_lock_zone (struct nullb_device * dev , unsigned int zno )
139148{
140- wait_on_bit_lock_io (dev -> zone_locks , zno , TASK_UNINTERRUPTIBLE );
149+ if (dev -> memory_backed )
150+ wait_on_bit_lock_io (dev -> zone_locks , zno , TASK_UNINTERRUPTIBLE );
151+ spin_lock_irq (& dev -> zone_lock );
141152}
142153
143154static inline void null_unlock_zone (struct nullb_device * dev , unsigned int zno )
144155{
145- clear_and_wake_up_bit (zno , dev -> zone_locks );
156+ spin_unlock_irq (& dev -> zone_lock );
157+
158+ if (dev -> memory_backed )
159+ clear_and_wake_up_bit (zno , dev -> zone_locks );
146160}
147161
148162int null_report_zones (struct gendisk * disk , sector_t sector ,
@@ -322,7 +336,6 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
322336 return null_process_cmd (cmd , REQ_OP_WRITE , sector , nr_sectors );
323337
324338 null_lock_zone (dev , zno );
325- spin_lock (& dev -> zone_dev_lock );
326339
327340 switch (zone -> cond ) {
328341 case BLK_ZONE_COND_FULL :
@@ -375,9 +388,17 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
375388 if (zone -> cond != BLK_ZONE_COND_EXP_OPEN )
376389 zone -> cond = BLK_ZONE_COND_IMP_OPEN ;
377390
378- spin_unlock (& dev -> zone_dev_lock );
391+ /*
392+ * Memory backing allocation may sleep: release the zone_lock spinlock
393+ * to avoid scheduling in atomic context. Zone operation atomicity is
394+ * still guaranteed through the zone_locks bitmap.
395+ */
396+ if (dev -> memory_backed )
397+ spin_unlock_irq (& dev -> zone_lock );
379398 ret = null_process_cmd (cmd , REQ_OP_WRITE , sector , nr_sectors );
380- spin_lock (& dev -> zone_dev_lock );
399+ if (dev -> memory_backed )
400+ spin_lock_irq (& dev -> zone_lock );
401+
381402 if (ret != BLK_STS_OK )
382403 goto unlock ;
383404
@@ -392,7 +413,6 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
392413 ret = BLK_STS_OK ;
393414
394415unlock :
395- spin_unlock (& dev -> zone_dev_lock );
396416 null_unlock_zone (dev , zno );
397417
398418 return ret ;
@@ -516,9 +536,7 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
516536 null_lock_zone (dev , i );
517537 zone = & dev -> zones [i ];
518538 if (zone -> cond != BLK_ZONE_COND_EMPTY ) {
519- spin_lock (& dev -> zone_dev_lock );
520539 null_reset_zone (dev , zone );
521- spin_unlock (& dev -> zone_dev_lock );
522540 trace_nullb_zone_op (cmd , i , zone -> cond );
523541 }
524542 null_unlock_zone (dev , i );
@@ -530,7 +548,6 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
530548 zone = & dev -> zones [zone_no ];
531549
532550 null_lock_zone (dev , zone_no );
533- spin_lock (& dev -> zone_dev_lock );
534551
535552 switch (op ) {
536553 case REQ_OP_ZONE_RESET :
@@ -550,8 +567,6 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
550567 break ;
551568 }
552569
553- spin_unlock (& dev -> zone_dev_lock );
554-
555570 if (ret == BLK_STS_OK )
556571 trace_nullb_zone_op (cmd , zone_no , zone -> cond );
557572
0 commit comments