History

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.

Christoph Hellwig committed 6 years ago

Commit b7205301 parent ad6bf883 files · +39 −8Browse files

Unified · Split

3 files
  1. block/partition-generic.c +22 −4
  2. drivers/scsi/sd.c +5 −4
  3. include/linux/genhd.h +12 −0
block/partition-generic.c+22−4
@@ -321,6 +321,24 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, · 320 unmodified lines
321 const char *dname;321 const char *dname;
322 int err;322 int err;
323 323
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
324 err = disk_expand_part_tbl(disk, partno);342 err = disk_expand_part_tbl(disk, partno);
325 if (err)343 if (err)
326 return ERR_PTR(err);344 return ERR_PTR(err);
@@ -501,7 +519,7 @@ static bool blk_add_partition(struct gendisk *disk, struct block_device *bdev, · 174 unmodified lines
501 519
502 part = add_partition(disk, p, from, size, state->parts[p].flags,520 part = add_partition(disk, p, from, size, state->parts[p].flags,
503 &state->parts[p].info);521 &state->parts[p].info);
504 if (IS_ERR(part)) {522 if (IS_ERR(part) && PTR_ERR(part) != -ENXIO) {
505 printk(KERN_ERR " %s: p%d could not be added: %ld\n",523 printk(KERN_ERR " %s: p%d could not be added: %ld\n",
506 disk->disk_name, p, -PTR_ERR(part));524 disk->disk_name, p, -PTR_ERR(part));
507 return true;525 return true;
@@ -540,10 +558,10 @@ int blk_add_partitions(struct gendisk *disk, struct block_device *bdev) · 32 unmodified lines
540 }558 }
541 559
542 /*560 /*
543 * Partitions are not supported on zoned block devices.561 * Partitions are not supported on host managed zoned block devices.
544 */562 */
545 if (bdev_is_zoned(bdev)) {563 if (disk->queue->limits.zoned == BLK_ZONED_HM) {
546 pr_warn("%s: ignoring partition table on zoned block device\n",564 pr_warn("%s: ignoring partition table on host managed zoned block device\n",
547 disk->disk_name);565 disk->disk_name);
548 ret = 0;566 ret = 0;
549 goto out_free_state;567 goto out_free_state;
drivers/scsi/sd.c+5−4
@@ -2956,15 +2956,16 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) · 2955 unmodified lines
2956 q->limits.zoned = BLK_ZONED_HM;2956 q->limits.zoned = BLK_ZONED_HM;
2957 } else {2957 } else {
2958 sdkp->zoned = (buffer[8] >> 4) & 3;2958 sdkp->zoned = (buffer[8] >> 4) & 3;
2959 if (sdkp->zoned == 1)2959 if (sdkp->zoned == 1 && !disk_has_partitions(sdkp->disk)) {
2960 /* Host-aware */2960 /* Host-aware */
2961 q->limits.zoned = BLK_ZONED_HA;2961 q->limits.zoned = BLK_ZONED_HA;
2962 else2962 } else {
2963 /*2963 /*
2964 * Treat drive-managed devices as2964 * Treat drive-managed devices and host-aware devices
2965 * regular block devices.2965 * with partitions as regular block devices.
2966 */2966 */
2967 q->limits.zoned = BLK_ZONED_NONE;2967 q->limits.zoned = BLK_ZONED_NONE;
2968 }
2968 }2969 }
2969 if (blk_queue_is_zoned(q) && sdkp->first_scan)2970 if (blk_queue_is_zoned(q) && sdkp->first_scan)
2970 sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",2971 sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",
include/linux/genhd.h+12−0
@@ -245,6 +245,18 @@ static inline bool disk_part_scan_enabled(struct gendisk *disk) · 244 unmodified lines
245 !(disk->flags & GENHD_FL_NO_PART_SCAN);245 !(disk->flags & GENHD_FL_NO_PART_SCAN);
246}246}
247 247
248static 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
248static inline dev_t disk_devt(struct gendisk *disk)260static inline dev_t disk_devt(struct gendisk *disk)
249{261{
250 return MKDEV(disk->major, disk->first_minor);262 return MKDEV(disk->major, disk->first_minor);