diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-07 13:47:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-07 13:47:20 -0400 |
commit | 81d4bab4ce87228c37ab14a885438544af5c9ce6 (patch) | |
tree | df057fdf7e4e3e255310a0e9092e26efad0d362d | |
parent | dc25ad3fe1152559d5bbc792c1cb1f080a55f233 (diff) | |
parent | 86e3e83b443669dd2bcc5c8a83b23e3aa0694c0d (diff) |
Merge tag 'dm-4.11-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mike Snitzer:
- two stable fixes for the verity target's FEC support
- a stable fix for raid target's raid1 support (when no bitmap is used)
- a 4.11 cache metadata v2 format fix to properly test blocks are clean
* tag 'dm-4.11-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
dm verity fec: fix bufio leaks
dm raid: fix NULL pointer dereference for raid1 without bitmap
dm cache metadata: fix metadata2 format's blocks_are_clean_separate_dirty
dm verity fec: limit error correction recursion
-rw-r--r-- | drivers/md/dm-cache-metadata.c | 8 | ||||
-rw-r--r-- | drivers/md/dm-raid.c | 2 | ||||
-rw-r--r-- | drivers/md/dm-verity-fec.c | 18 | ||||
-rw-r--r-- | drivers/md/dm-verity-fec.h | 4 |
4 files changed, 24 insertions, 8 deletions
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index e4c2c1a1e993..6735c8d6a445 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c | |||
@@ -932,7 +932,7 @@ static int blocks_are_clean_separate_dirty(struct dm_cache_metadata *cmd, | |||
932 | *result = true; | 932 | *result = true; |
933 | 933 | ||
934 | r = dm_bitset_cursor_begin(&cmd->dirty_info, cmd->dirty_root, | 934 | r = dm_bitset_cursor_begin(&cmd->dirty_info, cmd->dirty_root, |
935 | from_cblock(begin), &cmd->dirty_cursor); | 935 | from_cblock(cmd->cache_blocks), &cmd->dirty_cursor); |
936 | if (r) { | 936 | if (r) { |
937 | DMERR("%s: dm_bitset_cursor_begin for dirty failed", __func__); | 937 | DMERR("%s: dm_bitset_cursor_begin for dirty failed", __func__); |
938 | return r; | 938 | return r; |
@@ -959,14 +959,16 @@ static int blocks_are_clean_separate_dirty(struct dm_cache_metadata *cmd, | |||
959 | return 0; | 959 | return 0; |
960 | } | 960 | } |
961 | 961 | ||
962 | begin = to_cblock(from_cblock(begin) + 1); | ||
963 | if (begin == end) | ||
964 | break; | ||
965 | |||
962 | r = dm_bitset_cursor_next(&cmd->dirty_cursor); | 966 | r = dm_bitset_cursor_next(&cmd->dirty_cursor); |
963 | if (r) { | 967 | if (r) { |
964 | DMERR("%s: dm_bitset_cursor_next for dirty failed", __func__); | 968 | DMERR("%s: dm_bitset_cursor_next for dirty failed", __func__); |
965 | dm_bitset_cursor_end(&cmd->dirty_cursor); | 969 | dm_bitset_cursor_end(&cmd->dirty_cursor); |
966 | return r; | 970 | return r; |
967 | } | 971 | } |
968 | |||
969 | begin = to_cblock(from_cblock(begin) + 1); | ||
970 | } | 972 | } |
971 | 973 | ||
972 | dm_bitset_cursor_end(&cmd->dirty_cursor); | 974 | dm_bitset_cursor_end(&cmd->dirty_cursor); |
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index f8564d63982f..1e217ba84d09 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -3726,7 +3726,7 @@ static int raid_preresume(struct dm_target *ti) | |||
3726 | return r; | 3726 | return r; |
3727 | 3727 | ||
3728 | /* Resize bitmap to adjust to changed region size (aka MD bitmap chunksize) */ | 3728 | /* Resize bitmap to adjust to changed region size (aka MD bitmap chunksize) */ |
3729 | if (test_bit(RT_FLAG_RS_BITMAP_LOADED, &rs->runtime_flags) && | 3729 | if (test_bit(RT_FLAG_RS_BITMAP_LOADED, &rs->runtime_flags) && mddev->bitmap && |
3730 | mddev->bitmap_info.chunksize != to_bytes(rs->requested_bitmap_chunk_sectors)) { | 3730 | mddev->bitmap_info.chunksize != to_bytes(rs->requested_bitmap_chunk_sectors)) { |
3731 | r = bitmap_resize(mddev->bitmap, mddev->dev_sectors, | 3731 | r = bitmap_resize(mddev->bitmap, mddev->dev_sectors, |
3732 | to_bytes(rs->requested_bitmap_chunk_sectors), 0); | 3732 | to_bytes(rs->requested_bitmap_chunk_sectors), 0); |
diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 0f0eb8a3d922..78f36012eaca 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c | |||
@@ -146,8 +146,6 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio, | |||
146 | block = fec_buffer_rs_block(v, fio, n, i); | 146 | block = fec_buffer_rs_block(v, fio, n, i); |
147 | res = fec_decode_rs8(v, fio, block, &par[offset], neras); | 147 | res = fec_decode_rs8(v, fio, block, &par[offset], neras); |
148 | if (res < 0) { | 148 | if (res < 0) { |
149 | dm_bufio_release(buf); | ||
150 | |||
151 | r = res; | 149 | r = res; |
152 | goto error; | 150 | goto error; |
153 | } | 151 | } |
@@ -172,6 +170,8 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio, | |||
172 | done: | 170 | done: |
173 | r = corrected; | 171 | r = corrected; |
174 | error: | 172 | error: |
173 | dm_bufio_release(buf); | ||
174 | |||
175 | if (r < 0 && neras) | 175 | if (r < 0 && neras) |
176 | DMERR_LIMIT("%s: FEC %llu: failed to correct: %d", | 176 | DMERR_LIMIT("%s: FEC %llu: failed to correct: %d", |
177 | v->data_dev->name, (unsigned long long)rsb, r); | 177 | v->data_dev->name, (unsigned long long)rsb, r); |
@@ -269,7 +269,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io, | |||
269 | &is_zero) == 0) { | 269 | &is_zero) == 0) { |
270 | /* skip known zero blocks entirely */ | 270 | /* skip known zero blocks entirely */ |
271 | if (is_zero) | 271 | if (is_zero) |
272 | continue; | 272 | goto done; |
273 | 273 | ||
274 | /* | 274 | /* |
275 | * skip if we have already found the theoretical | 275 | * skip if we have already found the theoretical |
@@ -439,6 +439,13 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io, | |||
439 | if (!verity_fec_is_enabled(v)) | 439 | if (!verity_fec_is_enabled(v)) |
440 | return -EOPNOTSUPP; | 440 | return -EOPNOTSUPP; |
441 | 441 | ||
442 | if (fio->level >= DM_VERITY_FEC_MAX_RECURSION) { | ||
443 | DMWARN_LIMIT("%s: FEC: recursion too deep", v->data_dev->name); | ||
444 | return -EIO; | ||
445 | } | ||
446 | |||
447 | fio->level++; | ||
448 | |||
442 | if (type == DM_VERITY_BLOCK_TYPE_METADATA) | 449 | if (type == DM_VERITY_BLOCK_TYPE_METADATA) |
443 | block += v->data_blocks; | 450 | block += v->data_blocks; |
444 | 451 | ||
@@ -470,7 +477,7 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io, | |||
470 | if (r < 0) { | 477 | if (r < 0) { |
471 | r = fec_decode_rsb(v, io, fio, rsb, offset, true); | 478 | r = fec_decode_rsb(v, io, fio, rsb, offset, true); |
472 | if (r < 0) | 479 | if (r < 0) |
473 | return r; | 480 | goto done; |
474 | } | 481 | } |
475 | 482 | ||
476 | if (dest) | 483 | if (dest) |
@@ -480,6 +487,8 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io, | |||
480 | r = verity_for_bv_block(v, io, iter, fec_bv_copy); | 487 | r = verity_for_bv_block(v, io, iter, fec_bv_copy); |
481 | } | 488 | } |
482 | 489 | ||
490 | done: | ||
491 | fio->level--; | ||
483 | return r; | 492 | return r; |
484 | } | 493 | } |
485 | 494 | ||
@@ -520,6 +529,7 @@ void verity_fec_init_io(struct dm_verity_io *io) | |||
520 | memset(fio->bufs, 0, sizeof(fio->bufs)); | 529 | memset(fio->bufs, 0, sizeof(fio->bufs)); |
521 | fio->nbufs = 0; | 530 | fio->nbufs = 0; |
522 | fio->output = NULL; | 531 | fio->output = NULL; |
532 | fio->level = 0; | ||
523 | } | 533 | } |
524 | 534 | ||
525 | /* | 535 | /* |
diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h index 7fa0298b995e..bb31ce87a933 100644 --- a/drivers/md/dm-verity-fec.h +++ b/drivers/md/dm-verity-fec.h | |||
@@ -27,6 +27,9 @@ | |||
27 | #define DM_VERITY_FEC_BUF_MAX \ | 27 | #define DM_VERITY_FEC_BUF_MAX \ |
28 | (1 << (PAGE_SHIFT - DM_VERITY_FEC_BUF_RS_BITS)) | 28 | (1 << (PAGE_SHIFT - DM_VERITY_FEC_BUF_RS_BITS)) |
29 | 29 | ||
30 | /* maximum recursion level for verity_fec_decode */ | ||
31 | #define DM_VERITY_FEC_MAX_RECURSION 4 | ||
32 | |||
30 | #define DM_VERITY_OPT_FEC_DEV "use_fec_from_device" | 33 | #define DM_VERITY_OPT_FEC_DEV "use_fec_from_device" |
31 | #define DM_VERITY_OPT_FEC_BLOCKS "fec_blocks" | 34 | #define DM_VERITY_OPT_FEC_BLOCKS "fec_blocks" |
32 | #define DM_VERITY_OPT_FEC_START "fec_start" | 35 | #define DM_VERITY_OPT_FEC_START "fec_start" |
@@ -58,6 +61,7 @@ struct dm_verity_fec_io { | |||
58 | unsigned nbufs; /* number of buffers allocated */ | 61 | unsigned nbufs; /* number of buffers allocated */ |
59 | u8 *output; /* buffer for corrected output */ | 62 | u8 *output; /* buffer for corrected output */ |
60 | size_t output_pos; | 63 | size_t output_pos; |
64 | unsigned level; /* recursion level */ | ||
61 | }; | 65 | }; |
62 | 66 | ||
63 | #ifdef CONFIG_DM_VERITY_FEC | 67 | #ifdef CONFIG_DM_VERITY_FEC |