- Fix incorrect uses of kstrndup and DM logging macros in DM's early
init code. - Fix DM log-writes target's handling of super block sectors so updates are made in order through use of completion. - Fix DM core's argument splitting code to avoid undefined behaviour reported as a side-effect of UBSAN analysis on ppc64le. - Fix DM verity target to limit the amount of error messages that can result from a corrupt block being found. -----BEGIN PGP SIGNATURE----- iQFHBAABCAAxFiEEJfWUX4UqZ4x1O2wixSPxCi2dA1oFAl0VBp4THHNuaXR6ZXJA cmVkaGF0LmNvbQAKCRDFI/EKLZ0DWlLKB/9wnB1FWhVIwt5j0e3YpqToThptT22N sWO/vBKtIR8nbbohXeam7mgh15+D61SpY+8jdkgAlIQonPzCwFrgSWdtpbbveYw6 gFWAdd013R+piGX40l0EztwAQ9IawwFl7JP+fBevxFQdGAVT6SpaJfBWH0XcIBbb udEtoeW0dVp06SFsokGq6TPSRCdxwMh9JpRplgtLmz0yhfsWeFivjw2AMIen5QqB Z0zcJnL8UMRdJq0EEqjQ3z9CH/Th8Nryxibo8YLnADPBfv7RyR2+wCjrbode8LAj LZHjHikxzt39F9PpJIPvVuvNMzrBdQPDF61O5MK7dOMl49GfIoz2ybvH =oEWd -----END PGP SIGNATURE----- Merge tag 'for-5.2/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm Pull device mapper fixes from Mike Snitzer: - Fix incorrect uses of kstrndup and DM logging macros in DM's early init code. - Fix DM log-writes target's handling of super block sectors so updates are made in order through use of completion. - Fix DM core's argument splitting code to avoid undefined behaviour reported as a side-effect of UBSAN analysis on ppc64le. - Fix DM verity target to limit the amount of error messages that can result from a corrupt block being found. * tag 'for-5.2/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm verity: use message limit for data block corruption message dm table: don't copy from a NULL pointer in realloc_argv() dm log writes: make sure super sector log updates are written in order dm init: remove trailing newline from calls to DMERR() and DMINFO() dm init: fix incorrect uses of kstrndup()
This commit is contained in:
commit
65ee21eb63
|
@ -140,8 +140,8 @@ static char __init *dm_parse_table_entry(struct dm_device *dev, char *str)
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
/* target_args */
|
||||
dev->target_args_array[n] = kstrndup(field[3], GFP_KERNEL,
|
||||
DM_MAX_STR_SIZE);
|
||||
dev->target_args_array[n] = kstrndup(field[3], DM_MAX_STR_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (!dev->target_args_array[n])
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
@ -272,10 +272,10 @@ static int __init dm_init_init(void)
|
|||
return 0;
|
||||
|
||||
if (strlen(create) >= DM_MAX_STR_SIZE) {
|
||||
DMERR("Argument is too big. Limit is %d\n", DM_MAX_STR_SIZE);
|
||||
DMERR("Argument is too big. Limit is %d", DM_MAX_STR_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
str = kstrndup(create, GFP_KERNEL, DM_MAX_STR_SIZE);
|
||||
str = kstrndup(create, DM_MAX_STR_SIZE, GFP_KERNEL);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -283,7 +283,7 @@ static int __init dm_init_init(void)
|
|||
if (r)
|
||||
goto out;
|
||||
|
||||
DMINFO("waiting for all devices to be available before creating mapped devices\n");
|
||||
DMINFO("waiting for all devices to be available before creating mapped devices");
|
||||
wait_for_device_probe();
|
||||
|
||||
list_for_each_entry(dev, &devices, list) {
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
#define WRITE_LOG_VERSION 1ULL
|
||||
#define WRITE_LOG_MAGIC 0x6a736677736872ULL
|
||||
#define WRITE_LOG_SUPER_SECTOR 0
|
||||
|
||||
/*
|
||||
* The disk format for this is braindead simple.
|
||||
|
@ -115,6 +116,7 @@ struct log_writes_c {
|
|||
struct list_head logging_blocks;
|
||||
wait_queue_head_t wait;
|
||||
struct task_struct *log_kthread;
|
||||
struct completion super_done;
|
||||
};
|
||||
|
||||
struct pending_block {
|
||||
|
@ -180,6 +182,14 @@ static void log_end_io(struct bio *bio)
|
|||
bio_put(bio);
|
||||
}
|
||||
|
||||
static void log_end_super(struct bio *bio)
|
||||
{
|
||||
struct log_writes_c *lc = bio->bi_private;
|
||||
|
||||
complete(&lc->super_done);
|
||||
log_end_io(bio);
|
||||
}
|
||||
|
||||
/*
|
||||
* Meant to be called if there is an error, it will free all the pages
|
||||
* associated with the block.
|
||||
|
@ -215,7 +225,8 @@ static int write_metadata(struct log_writes_c *lc, void *entry,
|
|||
bio->bi_iter.bi_size = 0;
|
||||
bio->bi_iter.bi_sector = sector;
|
||||
bio_set_dev(bio, lc->logdev->bdev);
|
||||
bio->bi_end_io = log_end_io;
|
||||
bio->bi_end_io = (sector == WRITE_LOG_SUPER_SECTOR) ?
|
||||
log_end_super : log_end_io;
|
||||
bio->bi_private = lc;
|
||||
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
|
||||
|
||||
|
@ -418,11 +429,18 @@ static int log_super(struct log_writes_c *lc)
|
|||
super.nr_entries = cpu_to_le64(lc->logged_entries);
|
||||
super.sectorsize = cpu_to_le32(lc->sectorsize);
|
||||
|
||||
if (write_metadata(lc, &super, sizeof(super), NULL, 0, 0)) {
|
||||
if (write_metadata(lc, &super, sizeof(super), NULL, 0,
|
||||
WRITE_LOG_SUPER_SECTOR)) {
|
||||
DMERR("Couldn't write super");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Super sector should be writen in-order, otherwise the
|
||||
* nr_entries could be rewritten incorrectly by an old bio.
|
||||
*/
|
||||
wait_for_completion_io(&lc->super_done);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -531,6 +549,7 @@ static int log_writes_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|||
INIT_LIST_HEAD(&lc->unflushed_blocks);
|
||||
INIT_LIST_HEAD(&lc->logging_blocks);
|
||||
init_waitqueue_head(&lc->wait);
|
||||
init_completion(&lc->super_done);
|
||||
atomic_set(&lc->io_blocks, 0);
|
||||
atomic_set(&lc->pending_blocks, 0);
|
||||
|
||||
|
|
|
@ -561,7 +561,7 @@ static char **realloc_argv(unsigned *size, char **old_argv)
|
|||
gfp = GFP_NOIO;
|
||||
}
|
||||
argv = kmalloc_array(new_size, sizeof(*argv), gfp);
|
||||
if (argv) {
|
||||
if (argv && old_argv) {
|
||||
memcpy(argv, old_argv, *size * sizeof(*argv));
|
||||
*size = new_size;
|
||||
}
|
||||
|
|
|
@ -235,8 +235,8 @@ static int verity_handle_err(struct dm_verity *v, enum verity_block_type type,
|
|||
BUG();
|
||||
}
|
||||
|
||||
DMERR("%s: %s block %llu is corrupted", v->data_dev->name, type_str,
|
||||
block);
|
||||
DMERR_LIMIT("%s: %s block %llu is corrupted", v->data_dev->name,
|
||||
type_str, block);
|
||||
|
||||
if (v->corrupted_errs == DM_VERITY_MAX_CORRUPTED_ERRS)
|
||||
DMERR("%s: reached maximum errors", v->data_dev->name);
|
||||
|
|
Loading…
Reference in New Issue