From: Li Ruilin liruilin4@huawei.com
euleros/rtos inclusion category: bugfix bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=26
--------------------------------
commit 6947676c374("bcache: add a framework to perform prefetch") collects data insert info which includes device info got from bio. However, bio created by write_moving here has no device info, causing a null pointer dereference.
[ 1497.991768] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 [ 1497.991869] PGD 0 P4D 0 [ 1497.991912] Oops: 0000 [#1] SMP PTI [ 1497.991962] CPU: 2 PID: 733 Comm: kworker/2:3 Not tainted 4.19.90+ #33 [ 1497.992030] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 [ 1497.992137] Workqueue: bcache_gc write_moving [bcache] [ 1497.992219] RIP: 0010:bch_data_insert+0x4c/0x140 [bcache] ... [ 1497.993367] Call Trace: [ 1497.993427] ? cached_dev_read_error+0x140/0x140 [bcache] [ 1497.993526] write_moving+0x19e/0x1b0 [bcache] [ 1497.993621] process_one_work+0x1fd/0x440 [ 1497.993742] worker_thread+0x34/0x410 [ 1497.993811] kthread+0x121/0x140 [ 1497.993873] ? process_one_work+0x440/0x440 [ 1497.993946] ? kthread_create_worker_on_cpu+0x70/0x70 [ 1497.994043] ret_from_fork+0x35/0x40
Signed-off-by: Li Ruilin liruilin4@huawei.com Reviewed-by: Song Chao chao.song@huawei.com Reviewed-by: Xu Wei xuwei56@huawei.com --- drivers/md/bcache/request.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 984f400d3908..d34fe2b69956 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -316,12 +316,14 @@ void bch_data_insert(struct closure *cl) trace_bcache_write(op->c, op->inode, op->bio, op->writeback, op->bypass);
- msg.offset = op->bio->bi_iter.bi_sector; - msg.length = op->bio->bi_iter.bi_size; - msg.type = ACACHE_INFO_CACHE_INSERT; - msg.dev = bio_dev(op->bio); - msg.start_time = ktime_get_ns(); - save_circ_item(&msg); + if (op->bio->bi_disk) { + msg.offset = op->bio->bi_iter.bi_sector; + msg.length = op->bio->bi_iter.bi_size; + msg.type = ACACHE_INFO_CACHE_INSERT; + msg.dev = bio_dev(op->bio); + msg.start_time = ktime_get_ns(); + save_circ_item(&msg); + }
bch_keylist_init(&op->insert_keys); bio_get(op->bio);
From: Li Ruilin liruilin4@huawei.com
euleros/rtos inclusion category: bugfix bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=26 DTS: https://code.huawei.com/hulk/hulk/issues/682
--------------------------------
Before this patch bypassed I/O request will not record start time, therefore when calculating latency data, start time will be calculated wrongly. This patch makes start time always be recorded to fix this.
Signed-off-by: Li Ruilin liruilin4@huawei.com Reviewed-by: Song Chao chao.song@huawei.com --- drivers/md/bcache/request.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index d34fe2b69956..a7c64447ec66 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -1304,14 +1304,13 @@ static blk_qc_t cached_dev_make_request(struct request_queue *q, atomic_inc(&dc->front_io_num); s->iop.bypass = check_should_bypass(dc, bio);
- if (!s->iop.bypass && bio->bi_iter.bi_size && !rw) { - s->smp.offset = bio->bi_iter.bi_sector - dc->sb.data_offset; - s->smp.length = bio->bi_iter.bi_size; - s->smp.type = rw; - s->smp.dev = dc->bdev->bd_dev; - s->smp.start_time = ktime_get_ns(); + s->smp.offset = bio->bi_iter.bi_sector - dc->sb.data_offset; + s->smp.length = bio->bi_iter.bi_size; + s->smp.type = rw; + s->smp.dev = dc->bdev->bd_dev; + s->smp.start_time = ktime_get_ns(); + if (!s->iop.bypass && bio->bi_iter.bi_size && !rw) save_circ_item(&s->smp); - }
if (rw) { if ((s->iop.bypass == false) &&
From: Your Name you@example.com
euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I41P6F CVE: NA DTS: https://code.huawei.com/hulk/hulk/issues/705
--------------------------------
When making bcache devices, we need to wipe the filesystem on the disks and use the first 8KB space to store the bcache superblock info. Therefore it can be used only on new disks. This patch writes 8K size superblock info to a file on the disk through VFS rather than writes to the first 8KB on the disk, thus there's no need to wipe the disks's filesystem. Note that the superblock file should be set immutable to avoid to be changed through VFS. When registering bcache device, we now pass the offset of the superblock file to the kernel, and use the offset to get the superblock info. This patch don't impact the origin methord to make bcache devices. We can also use the origin bcache-tools to make bcache devices.
Signed-off-by: Song Chao chao.song@huawei.com Reviewed-by: Li Ruilin liruilin4@huawei.com --- drivers/md/bcache/super.c | 47 +++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-)
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index e2828c762edc..4f1b5463c0ca 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -57,10 +57,33 @@ struct workqueue_struct *bch_journal_wq; /* limitation of bcache devices number on single system */ #define BCACHE_DEVICE_IDX_MAX ((1U << MINORBITS)/BCACHE_MINORS)
+#define WITH_FS_DATA_OFFSET 0 + +int get_sb_offset(char *path, uint64_t *offset) +{ + char *p = path; + + while (*p == ' ') + p++; + while (*p != ' ' && *p != '\0') + p++; + while (*p == ' ') { + *p = '\0'; + p++; + } + + if (strlen(p) == 0) { + *offset = SB_SECTOR; + return 0; + } + + return kstrtoull(p, 10, offset); +} + /* Superblock */
static const char *read_super(struct cache_sb *sb, struct block_device *bdev, - struct cache_sb_disk **res) + struct cache_sb_disk **res, uint64_t sb_offset) { const char *err; struct cache_sb_disk *s; @@ -68,10 +91,10 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev, unsigned int i;
page = read_cache_page_gfp(bdev->bd_inode->i_mapping, - SB_OFFSET >> PAGE_SHIFT, GFP_KERNEL); + (sb_offset << SECTOR_SHIFT) >> PAGE_SHIFT, GFP_KERNEL); if (IS_ERR(page)) return "IO error"; - s = page_address(page) + offset_in_page(SB_OFFSET); + s = page_address(page) + offset_in_page(sb_offset << SECTOR_SHIFT);
sb->offset = le64_to_cpu(s->offset); sb->version = le64_to_cpu(s->version); @@ -94,7 +117,7 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev, sb->version, sb->flags, sb->seq, sb->keys);
err = "Not a bcache superblock (bad offset)"; - if (sb->offset != SB_SECTOR) + if (sb->offset != sb_offset) goto err;
err = "Not a bcache superblock (bad magic)"; @@ -127,7 +150,11 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev, sb->data_offset = le64_to_cpu(s->data_offset);
err = "Bad data offset"; - if (sb->data_offset < BDEV_DATA_START_DEFAULT) + /* if make-bcache with filesystem on the device, + * the data_offset is set to zero. + */ + if ((sb->data_offset < BDEV_DATA_START_DEFAULT) && + sb->data_offset != WITH_FS_DATA_OFFSET) goto err;
break; @@ -212,7 +239,7 @@ static void __write_super(struct cache_sb *sb, struct cache_sb_disk *out, unsigned int i;
bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_META; - bio->bi_iter.bi_sector = SB_SECTOR; + bio->bi_iter.bi_sector = le64_to_cpu(out->offset); __bio_add_page(bio, virt_to_page(out), SB_SIZE, offset_in_page(out));
@@ -2404,6 +2431,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, struct cache_sb_disk *sb_disk; struct block_device *bdev; ssize_t ret; + uint64_t sb_offset; + int val;
ret = -EBUSY; err = "failed to reference bcache module"; @@ -2426,6 +2455,10 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, if (!sb) goto out_free_path;
+ val = get_sb_offset(path, &sb_offset); + if (val) + return -EINVAL; + ret = -EINVAL; err = "failed to open device"; bdev = blkdev_get_by_path(strim(path), @@ -2452,7 +2485,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, if (set_blocksize(bdev, 4096)) goto out_blkdev_put;
- err = read_super(sb, bdev, &sb_disk); + err = read_super(sb, bdev, &sb_disk, sb_offset); if (err) goto out_blkdev_put;