Replace bd_partno with a 32bit field (__bd_flags). The lower 8 bits contain the partition number, the upper 24 are for flags. Helpers: bdev_{test,set,clear}_flag(bdev, flag), where flag numbers are zero-based. Use cmpxchg() to set/clear - all architectures support it for u32. NOTE: this commit does not actuall move any flags over there - they are still bool fields. As the result, it shifts the fields wrt cacheline boundaries; that's going to be restored once the first 3 flags are dealt with. Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> --- block/bdev.c | 2 +- include/linux/blk_types.h | 2 +- include/linux/blkdev.h | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/block/bdev.c b/block/bdev.c index 7a5f611c3d2e..0c55f7abaac3 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -411,7 +411,7 @@ struct block_device *bdev_alloc(struct gendisk *disk, u8 partno) mutex_init(&bdev->bd_fsfreeze_mutex); spin_lock_init(&bdev->bd_size_lock); mutex_init(&bdev->bd_holder_lock); - bdev->bd_partno = partno; + bdev->__bd_flags = partno; bdev->bd_inode = inode; bdev->bd_queue = disk->queue; if (partno) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index cb1526ec44b5..274f7eb4138f 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -45,8 +45,8 @@ struct block_device { struct request_queue * bd_queue; struct disk_stats __percpu *bd_stats; unsigned long bd_stamp; + u32 __bd_flags; // partition number + flags bool bd_read_only; /* read-only policy */ - u8 bd_partno; bool bd_write_holder; bool bd_has_submit_bio; dev_t bd_dev; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 32549d675955..b9dbfb811533 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -722,7 +722,38 @@ void disk_uevent(struct gendisk *disk, enum kobject_action action); static inline u8 bdev_partno(const struct block_device *bdev) { - return bdev->bd_partno; + return bdev->__bd_flags & 0xff; +} + +static inline bool bdev_test_flag(const struct block_device *bdev, int flag) +{ + return bdev->__bd_flags & (1 << (flag + 8)); +} + +static inline void bdev_set_flag(struct block_device *bdev, int flag) +{ + u32 v = bdev->__bd_flags; + + for (;;) { + u32 w = cmpxchg(&bdev->__bd_flags, v, v | (1 << (flag + 8))); + + if (v == w) + return; + v = w; + } +} + +static inline void bdev_clear_flag(struct block_device *bdev, int flag) +{ + u32 v = bdev->__bd_flags; + + for (;;) { + u32 w = cmpxchg(&bdev->__bd_flags, v, v & ~(1 << (flag + 8))); + + if (v == w) + return; + v = w; + } } static inline int get_disk_ro(struct gendisk *disk) -- 2.39.2