11// SPDX-License-Identifier: GPL-2.0
22#include <linux/vmalloc.h>
3+ #include <linux/bitmap.h>
34#include "null_blk.h"
45
56#define CREATE_TRACE_POINTS
@@ -45,6 +46,13 @@ int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q)
4546 if (!dev -> zones )
4647 return - ENOMEM ;
4748
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 ;
54+ }
55+
4856 if (dev -> zone_nr_conv >= dev -> nr_zones ) {
4957 dev -> zone_nr_conv = dev -> nr_zones - 1 ;
5058 pr_info ("changed the number of conventional zones to %u" ,
@@ -123,15 +131,26 @@ int null_register_zoned_dev(struct nullb *nullb)
123131
124132void null_free_zoned_dev (struct nullb_device * dev )
125133{
134+ bitmap_free (dev -> zone_locks );
126135 kvfree (dev -> zones );
127136}
128137
138+ static inline void null_lock_zone (struct nullb_device * dev , unsigned int zno )
139+ {
140+ wait_on_bit_lock_io (dev -> zone_locks , zno , TASK_UNINTERRUPTIBLE );
141+ }
142+
143+ static inline void null_unlock_zone (struct nullb_device * dev , unsigned int zno )
144+ {
145+ clear_and_wake_up_bit (zno , dev -> zone_locks );
146+ }
147+
129148int null_report_zones (struct gendisk * disk , sector_t sector ,
130149 unsigned int nr_zones , report_zones_cb cb , void * data )
131150{
132151 struct nullb * nullb = disk -> private_data ;
133152 struct nullb_device * dev = nullb -> dev ;
134- unsigned int first_zone , i ;
153+ unsigned int first_zone , i , zno ;
135154 struct blk_zone zone ;
136155 int error ;
137156
@@ -142,15 +161,18 @@ int null_report_zones(struct gendisk *disk, sector_t sector,
142161 nr_zones = min (nr_zones , dev -> nr_zones - first_zone );
143162 trace_nullb_report_zones (nullb , nr_zones );
144163
145- for (i = 0 ; i < nr_zones ; i ++ ) {
164+ zno = first_zone ;
165+ for (i = 0 ; i < nr_zones ; i ++ , zno ++ ) {
146166 /*
147167 * Stacked DM target drivers will remap the zone information by
148168 * modifying the zone information passed to the report callback.
149169 * So use a local copy to avoid corruption of the device zone
150170 * array.
151171 */
152- memcpy (& zone , & dev -> zones [first_zone + i ],
153- sizeof (struct blk_zone ));
172+ null_lock_zone (dev , zno );
173+ memcpy (& zone , & dev -> zones [zno ], sizeof (struct blk_zone ));
174+ null_unlock_zone (dev , zno );
175+
154176 error = cb (& zone , i , data );
155177 if (error )
156178 return error ;
@@ -159,6 +181,10 @@ int null_report_zones(struct gendisk *disk, sector_t sector,
159181 return nr_zones ;
160182}
161183
184+ /*
185+ * This is called in the case of memory backing from null_process_cmd()
186+ * with the target zone already locked.
187+ */
162188size_t null_zone_valid_read_len (struct nullb * nullb ,
163189 sector_t sector , unsigned int len )
164190{
@@ -295,22 +321,27 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
295321 if (zone -> type == BLK_ZONE_TYPE_CONVENTIONAL )
296322 return null_process_cmd (cmd , REQ_OP_WRITE , sector , nr_sectors );
297323
324+ null_lock_zone (dev , zno );
325+ spin_lock (& dev -> zone_dev_lock );
326+
298327 switch (zone -> cond ) {
299328 case BLK_ZONE_COND_FULL :
300329 /* Cannot write to a full zone */
301- return BLK_STS_IOERR ;
330+ ret = BLK_STS_IOERR ;
331+ goto unlock ;
302332 case BLK_ZONE_COND_EMPTY :
303333 case BLK_ZONE_COND_CLOSED :
304334 ret = null_check_zone_resources (dev , zone );
305335 if (ret != BLK_STS_OK )
306- return ret ;
336+ goto unlock ;
307337 break ;
308338 case BLK_ZONE_COND_IMP_OPEN :
309339 case BLK_ZONE_COND_EXP_OPEN :
310340 break ;
311341 default :
312342 /* Invalid zone condition */
313- return BLK_STS_IOERR ;
343+ ret = BLK_STS_IOERR ;
344+ goto unlock ;
314345 }
315346
316347 /*
@@ -326,11 +357,14 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
326357 else
327358 cmd -> rq -> __sector = sector ;
328359 } else if (sector != zone -> wp ) {
329- return BLK_STS_IOERR ;
360+ ret = BLK_STS_IOERR ;
361+ goto unlock ;
330362 }
331363
332- if (zone -> wp + nr_sectors > zone -> start + zone -> capacity )
333- return BLK_STS_IOERR ;
364+ if (zone -> wp + nr_sectors > zone -> start + zone -> capacity ) {
365+ ret = BLK_STS_IOERR ;
366+ goto unlock ;
367+ }
334368
335369 if (zone -> cond == BLK_ZONE_COND_CLOSED ) {
336370 dev -> nr_zones_closed -- ;
@@ -341,9 +375,11 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
341375 if (zone -> cond != BLK_ZONE_COND_EXP_OPEN )
342376 zone -> cond = BLK_ZONE_COND_IMP_OPEN ;
343377
378+ spin_unlock (& dev -> zone_dev_lock );
344379 ret = null_process_cmd (cmd , REQ_OP_WRITE , sector , nr_sectors );
380+ spin_lock (& dev -> zone_dev_lock );
345381 if (ret != BLK_STS_OK )
346- return ret ;
382+ goto unlock ;
347383
348384 zone -> wp += nr_sectors ;
349385 if (zone -> wp == zone -> start + zone -> capacity ) {
@@ -353,7 +389,13 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
353389 dev -> nr_zones_imp_open -- ;
354390 zone -> cond = BLK_ZONE_COND_FULL ;
355391 }
356- return BLK_STS_OK ;
392+ ret = BLK_STS_OK ;
393+
394+ unlock :
395+ spin_unlock (& dev -> zone_dev_lock );
396+ null_unlock_zone (dev , zno );
397+
398+ return ret ;
357399}
358400
359401static blk_status_t null_open_zone (struct nullb_device * dev , struct blk_zone * zone )
@@ -464,16 +506,33 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
464506 sector_t sector )
465507{
466508 struct nullb_device * dev = cmd -> nq -> dev ;
467- unsigned int zone_no = null_zone_no ( dev , sector ) ;
468- struct blk_zone * zone = & dev -> zones [ zone_no ] ;
469- blk_status_t ret = BLK_STS_OK ;
509+ unsigned int zone_no ;
510+ struct blk_zone * zone ;
511+ blk_status_t ret ;
470512 size_t i ;
471513
514+ if (op == REQ_OP_ZONE_RESET_ALL ) {
515+ for (i = dev -> zone_nr_conv ; i < dev -> nr_zones ; i ++ ) {
516+ null_lock_zone (dev , i );
517+ zone = & dev -> zones [i ];
518+ if (zone -> cond != BLK_ZONE_COND_EMPTY ) {
519+ spin_lock (& dev -> zone_dev_lock );
520+ null_reset_zone (dev , zone );
521+ spin_unlock (& dev -> zone_dev_lock );
522+ trace_nullb_zone_op (cmd , i , zone -> cond );
523+ }
524+ null_unlock_zone (dev , i );
525+ }
526+ return BLK_STS_OK ;
527+ }
528+
529+ zone_no = null_zone_no (dev , sector );
530+ zone = & dev -> zones [zone_no ];
531+
532+ null_lock_zone (dev , zone_no );
533+ spin_lock (& dev -> zone_dev_lock );
534+
472535 switch (op ) {
473- case REQ_OP_ZONE_RESET_ALL :
474- for (i = dev -> zone_nr_conv ; i < dev -> nr_zones ; i ++ )
475- null_reset_zone (dev , & dev -> zones [i ]);
476- break ;
477536 case REQ_OP_ZONE_RESET :
478537 ret = null_reset_zone (dev , zone );
479538 break ;
@@ -487,30 +546,46 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
487546 ret = null_finish_zone (dev , zone );
488547 break ;
489548 default :
490- return BLK_STS_NOTSUPP ;
549+ ret = BLK_STS_NOTSUPP ;
550+ break ;
491551 }
492552
553+ spin_unlock (& dev -> zone_dev_lock );
554+
493555 if (ret == BLK_STS_OK )
494556 trace_nullb_zone_op (cmd , zone_no , zone -> cond );
495557
558+ null_unlock_zone (dev , zone_no );
559+
496560 return ret ;
497561}
498562
499563blk_status_t null_process_zoned_cmd (struct nullb_cmd * cmd , enum req_opf op ,
500564 sector_t sector , sector_t nr_sectors )
501565{
566+ struct nullb_device * dev = cmd -> nq -> dev ;
567+ unsigned int zno = null_zone_no (dev , sector );
568+ blk_status_t sts ;
569+
502570 switch (op ) {
503571 case REQ_OP_WRITE :
504- return null_zone_write (cmd , sector , nr_sectors , false);
572+ sts = null_zone_write (cmd , sector , nr_sectors , false);
573+ break ;
505574 case REQ_OP_ZONE_APPEND :
506- return null_zone_write (cmd , sector , nr_sectors , true);
575+ sts = null_zone_write (cmd , sector , nr_sectors , true);
576+ break ;
507577 case REQ_OP_ZONE_RESET :
508578 case REQ_OP_ZONE_RESET_ALL :
509579 case REQ_OP_ZONE_OPEN :
510580 case REQ_OP_ZONE_CLOSE :
511581 case REQ_OP_ZONE_FINISH :
512- return null_zone_mgmt (cmd , op , sector );
582+ sts = null_zone_mgmt (cmd , op , sector );
583+ break ;
513584 default :
514- return null_process_cmd (cmd , op , sector , nr_sectors );
585+ null_lock_zone (dev , zno );
586+ sts = null_process_cmd (cmd , op , sector , nr_sectors );
587+ null_unlock_zone (dev , zno );
515588 }
589+
590+ return sts ;
516591}
0 commit comments