@@ -400,8 +400,10 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, unsigned char *buf)
400
400
*
401
401
* Check that all zones of the device are equal. The last zone can however
402
402
* be smaller. The zone size must also be a power of two number of LBAs.
403
+ *
404
+ * Returns the zone size in bytes upon success or an error code upon failure.
403
405
*/
404
- static int sd_zbc_check_zone_size (struct scsi_disk * sdkp )
406
+ static s64 sd_zbc_check_zone_size (struct scsi_disk * sdkp )
405
407
{
406
408
u64 zone_blocks = 0 ;
407
409
sector_t block = 0 ;
@@ -412,8 +414,6 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
412
414
int ret ;
413
415
u8 same ;
414
416
415
- sdkp -> zone_blocks = 0 ;
416
-
417
417
/* Get a buffer */
418
418
buf = kmalloc (SD_ZBC_BUF_SIZE , GFP_KERNEL );
419
419
if (!buf )
@@ -445,16 +445,17 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
445
445
446
446
/* Parse zone descriptors */
447
447
while (rec < buf + buf_len ) {
448
- zone_blocks = get_unaligned_be64 (& rec [8 ]);
449
- if (sdkp -> zone_blocks == 0 ) {
450
- sdkp -> zone_blocks = zone_blocks ;
451
- } else if (zone_blocks != sdkp -> zone_blocks &&
452
- (block + zone_blocks < sdkp -> capacity
453
- || zone_blocks > sdkp -> zone_blocks )) {
454
- zone_blocks = 0 ;
448
+ u64 this_zone_blocks = get_unaligned_be64 (& rec [8 ]);
449
+
450
+ if (zone_blocks == 0 ) {
451
+ zone_blocks = this_zone_blocks ;
452
+ } else if (this_zone_blocks != zone_blocks &&
453
+ (block + this_zone_blocks < sdkp -> capacity
454
+ || this_zone_blocks > zone_blocks )) {
455
+ this_zone_blocks = 0 ;
455
456
goto out ;
456
457
}
457
- block += zone_blocks ;
458
+ block += this_zone_blocks ;
458
459
rec += 64 ;
459
460
}
460
461
@@ -467,8 +468,6 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
467
468
468
469
} while (block < sdkp -> capacity );
469
470
470
- zone_blocks = sdkp -> zone_blocks ;
471
-
472
471
out :
473
472
if (!zone_blocks ) {
474
473
if (sdkp -> first_scan )
@@ -488,8 +487,7 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
488
487
"Zone size too large\n" );
489
488
ret = - ENODEV ;
490
489
} else {
491
- sdkp -> zone_blocks = zone_blocks ;
492
- sdkp -> zone_shift = ilog2 (zone_blocks );
490
+ ret = zone_blocks ;
493
491
}
494
492
495
493
out_free :
@@ -500,22 +498,22 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
500
498
501
499
/**
502
500
* sd_zbc_alloc_zone_bitmap - Allocate a zone bitmap (one bit per zone).
503
- * @sdkp: The disk of the bitmap
501
+ * @nr_zones: Number of zones to allocate space for.
502
+ * @numa_node: NUMA node to allocate the memory from.
504
503
*/
505
- static inline unsigned long * sd_zbc_alloc_zone_bitmap (struct scsi_disk * sdkp )
504
+ static inline unsigned long *
505
+ sd_zbc_alloc_zone_bitmap (u32 nr_zones , int numa_node )
506
506
{
507
- struct request_queue * q = sdkp -> disk -> queue ;
508
-
509
- return kzalloc_node (BITS_TO_LONGS (sdkp -> nr_zones )
510
- * sizeof (unsigned long ),
511
- GFP_KERNEL , q -> node );
507
+ return kzalloc_node (BITS_TO_LONGS (nr_zones ) * sizeof (unsigned long ),
508
+ GFP_KERNEL , numa_node );
512
509
}
513
510
514
511
/**
515
512
* sd_zbc_get_seq_zones - Parse report zones reply to identify sequential zones
516
513
* @sdkp: disk used
517
514
* @buf: report reply buffer
518
515
* @buflen: length of @buf
516
+ * @zone_shift: logarithm base 2 of the number of blocks in a zone
519
517
* @seq_zones_bitmap: bitmap of sequential zones to set
520
518
*
521
519
* Parse reported zone descriptors in @buf to identify sequential zones and
@@ -525,7 +523,7 @@ static inline unsigned long *sd_zbc_alloc_zone_bitmap(struct scsi_disk *sdkp)
525
523
* Return the LBA after the last zone reported.
526
524
*/
527
525
static sector_t sd_zbc_get_seq_zones (struct scsi_disk * sdkp , unsigned char * buf ,
528
- unsigned int buflen ,
526
+ unsigned int buflen , u32 zone_shift ,
529
527
unsigned long * seq_zones_bitmap )
530
528
{
531
529
sector_t lba , next_lba = sdkp -> capacity ;
@@ -544,7 +542,7 @@ static sector_t sd_zbc_get_seq_zones(struct scsi_disk *sdkp, unsigned char *buf,
544
542
if (type != ZBC_ZONE_TYPE_CONV &&
545
543
cond != ZBC_ZONE_COND_READONLY &&
546
544
cond != ZBC_ZONE_COND_OFFLINE )
547
- set_bit (lba >> sdkp -> zone_shift , seq_zones_bitmap );
545
+ set_bit (lba >> zone_shift , seq_zones_bitmap );
548
546
next_lba = lba + get_unaligned_be64 (& rec [8 ]);
549
547
rec += 64 ;
550
548
}
@@ -553,22 +551,26 @@ static sector_t sd_zbc_get_seq_zones(struct scsi_disk *sdkp, unsigned char *buf,
553
551
}
554
552
555
553
/**
556
- * sd_zbc_setup_seq_zones_bitmap - Initialize the disk seq zone bitmap.
554
+ * sd_zbc_setup_seq_zones_bitmap - Initialize a seq zone bitmap.
557
555
* @sdkp: target disk
556
+ * @zone_shift: logarithm base 2 of the number of blocks in a zone
557
+ * @nr_zones: number of zones to set up a seq zone bitmap for
558
558
*
559
559
* Allocate a zone bitmap and initialize it by identifying sequential zones.
560
560
*/
561
- static int sd_zbc_setup_seq_zones_bitmap (struct scsi_disk * sdkp )
561
+ static unsigned long *
562
+ sd_zbc_setup_seq_zones_bitmap (struct scsi_disk * sdkp , u32 zone_shift ,
563
+ u32 nr_zones )
562
564
{
563
565
struct request_queue * q = sdkp -> disk -> queue ;
564
566
unsigned long * seq_zones_bitmap ;
565
567
sector_t lba = 0 ;
566
568
unsigned char * buf ;
567
569
int ret = - ENOMEM ;
568
570
569
- seq_zones_bitmap = sd_zbc_alloc_zone_bitmap (sdkp );
571
+ seq_zones_bitmap = sd_zbc_alloc_zone_bitmap (nr_zones , q -> node );
570
572
if (!seq_zones_bitmap )
571
- return - ENOMEM ;
573
+ return ERR_PTR ( - ENOMEM ) ;
572
574
573
575
buf = kmalloc (SD_ZBC_BUF_SIZE , GFP_KERNEL );
574
576
if (!buf )
@@ -579,7 +581,7 @@ static int sd_zbc_setup_seq_zones_bitmap(struct scsi_disk *sdkp)
579
581
if (ret )
580
582
goto out ;
581
583
lba = sd_zbc_get_seq_zones (sdkp , buf , SD_ZBC_BUF_SIZE ,
582
- seq_zones_bitmap );
584
+ zone_shift , seq_zones_bitmap );
583
585
}
584
586
585
587
if (lba != sdkp -> capacity ) {
@@ -591,12 +593,9 @@ static int sd_zbc_setup_seq_zones_bitmap(struct scsi_disk *sdkp)
591
593
kfree (buf );
592
594
if (ret ) {
593
595
kfree (seq_zones_bitmap );
594
- return ret ;
596
+ return ERR_PTR ( ret ) ;
595
597
}
596
-
597
- q -> seq_zones_bitmap = seq_zones_bitmap ;
598
-
599
- return 0 ;
598
+ return seq_zones_bitmap ;
600
599
}
601
600
602
601
static void sd_zbc_cleanup (struct scsi_disk * sdkp )
@@ -612,44 +611,64 @@ static void sd_zbc_cleanup(struct scsi_disk *sdkp)
612
611
q -> nr_zones = 0 ;
613
612
}
614
613
615
- static int sd_zbc_setup (struct scsi_disk * sdkp )
614
+ static int sd_zbc_setup (struct scsi_disk * sdkp , u32 zone_blocks )
616
615
{
617
616
struct request_queue * q = sdkp -> disk -> queue ;
617
+ u32 zone_shift = ilog2 (zone_blocks );
618
+ u32 nr_zones ;
618
619
int ret ;
619
620
620
- /* READ16/WRITE16 is mandatory for ZBC disks */
621
- sdkp -> device -> use_16_for_rw = 1 ;
622
- sdkp -> device -> use_10_for_rw = 0 ;
623
-
624
621
/* chunk_sectors indicates the zone size */
625
- blk_queue_chunk_sectors (sdkp -> disk -> queue ,
626
- logical_to_sectors (sdkp -> device , sdkp -> zone_blocks ));
627
- sdkp -> nr_zones =
628
- round_up (sdkp -> capacity , sdkp -> zone_blocks ) >> sdkp -> zone_shift ;
622
+ blk_queue_chunk_sectors (q ,
623
+ logical_to_sectors (sdkp -> device , zone_blocks ));
624
+ nr_zones = round_up (sdkp -> capacity , zone_blocks ) >> zone_shift ;
629
625
630
626
/*
631
627
* Initialize the device request queue information if the number
632
628
* of zones changed.
633
629
*/
634
- if (sdkp -> nr_zones != q -> nr_zones ) {
635
-
636
- sd_zbc_cleanup ( sdkp ) ;
637
-
638
- q -> nr_zones = sdkp -> nr_zones ;
639
- if ( sdkp -> nr_zones ) {
640
- q -> seq_zones_wlock = sd_zbc_alloc_zone_bitmap ( sdkp );
641
- if (!q -> seq_zones_wlock ) {
630
+ if (nr_zones != sdkp -> nr_zones || nr_zones != q -> nr_zones ) {
631
+ unsigned long * seq_zones_wlock = NULL , * seq_zones_bitmap = NULL ;
632
+ size_t zone_bitmap_size ;
633
+
634
+ if ( nr_zones ) {
635
+ seq_zones_wlock = sd_zbc_alloc_zone_bitmap ( nr_zones ,
636
+ q -> node );
637
+ if (!seq_zones_wlock ) {
642
638
ret = - ENOMEM ;
643
639
goto err ;
644
640
}
645
641
646
- ret = sd_zbc_setup_seq_zones_bitmap (sdkp );
647
- if (ret ) {
648
- sd_zbc_cleanup (sdkp );
642
+ seq_zones_bitmap = sd_zbc_setup_seq_zones_bitmap (sdkp ,
643
+ zone_shift , nr_zones );
644
+ if (IS_ERR (seq_zones_bitmap )) {
645
+ ret = PTR_ERR (seq_zones_bitmap );
646
+ kfree (seq_zones_wlock );
649
647
goto err ;
650
648
}
651
649
}
652
-
650
+ zone_bitmap_size = BITS_TO_LONGS (nr_zones ) *
651
+ sizeof (unsigned long );
652
+ blk_mq_freeze_queue (q );
653
+ if (q -> nr_zones != nr_zones ) {
654
+ /* READ16/WRITE16 is mandatory for ZBC disks */
655
+ sdkp -> device -> use_16_for_rw = 1 ;
656
+ sdkp -> device -> use_10_for_rw = 0 ;
657
+
658
+ sdkp -> zone_blocks = zone_blocks ;
659
+ sdkp -> zone_shift = zone_shift ;
660
+ sdkp -> nr_zones = nr_zones ;
661
+ q -> nr_zones = nr_zones ;
662
+ swap (q -> seq_zones_wlock , seq_zones_wlock );
663
+ swap (q -> seq_zones_bitmap , seq_zones_bitmap );
664
+ } else if (memcmp (q -> seq_zones_bitmap , seq_zones_bitmap ,
665
+ zone_bitmap_size ) != 0 ) {
666
+ memcpy (q -> seq_zones_bitmap , seq_zones_bitmap ,
667
+ zone_bitmap_size );
668
+ }
669
+ blk_mq_unfreeze_queue (q );
670
+ kfree (seq_zones_wlock );
671
+ kfree (seq_zones_bitmap );
653
672
}
654
673
655
674
return 0 ;
@@ -661,6 +680,7 @@ static int sd_zbc_setup(struct scsi_disk *sdkp)
661
680
662
681
int sd_zbc_read_zones (struct scsi_disk * sdkp , unsigned char * buf )
663
682
{
683
+ int64_t zone_blocks ;
664
684
int ret ;
665
685
666
686
if (!sd_is_zoned (sdkp ))
@@ -697,12 +717,16 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
697
717
* Check zone size: only devices with a constant zone size (except
698
718
* an eventual last runt zone) that is a power of 2 are supported.
699
719
*/
700
- ret = sd_zbc_check_zone_size (sdkp );
701
- if (ret )
720
+ zone_blocks = sd_zbc_check_zone_size (sdkp );
721
+ ret = - EFBIG ;
722
+ if (zone_blocks != (u32 )zone_blocks )
723
+ goto err ;
724
+ ret = zone_blocks ;
725
+ if (ret < 0 )
702
726
goto err ;
703
727
704
728
/* The drive satisfies the kernel restrictions: set it up */
705
- ret = sd_zbc_setup (sdkp );
729
+ ret = sd_zbc_setup (sdkp , zone_blocks );
706
730
if (ret )
707
731
goto err ;
708
732
0 commit comments