Skip to content

Commit b720530

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: allow partitions on host aware zone devices
Host-aware SMR drives can be used with the commands to explicitly manage zone state, but they can also be used as normal disks. In the former case it makes perfect sense to allow partitions on them, in the latter it does not, just like for host managed devices. Add a check to add_partition to allow partitions on host aware devices, but give up any zone management capabilities in that case, which also catches the previously missed case of adding a partition vs just scanning it. Because sd can rescan the attribute at runtime it needs to check if a disk has partitions, for which a new helper is added to genhd.h. Fixes: 5eac3eb ("block: Remove partition support for zoned block devices") Reported-by: Borislav Petkov <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Tested-by: Damien Le Moal <[email protected]> Reviewed-by: Damien Le Moal <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent ad6bf88 commit b720530

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

block/partition-generic.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,24 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno,
321321
const char *dname;
322322
int err;
323323

324+
/*
325+
* Partitions are not supported on zoned block devices that are used as
326+
* such.
327+
*/
328+
switch (disk->queue->limits.zoned) {
329+
case BLK_ZONED_HM:
330+
pr_warn("%s: partitions not supported on host managed zoned block device\n",
331+
disk->disk_name);
332+
return ERR_PTR(-ENXIO);
333+
case BLK_ZONED_HA:
334+
pr_info("%s: disabling host aware zoned block device support due to partitions\n",
335+
disk->disk_name);
336+
disk->queue->limits.zoned = BLK_ZONED_NONE;
337+
break;
338+
case BLK_ZONED_NONE:
339+
break;
340+
}
341+
324342
err = disk_expand_part_tbl(disk, partno);
325343
if (err)
326344
return ERR_PTR(err);
@@ -501,7 +519,7 @@ static bool blk_add_partition(struct gendisk *disk, struct block_device *bdev,
501519

502520
part = add_partition(disk, p, from, size, state->parts[p].flags,
503521
&state->parts[p].info);
504-
if (IS_ERR(part)) {
522+
if (IS_ERR(part) && PTR_ERR(part) != -ENXIO) {
505523
printk(KERN_ERR " %s: p%d could not be added: %ld\n",
506524
disk->disk_name, p, -PTR_ERR(part));
507525
return true;
@@ -540,10 +558,10 @@ int blk_add_partitions(struct gendisk *disk, struct block_device *bdev)
540558
}
541559

542560
/*
543-
* Partitions are not supported on zoned block devices.
561+
* Partitions are not supported on host managed zoned block devices.
544562
*/
545-
if (bdev_is_zoned(bdev)) {
546-
pr_warn("%s: ignoring partition table on zoned block device\n",
563+
if (disk->queue->limits.zoned == BLK_ZONED_HM) {
564+
pr_warn("%s: ignoring partition table on host managed zoned block device\n",
547565
disk->disk_name);
548566
ret = 0;
549567
goto out_free_state;

drivers/scsi/sd.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2956,15 +2956,16 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
29562956
q->limits.zoned = BLK_ZONED_HM;
29572957
} else {
29582958
sdkp->zoned = (buffer[8] >> 4) & 3;
2959-
if (sdkp->zoned == 1)
2959+
if (sdkp->zoned == 1 && !disk_has_partitions(sdkp->disk)) {
29602960
/* Host-aware */
29612961
q->limits.zoned = BLK_ZONED_HA;
2962-
else
2962+
} else {
29632963
/*
2964-
* Treat drive-managed devices as
2965-
* regular block devices.
2964+
* Treat drive-managed devices and host-aware devices
2965+
* with partitions as regular block devices.
29662966
*/
29672967
q->limits.zoned = BLK_ZONED_NONE;
2968+
}
29682969
}
29692970
if (blk_queue_is_zoned(q) && sdkp->first_scan)
29702971
sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",

include/linux/genhd.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,18 @@ static inline bool disk_part_scan_enabled(struct gendisk *disk)
245245
!(disk->flags & GENHD_FL_NO_PART_SCAN);
246246
}
247247

248+
static inline bool disk_has_partitions(struct gendisk *disk)
249+
{
250+
bool ret = false;
251+
252+
rcu_read_lock();
253+
if (rcu_dereference(disk->part_tbl)->len > 1)
254+
ret = true;
255+
rcu_read_unlock();
256+
257+
return ret;
258+
}
259+
248260
static inline dev_t disk_devt(struct gendisk *disk)
249261
{
250262
return MKDEV(disk->major, disk->first_minor);

0 commit comments

Comments
 (0)