From: Yu Kuai yukuai3@huawei.com
hulk inclusion category: bugfix bugzilla: 187190, https://gitee.com/src-openeuler/kernel/issues/I5GWOV CVE: NA
--------------------------------
This reverts commit b2f0e44fd4aeba9d03a0e152cd50271bff9119b3.
Because it will introduce following problem in ltp zram tests:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000600 PGD 0 P4D 0 Oops: 0002 [#1] SMP PTI CPU: 28 PID: 172121 Comm: sh Kdump: loaded Tainted: G OE --------- - - 4.18.0+ #2 Hardware name: Huawei RH2288H V3/BC11HGSA0, BIOS 5.15 05/21/2019 RIP: 0010:flush_disk+0x1d/0x50 RSP: 0018:ffffaf14a516fe20 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff899e26bac380 RCX: 0000000000000000 RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff899e26bac380 RBP: ffff899e26bac380 R08: 00000000000006a9 R09: 0000000000000004 R10: ffff89cd878ff440 R11: 0000000000000001 R12: 0000000000000000 R13: ffff899e26bac398 R14: ffffaf14a516ff00 R15: ffff89cd8709c3e0 FS: 00007f78d6840740(0000) GS:ffff89fcbf480000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000600 CR3: 000000308afc0002 CR4: 00000000001606e0 Call Trace: revalidate_disk+0x57/0x80 reset_store+0xaf/0x120 [zram] kernfs_fop_write+0x10f/0x190 vfs_write+0xad/0x1a0 ksys_write+0x52/0xc0 do_syscall_64+0x5d/0x1d0 entry_SYSCALL_64_after_hwframe+0x65/0xca
This is because "bdev->bd_disk" is not ensured to exist, just convert "set_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags)" to "set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state)" is wrong.
The reason to backport it is that commit 2a57456c8973 ("block: Fix warning in bd_link_disk_holder()") has a regression that part scan is disabled in device_add_disk(), and this problem will be fixed in later patch.
Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- block/genhd.c | 2 +- block/partition-generic.c | 6 +++--- drivers/block/nbd.c | 8 ++++---- fs/block_dev.c | 11 ++++++----- include/linux/fs.h | 3 +++ include/linux/genhd.h | 2 -- 6 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/block/genhd.c b/block/genhd.c index 94b0fe34a755..4211722e1c85 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -646,7 +646,7 @@ static void register_disk(struct device *parent, struct gendisk *disk) if (!bdev) goto exit;
- set_bit(GD_NEED_PART_SCAN, &disk->state); + set_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); err = blkdev_get(bdev, FMODE_READ, NULL); if (err < 0) goto exit; diff --git a/block/partition-generic.c b/block/partition-generic.c index b8481079c58a..ae3761fed854 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -546,7 +546,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) if (disk->fops->revalidate_disk) disk->fops->revalidate_disk(disk); check_disk_size_change(disk, bdev, true); - clear_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + clear_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); if (!get_capacity(disk) || !(state = check_partition(disk, bdev))) return 0; if (IS_ERR(state)) { @@ -662,7 +662,7 @@ int invalidate_partitions(struct gendisk *disk, struct block_device *bdev) { int res;
- if (!test_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state)) + if (!test_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags)) return 0;
res = drop_partitions(disk, bdev); @@ -671,7 +671,7 @@ int invalidate_partitions(struct gendisk *disk, struct block_device *bdev)
set_capacity(disk, 0); check_disk_size_change(disk, bdev, false); - clear_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + clear_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); /* tell userspace that the media / partition table may have changed */ kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 833525f41005..b0a45edddafd 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -317,7 +317,7 @@ static void nbd_size_update(struct nbd_device *nbd, bool start) if (start) set_blocksize(bdev, config->blksize); } else - set_bit(GD_NEED_PART_SCAN, &nbd->disk->state); + set_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); bdput(bdev); } kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); @@ -1343,7 +1343,7 @@ static int nbd_start_device_ioctl(struct nbd_device *nbd, struct block_device *b return ret;
if (max_part) - set_bit(GD_NEED_PART_SCAN, &nbd->disk->state); + set_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); mutex_unlock(&nbd->config_lock); ret = wait_event_interruptible(config->recv_wq, atomic_read(&config->recv_threads) == 0); @@ -1524,9 +1524,9 @@ static int nbd_open(struct block_device *bdev, fmode_t mode) refcount_set(&nbd->config_refs, 1); refcount_inc(&nbd->refs); mutex_unlock(&nbd->config_lock); - set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + set_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); } else if (nbd_disconnected(nbd->config)) { - set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + set_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); } out: mutex_unlock(&nbd_index_mutex); diff --git a/fs/block_dev.c b/fs/block_dev.c index e255c3b65224..f521b7cf907f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -922,6 +922,7 @@ struct block_device *bdget(dev_t dev) bdev->bd_inode = inode; bdev->bd_block_size = i_blocksize(inode); bdev->bd_part_count = 0; + bdev->bd_flags = 0; inode->i_mode = S_IFBLK; inode->i_rdev = dev; inode->i_bdev = bdev; @@ -1403,7 +1404,7 @@ static void flush_disk(struct block_device *bdev, bool kill_dirty) "resized disk %s\n", bdev->bd_disk ? bdev->bd_disk->disk_name : ""); } - set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + set_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); }
/** @@ -1456,7 +1457,7 @@ int revalidate_disk(struct gendisk *disk)
mutex_lock(&bdev->bd_mutex); check_disk_size_change(disk, bdev, ret == 0); - clear_bit(GD_NEED_PART_SCAN, &disk->state); + clear_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); mutex_unlock(&bdev->bd_mutex); bdput(bdev); return ret; @@ -1519,7 +1520,7 @@ static void bdev_disk_changed(struct block_device *bdev, bool invalidate) up_read(&disk->lookup_sem); } else { check_disk_size_change(bdev->bd_disk, bdev, !invalidate); - clear_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); + clear_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags); } }
@@ -1604,7 +1605,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) * The latter is necessary to prevent ghost * partitions on a removed medium. */ - if (test_bit(GD_NEED_PART_SCAN, &disk->state) && + if (test_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags) && (!ret || ret == -ENOMEDIUM)) bdev_disk_changed(bdev, ret == -ENOMEDIUM);
@@ -1641,7 +1642,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (bdev->bd_disk->fops->open) ret = bdev->bd_disk->fops->open(bdev, mode); /* the same as first opener case, read comment there */ - if (test_bit(GD_NEED_PART_SCAN, &disk->state) && + if (test_bit(BDEV_NEED_PART_SCAN, &bdev->bd_flags) && (!ret || ret == -ENOMEDIUM)) bdev_disk_changed(bdev, ret == -ENOMEDIUM); if (ret) diff --git a/include/linux/fs.h b/include/linux/fs.h index 025b98fbab05..480936c2d938 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -459,6 +459,8 @@ struct address_space { */ struct request_queue;
+#define BDEV_NEED_PART_SCAN 0 + struct block_device { dev_t bd_dev; /* not a kdev_t - it's a search key */ int bd_openers; @@ -479,6 +481,7 @@ struct block_device { struct hd_struct * bd_part; /* number of times partitions within this device have been opened. */ unsigned bd_part_count; + unsigned long bd_flags; struct gendisk * bd_disk; struct request_queue * bd_queue; struct backing_dev_info *bd_bdi; diff --git a/include/linux/genhd.h b/include/linux/genhd.h index f3fc01f0e84c..58a819484fb4 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -208,8 +208,6 @@ struct gendisk { void *private_data;
int flags; - unsigned long state; -#define GD_NEED_PART_SCAN 0 struct rw_semaphore lookup_sem; struct kobject *slave_dir;