On Wed 18-11-20 09:47:55, Christoph Hellwig wrote: > Instead of having two structures that represent each block device with > different lift time rules merged them into a single one. This also ^^^ :) life ^^^^ merge > greatly simplifies the reference counting rules, as we can use the inode > reference count as the main reference count for the new struct > block_device, with the device model reference front ending it for device > model interaction. The percpu refcount in struct hd_struct is entirely > gone given that struct block_device must be opened and thus valid for > the duration of the I/O. > > Signed-off-by: Christoph Hellwig <hch@xxxxxx> This patch is kind of difficult to review due to the size of mostly mechanical changes mixed with not completely mechanical changes. Can we perhaps split out the mechanical bits? E.g. the rq->part => rq->bdev renaming is mechanical and notable part of the patch. Similarly the part->foo => part->bd_foo bits... Also I'm kind of wondering: AFAIU the new lifetime rules, gendisk holds bdev reference and bdev is created on gendisk allocation so bdev lifetime is strictly larger than gendisk lifetime. But what now keeps bdev->bd_disk reference safe in presence device hot unplug? In most cases we are still protected by gendisk reference taken in __blkdev_get() but how about disk->lookup_sem and disk->flags dereferences before we actually grab the reference? Also I find it rather non-obvious (although elegant ;) that bdev->bd_device rules the lifetime of gendisk. Can you perhaps explain this in the changelog and probably also add somewhere to source a documentation about the new lifetime rules? > diff --git a/block/blk.h b/block/blk.h > index 09cee7024fb43e..90dd2047c6cd29 100644 > --- a/block/blk.h > +++ b/block/blk.h > @@ -215,7 +215,15 @@ static inline void elevator_exit(struct request_queue *q, > __elevator_exit(q, e); > } > > -struct hd_struct *__disk_get_part(struct gendisk *disk, int partno); > +static inline struct block_device *__bdget_disk(struct gendisk *disk, > + int partno) > +{ > + struct disk_part_tbl *ptbl = rcu_dereference(disk->part_tbl); > + > + if (unlikely(partno < 0 || partno >= ptbl->len)) > + return NULL; > + return rcu_dereference(ptbl->part[partno]); > +} I understand this is lower-level counterpart of bdget_disk() but it is confusing to me that this has 'bdget' in the name and returns no bdev reference. Can we call it like __bdev_from_disk() or something like that? > > ssize_t part_size_show(struct device *dev, struct device_attribute *attr, > char *buf); Honza -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR