diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-03 20:29:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-03 20:29:58 -0400 |
commit | 28e68154c5e2793123b248d38cf17b34dcb16d87 (patch) | |
tree | c188dc353782dd0bdc4da099790b3f60c2b94894 /drivers/md | |
parent | 4b30b6d126ca8b23b319f5329570f6855736a095 (diff) | |
parent | edd1ea2a8a2549e4fe58e817d539445729491ecf (diff) |
Merge tag 'dm-4.8-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mike Snitzer:
- a stable fix in both DM crypt and DM log-writes for too large bios
(as generated by bcache)
- two other stable fixes for DM log-writes
- a stable fix for a DM crypt bug that could result in freeing pointers
from uninitialized memory in the tfm allocation error path
- a DM bufio cleanup to discontinue using create_singlethread_workqueue()
* tag 'dm-4.8-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
dm bufio: remove use of deprecated create_singlethread_workqueue()
dm crypt: fix free of bad values after tfm allocation failure
dm crypt: fix error with too large bios
dm log writes: fix check of kthread_run() return value
dm log writes: fix bug with too large bios
dm log writes: move IO accounting earlier to fix error path
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-bufio.c | 2 | ||||
-rw-r--r-- | drivers/md/dm-crypt.c | 9 | ||||
-rw-r--r-- | drivers/md/dm-log-writes.c | 10 |
3 files changed, 14 insertions, 7 deletions
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 6571c81465e1..8625040bae92 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c | |||
@@ -1879,7 +1879,7 @@ static int __init dm_bufio_init(void) | |||
1879 | __cache_size_refresh(); | 1879 | __cache_size_refresh(); |
1880 | mutex_unlock(&dm_bufio_clients_lock); | 1880 | mutex_unlock(&dm_bufio_clients_lock); |
1881 | 1881 | ||
1882 | dm_bufio_wq = create_singlethread_workqueue("dm_bufio_cache"); | 1882 | dm_bufio_wq = alloc_workqueue("dm_bufio_cache", WQ_MEM_RECLAIM, 0); |
1883 | if (!dm_bufio_wq) | 1883 | if (!dm_bufio_wq) |
1884 | return -ENOMEM; | 1884 | return -ENOMEM; |
1885 | 1885 | ||
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index eedba67b0e3e..874295757caa 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -1453,7 +1453,7 @@ static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode) | |||
1453 | unsigned i; | 1453 | unsigned i; |
1454 | int err; | 1454 | int err; |
1455 | 1455 | ||
1456 | cc->tfms = kmalloc(cc->tfms_count * sizeof(struct crypto_skcipher *), | 1456 | cc->tfms = kzalloc(cc->tfms_count * sizeof(struct crypto_skcipher *), |
1457 | GFP_KERNEL); | 1457 | GFP_KERNEL); |
1458 | if (!cc->tfms) | 1458 | if (!cc->tfms) |
1459 | return -ENOMEM; | 1459 | return -ENOMEM; |
@@ -1924,6 +1924,13 @@ static int crypt_map(struct dm_target *ti, struct bio *bio) | |||
1924 | return DM_MAPIO_REMAPPED; | 1924 | return DM_MAPIO_REMAPPED; |
1925 | } | 1925 | } |
1926 | 1926 | ||
1927 | /* | ||
1928 | * Check if bio is too large, split as needed. | ||
1929 | */ | ||
1930 | if (unlikely(bio->bi_iter.bi_size > (BIO_MAX_PAGES << PAGE_SHIFT)) && | ||
1931 | bio_data_dir(bio) == WRITE) | ||
1932 | dm_accept_partial_bio(bio, ((BIO_MAX_PAGES << PAGE_SHIFT) >> SECTOR_SHIFT)); | ||
1933 | |||
1927 | io = dm_per_bio_data(bio, cc->per_bio_data_size); | 1934 | io = dm_per_bio_data(bio, cc->per_bio_data_size); |
1928 | crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector)); | 1935 | crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector)); |
1929 | io->ctx.req = (struct skcipher_request *)(io + 1); | 1936 | io->ctx.req = (struct skcipher_request *)(io + 1); |
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c index 4ab68033f9d1..49e4d8d4558f 100644 --- a/drivers/md/dm-log-writes.c +++ b/drivers/md/dm-log-writes.c | |||
@@ -259,12 +259,12 @@ static int log_one_block(struct log_writes_c *lc, | |||
259 | goto out; | 259 | goto out; |
260 | sector++; | 260 | sector++; |
261 | 261 | ||
262 | bio = bio_alloc(GFP_KERNEL, block->vec_cnt); | 262 | atomic_inc(&lc->io_blocks); |
263 | bio = bio_alloc(GFP_KERNEL, min(block->vec_cnt, BIO_MAX_PAGES)); | ||
263 | if (!bio) { | 264 | if (!bio) { |
264 | DMERR("Couldn't alloc log bio"); | 265 | DMERR("Couldn't alloc log bio"); |
265 | goto error; | 266 | goto error; |
266 | } | 267 | } |
267 | atomic_inc(&lc->io_blocks); | ||
268 | bio->bi_iter.bi_size = 0; | 268 | bio->bi_iter.bi_size = 0; |
269 | bio->bi_iter.bi_sector = sector; | 269 | bio->bi_iter.bi_sector = sector; |
270 | bio->bi_bdev = lc->logdev->bdev; | 270 | bio->bi_bdev = lc->logdev->bdev; |
@@ -282,7 +282,7 @@ static int log_one_block(struct log_writes_c *lc, | |||
282 | if (ret != block->vecs[i].bv_len) { | 282 | if (ret != block->vecs[i].bv_len) { |
283 | atomic_inc(&lc->io_blocks); | 283 | atomic_inc(&lc->io_blocks); |
284 | submit_bio(bio); | 284 | submit_bio(bio); |
285 | bio = bio_alloc(GFP_KERNEL, block->vec_cnt - i); | 285 | bio = bio_alloc(GFP_KERNEL, min(block->vec_cnt - i, BIO_MAX_PAGES)); |
286 | if (!bio) { | 286 | if (!bio) { |
287 | DMERR("Couldn't alloc log bio"); | 287 | DMERR("Couldn't alloc log bio"); |
288 | goto error; | 288 | goto error; |
@@ -459,9 +459,9 @@ static int log_writes_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
459 | goto bad; | 459 | goto bad; |
460 | } | 460 | } |
461 | 461 | ||
462 | ret = -EINVAL; | ||
463 | lc->log_kthread = kthread_run(log_writes_kthread, lc, "log-write"); | 462 | lc->log_kthread = kthread_run(log_writes_kthread, lc, "log-write"); |
464 | if (!lc->log_kthread) { | 463 | if (IS_ERR(lc->log_kthread)) { |
464 | ret = PTR_ERR(lc->log_kthread); | ||
465 | ti->error = "Couldn't alloc kthread"; | 465 | ti->error = "Couldn't alloc kthread"; |
466 | dm_put_device(ti, lc->dev); | 466 | dm_put_device(ti, lc->dev); |
467 | dm_put_device(ti, lc->logdev); | 467 | dm_put_device(ti, lc->logdev); |