On 2020/02/21 10:37, Shin'ichiro Kawasaki wrote: > Commit b72053072c0b ("block: allow partitions on host aware zone > devices") introduced the helper function disk_has_partitions() to check > if a given disk has valid partitions. However, since this function result > directly depends on the disk partition table length rather than the > actual existence of valid partitions in the table, it returns true even > after all partitions are removed from the disk. For host aware zoned > block devices, this results in zone management support to be kept > disabled even after removing all partitions. > > Fix this by changing disk_has_partitions() to walk through the partition > table entries and return true if and only if a valid non-zero size > partition is found. > > Fixes: b72053072c0b ("block: allow partitions on host aware zone devices") > Cc: stable@xxxxxxxxxxxxxxx # 5.5 > Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@xxxxxxx> Looks good to me. Reviewed-by: Damien Le Moal <damien.lemoal@xxxxxxx> > --- > Changes from v1: > * Addressed comments on the list > > block/genhd.c | 36 ++++++++++++++++++++++++++++++++++++ > include/linux/genhd.h | 13 +------------ > 2 files changed, 37 insertions(+), 12 deletions(-) > > diff --git a/block/genhd.c b/block/genhd.c > index ff6268970ddc..9c2e13ce0d19 100644 > --- a/block/genhd.c > +++ b/block/genhd.c > @@ -301,6 +301,42 @@ struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) > } > EXPORT_SYMBOL_GPL(disk_map_sector_rcu); > > +/** > + * disk_has_partitions > + * @disk: gendisk of interest > + * > + * Walk through the partition table and check if valid partition exists. > + * > + * CONTEXT: > + * Don't care. > + * > + * RETURNS: > + * True if the gendisk has at least one valid non-zero size partition. > + * Otherwise false. > + */ > +bool disk_has_partitions(struct gendisk *disk) > +{ > + struct disk_part_tbl *ptbl; > + int i; > + bool ret = false; > + > + rcu_read_lock(); > + ptbl = rcu_dereference(disk->part_tbl); > + > + /* Iterate partitions skipping the whole device at index 0 */ > + for (i = 1; i < ptbl->len; i++) { > + if (rcu_dereference(ptbl->part[i])) { > + ret = true; > + break; > + } > + } > + > + rcu_read_unlock(); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(disk_has_partitions); > + > /* > * Can be deleted altogether. Later. > * > diff --git a/include/linux/genhd.h b/include/linux/genhd.h > index 6fbe58538ad6..07dc91835b98 100644 > --- a/include/linux/genhd.h > +++ b/include/linux/genhd.h > @@ -245,18 +245,6 @@ static inline bool disk_part_scan_enabled(struct gendisk *disk) > !(disk->flags & GENHD_FL_NO_PART_SCAN); > } > > -static inline bool disk_has_partitions(struct gendisk *disk) > -{ > - bool ret = false; > - > - rcu_read_lock(); > - if (rcu_dereference(disk->part_tbl)->len > 1) > - ret = true; > - rcu_read_unlock(); > - > - return ret; > -} > - > static inline dev_t disk_devt(struct gendisk *disk) > { > return MKDEV(disk->major, disk->first_minor); > @@ -298,6 +286,7 @@ extern void disk_part_iter_exit(struct disk_part_iter *piter); > > extern struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, > sector_t sector); > +bool disk_has_partitions(struct gendisk *disk); > > /* > * Macros to operate on percpu disk statistics: > -- Damien Le Moal Western Digital Research