diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-11-13 12:19:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-11-13 12:19:20 -0500 |
commit | 5a7a662cc6938cac34456aa7871929b40bc964fe (patch) | |
tree | ab656a418e83333ea0dd44efb472e959a45a85ec | |
parent | 04689e749b7ec156291446028a0ce2e685bf3855 (diff) | |
parent | 9b460d3699324d570a4d4161c3741431887f102f (diff) |
Merge tag 'dm-3.18-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mike Snitzer:
- stable fix for dm-thin that avoids normal IO racing with discard
- stable fix for a dm-cache related bug in dm-btree walking code that
results from using very large fast device (eg 4T) with a very small
cache blocksize (eg 32K) -- this is a very uncommon configuration
- a couple fixes for dm-raid (one for stable and the other addresses a
crash in 3.18-rc1 code)
- stable fix for dm-thinp that addresses a very rare dm-bufio bug
having to do with memory reclaimation (via shrinker) when using
dm-thinp ontop of loopback devices
- fix a leak in dm-stripe target constructor's error path
* tag 'dm-3.18-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
dm btree: fix a recursion depth bug in btree walking code
dm thin: grab a virtual cell before looking up the mapping
dm raid: fix inaccessible superblocks causing oops in configure_discard_support
dm raid: ensure superblock's size matches device's logical block size
dm bufio: change __GFP_IO to __GFP_FS in shrinker callbacks
dm stripe: fix potential for leak in stripe_ctr error path
-rw-r--r-- | drivers/md/dm-bufio.c | 12 | ||||
-rw-r--r-- | drivers/md/dm-raid.c | 17 | ||||
-rw-r--r-- | drivers/md/dm-stripe.c | 4 | ||||
-rw-r--r-- | drivers/md/dm-thin.c | 16 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-btree-internal.h | 6 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-btree-spine.c | 2 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-btree.c | 24 |
7 files changed, 50 insertions, 31 deletions
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 825ca1f87639..afe79719ea32 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c | |||
@@ -1434,9 +1434,9 @@ static void drop_buffers(struct dm_bufio_client *c) | |||
1434 | 1434 | ||
1435 | /* | 1435 | /* |
1436 | * Test if the buffer is unused and too old, and commit it. | 1436 | * Test if the buffer is unused and too old, and commit it. |
1437 | * At if noio is set, we must not do any I/O because we hold | 1437 | * And if GFP_NOFS is used, we must not do any I/O because we hold |
1438 | * dm_bufio_clients_lock and we would risk deadlock if the I/O gets rerouted to | 1438 | * dm_bufio_clients_lock and we would risk deadlock if the I/O gets |
1439 | * different bufio client. | 1439 | * rerouted to different bufio client. |
1440 | */ | 1440 | */ |
1441 | static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp, | 1441 | static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp, |
1442 | unsigned long max_jiffies) | 1442 | unsigned long max_jiffies) |
@@ -1444,7 +1444,7 @@ static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp, | |||
1444 | if (jiffies - b->last_accessed < max_jiffies) | 1444 | if (jiffies - b->last_accessed < max_jiffies) |
1445 | return 0; | 1445 | return 0; |
1446 | 1446 | ||
1447 | if (!(gfp & __GFP_IO)) { | 1447 | if (!(gfp & __GFP_FS)) { |
1448 | if (test_bit(B_READING, &b->state) || | 1448 | if (test_bit(B_READING, &b->state) || |
1449 | test_bit(B_WRITING, &b->state) || | 1449 | test_bit(B_WRITING, &b->state) || |
1450 | test_bit(B_DIRTY, &b->state)) | 1450 | test_bit(B_DIRTY, &b->state)) |
@@ -1486,7 +1486,7 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) | |||
1486 | unsigned long freed; | 1486 | unsigned long freed; |
1487 | 1487 | ||
1488 | c = container_of(shrink, struct dm_bufio_client, shrinker); | 1488 | c = container_of(shrink, struct dm_bufio_client, shrinker); |
1489 | if (sc->gfp_mask & __GFP_IO) | 1489 | if (sc->gfp_mask & __GFP_FS) |
1490 | dm_bufio_lock(c); | 1490 | dm_bufio_lock(c); |
1491 | else if (!dm_bufio_trylock(c)) | 1491 | else if (!dm_bufio_trylock(c)) |
1492 | return SHRINK_STOP; | 1492 | return SHRINK_STOP; |
@@ -1503,7 +1503,7 @@ dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc) | |||
1503 | unsigned long count; | 1503 | unsigned long count; |
1504 | 1504 | ||
1505 | c = container_of(shrink, struct dm_bufio_client, shrinker); | 1505 | c = container_of(shrink, struct dm_bufio_client, shrinker); |
1506 | if (sc->gfp_mask & __GFP_IO) | 1506 | if (sc->gfp_mask & __GFP_FS) |
1507 | dm_bufio_lock(c); | 1507 | dm_bufio_lock(c); |
1508 | else if (!dm_bufio_trylock(c)) | 1508 | else if (!dm_bufio_trylock(c)) |
1509 | return 0; | 1509 | return 0; |
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 4857fa4a5484..07c0fa0fa284 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -789,8 +789,7 @@ struct dm_raid_superblock { | |||
789 | __le32 layout; | 789 | __le32 layout; |
790 | __le32 stripe_sectors; | 790 | __le32 stripe_sectors; |
791 | 791 | ||
792 | __u8 pad[452]; /* Round struct to 512 bytes. */ | 792 | /* Remainder of a logical block is zero-filled when writing (see super_sync()). */ |
793 | /* Always set to 0 when writing. */ | ||
794 | } __packed; | 793 | } __packed; |
795 | 794 | ||
796 | static int read_disk_sb(struct md_rdev *rdev, int size) | 795 | static int read_disk_sb(struct md_rdev *rdev, int size) |
@@ -827,7 +826,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev) | |||
827 | test_bit(Faulty, &(rs->dev[i].rdev.flags))) | 826 | test_bit(Faulty, &(rs->dev[i].rdev.flags))) |
828 | failed_devices |= (1ULL << i); | 827 | failed_devices |= (1ULL << i); |
829 | 828 | ||
830 | memset(sb, 0, sizeof(*sb)); | 829 | memset(sb + 1, 0, rdev->sb_size - sizeof(*sb)); |
831 | 830 | ||
832 | sb->magic = cpu_to_le32(DM_RAID_MAGIC); | 831 | sb->magic = cpu_to_le32(DM_RAID_MAGIC); |
833 | sb->features = cpu_to_le32(0); /* No features yet */ | 832 | sb->features = cpu_to_le32(0); /* No features yet */ |
@@ -862,7 +861,11 @@ static int super_load(struct md_rdev *rdev, struct md_rdev *refdev) | |||
862 | uint64_t events_sb, events_refsb; | 861 | uint64_t events_sb, events_refsb; |
863 | 862 | ||
864 | rdev->sb_start = 0; | 863 | rdev->sb_start = 0; |
865 | rdev->sb_size = sizeof(*sb); | 864 | rdev->sb_size = bdev_logical_block_size(rdev->meta_bdev); |
865 | if (rdev->sb_size < sizeof(*sb) || rdev->sb_size > PAGE_SIZE) { | ||
866 | DMERR("superblock size of a logical block is no longer valid"); | ||
867 | return -EINVAL; | ||
868 | } | ||
866 | 869 | ||
867 | ret = read_disk_sb(rdev, rdev->sb_size); | 870 | ret = read_disk_sb(rdev, rdev->sb_size); |
868 | if (ret) | 871 | if (ret) |
@@ -1169,8 +1172,12 @@ static void configure_discard_support(struct dm_target *ti, struct raid_set *rs) | |||
1169 | raid456 = (rs->md.level == 4 || rs->md.level == 5 || rs->md.level == 6); | 1172 | raid456 = (rs->md.level == 4 || rs->md.level == 5 || rs->md.level == 6); |
1170 | 1173 | ||
1171 | for (i = 0; i < rs->md.raid_disks; i++) { | 1174 | for (i = 0; i < rs->md.raid_disks; i++) { |
1172 | struct request_queue *q = bdev_get_queue(rs->dev[i].rdev.bdev); | 1175 | struct request_queue *q; |
1176 | |||
1177 | if (!rs->dev[i].rdev.bdev) | ||
1178 | continue; | ||
1173 | 1179 | ||
1180 | q = bdev_get_queue(rs->dev[i].rdev.bdev); | ||
1174 | if (!q || !blk_queue_discard(q)) | 1181 | if (!q || !blk_queue_discard(q)) |
1175 | return; | 1182 | return; |
1176 | 1183 | ||
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index d1600d2aa2e2..f8b37d4c05d8 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
@@ -159,8 +159,10 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
159 | sc->stripes_shift = __ffs(stripes); | 159 | sc->stripes_shift = __ffs(stripes); |
160 | 160 | ||
161 | r = dm_set_target_max_io_len(ti, chunk_size); | 161 | r = dm_set_target_max_io_len(ti, chunk_size); |
162 | if (r) | 162 | if (r) { |
163 | kfree(sc); | ||
163 | return r; | 164 | return r; |
165 | } | ||
164 | 166 | ||
165 | ti->num_flush_bios = stripes; | 167 | ti->num_flush_bios = stripes; |
166 | ti->num_discard_bios = stripes; | 168 | ti->num_discard_bios = stripes; |
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 4843801173fe..0f86d802b533 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -1936,6 +1936,14 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) | |||
1936 | return DM_MAPIO_SUBMITTED; | 1936 | return DM_MAPIO_SUBMITTED; |
1937 | } | 1937 | } |
1938 | 1938 | ||
1939 | /* | ||
1940 | * We must hold the virtual cell before doing the lookup, otherwise | ||
1941 | * there's a race with discard. | ||
1942 | */ | ||
1943 | build_virtual_key(tc->td, block, &key); | ||
1944 | if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1, &cell_result)) | ||
1945 | return DM_MAPIO_SUBMITTED; | ||
1946 | |||
1939 | r = dm_thin_find_block(td, block, 0, &result); | 1947 | r = dm_thin_find_block(td, block, 0, &result); |
1940 | 1948 | ||
1941 | /* | 1949 | /* |
@@ -1959,13 +1967,10 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) | |||
1959 | * shared flag will be set in their case. | 1967 | * shared flag will be set in their case. |
1960 | */ | 1968 | */ |
1961 | thin_defer_bio(tc, bio); | 1969 | thin_defer_bio(tc, bio); |
1970 | cell_defer_no_holder_no_free(tc, &cell1); | ||
1962 | return DM_MAPIO_SUBMITTED; | 1971 | return DM_MAPIO_SUBMITTED; |
1963 | } | 1972 | } |
1964 | 1973 | ||
1965 | build_virtual_key(tc->td, block, &key); | ||
1966 | if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1, &cell_result)) | ||
1967 | return DM_MAPIO_SUBMITTED; | ||
1968 | |||
1969 | build_data_key(tc->td, result.block, &key); | 1974 | build_data_key(tc->td, result.block, &key); |
1970 | if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2, &cell_result)) { | 1975 | if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2, &cell_result)) { |
1971 | cell_defer_no_holder_no_free(tc, &cell1); | 1976 | cell_defer_no_holder_no_free(tc, &cell1); |
@@ -1986,6 +1991,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) | |||
1986 | * of doing so. | 1991 | * of doing so. |
1987 | */ | 1992 | */ |
1988 | handle_unserviceable_bio(tc->pool, bio); | 1993 | handle_unserviceable_bio(tc->pool, bio); |
1994 | cell_defer_no_holder_no_free(tc, &cell1); | ||
1989 | return DM_MAPIO_SUBMITTED; | 1995 | return DM_MAPIO_SUBMITTED; |
1990 | } | 1996 | } |
1991 | /* fall through */ | 1997 | /* fall through */ |
@@ -1996,6 +2002,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) | |||
1996 | * provide the hint to load the metadata into cache. | 2002 | * provide the hint to load the metadata into cache. |
1997 | */ | 2003 | */ |
1998 | thin_defer_bio(tc, bio); | 2004 | thin_defer_bio(tc, bio); |
2005 | cell_defer_no_holder_no_free(tc, &cell1); | ||
1999 | return DM_MAPIO_SUBMITTED; | 2006 | return DM_MAPIO_SUBMITTED; |
2000 | 2007 | ||
2001 | default: | 2008 | default: |
@@ -2005,6 +2012,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) | |||
2005 | * pool is switched to fail-io mode. | 2012 | * pool is switched to fail-io mode. |
2006 | */ | 2013 | */ |
2007 | bio_io_error(bio); | 2014 | bio_io_error(bio); |
2015 | cell_defer_no_holder_no_free(tc, &cell1); | ||
2008 | return DM_MAPIO_SUBMITTED; | 2016 | return DM_MAPIO_SUBMITTED; |
2009 | } | 2017 | } |
2010 | } | 2018 | } |
diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h index 37d367bb9aa8..bf2b80d5c470 100644 --- a/drivers/md/persistent-data/dm-btree-internal.h +++ b/drivers/md/persistent-data/dm-btree-internal.h | |||
@@ -42,6 +42,12 @@ struct btree_node { | |||
42 | } __packed; | 42 | } __packed; |
43 | 43 | ||
44 | 44 | ||
45 | /* | ||
46 | * Locks a block using the btree node validator. | ||
47 | */ | ||
48 | int bn_read_lock(struct dm_btree_info *info, dm_block_t b, | ||
49 | struct dm_block **result); | ||
50 | |||
45 | void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, | 51 | void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, |
46 | struct dm_btree_value_type *vt); | 52 | struct dm_btree_value_type *vt); |
47 | 53 | ||
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c index cf9fd676ae44..1b5e13ec7f96 100644 --- a/drivers/md/persistent-data/dm-btree-spine.c +++ b/drivers/md/persistent-data/dm-btree-spine.c | |||
@@ -92,7 +92,7 @@ struct dm_block_validator btree_node_validator = { | |||
92 | 92 | ||
93 | /*----------------------------------------------------------------*/ | 93 | /*----------------------------------------------------------------*/ |
94 | 94 | ||
95 | static int bn_read_lock(struct dm_btree_info *info, dm_block_t b, | 95 | int bn_read_lock(struct dm_btree_info *info, dm_block_t b, |
96 | struct dm_block **result) | 96 | struct dm_block **result) |
97 | { | 97 | { |
98 | return dm_tm_read_lock(info->tm, b, &btree_node_validator, result); | 98 | return dm_tm_read_lock(info->tm, b, &btree_node_validator, result); |
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index 416060c25709..200ac12a1d40 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c | |||
@@ -847,22 +847,26 @@ EXPORT_SYMBOL_GPL(dm_btree_find_lowest_key); | |||
847 | * FIXME: We shouldn't use a recursive algorithm when we have limited stack | 847 | * FIXME: We shouldn't use a recursive algorithm when we have limited stack |
848 | * space. Also this only works for single level trees. | 848 | * space. Also this only works for single level trees. |
849 | */ | 849 | */ |
850 | static int walk_node(struct ro_spine *s, dm_block_t block, | 850 | static int walk_node(struct dm_btree_info *info, dm_block_t block, |
851 | int (*fn)(void *context, uint64_t *keys, void *leaf), | 851 | int (*fn)(void *context, uint64_t *keys, void *leaf), |
852 | void *context) | 852 | void *context) |
853 | { | 853 | { |
854 | int r; | 854 | int r; |
855 | unsigned i, nr; | 855 | unsigned i, nr; |
856 | struct dm_block *node; | ||
856 | struct btree_node *n; | 857 | struct btree_node *n; |
857 | uint64_t keys; | 858 | uint64_t keys; |
858 | 859 | ||
859 | r = ro_step(s, block); | 860 | r = bn_read_lock(info, block, &node); |
860 | n = ro_node(s); | 861 | if (r) |
862 | return r; | ||
863 | |||
864 | n = dm_block_data(node); | ||
861 | 865 | ||
862 | nr = le32_to_cpu(n->header.nr_entries); | 866 | nr = le32_to_cpu(n->header.nr_entries); |
863 | for (i = 0; i < nr; i++) { | 867 | for (i = 0; i < nr; i++) { |
864 | if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) { | 868 | if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) { |
865 | r = walk_node(s, value64(n, i), fn, context); | 869 | r = walk_node(info, value64(n, i), fn, context); |
866 | if (r) | 870 | if (r) |
867 | goto out; | 871 | goto out; |
868 | } else { | 872 | } else { |
@@ -874,7 +878,7 @@ static int walk_node(struct ro_spine *s, dm_block_t block, | |||
874 | } | 878 | } |
875 | 879 | ||
876 | out: | 880 | out: |
877 | ro_pop(s); | 881 | dm_tm_unlock(info->tm, node); |
878 | return r; | 882 | return r; |
879 | } | 883 | } |
880 | 884 | ||
@@ -882,15 +886,7 @@ int dm_btree_walk(struct dm_btree_info *info, dm_block_t root, | |||
882 | int (*fn)(void *context, uint64_t *keys, void *leaf), | 886 | int (*fn)(void *context, uint64_t *keys, void *leaf), |
883 | void *context) | 887 | void *context) |
884 | { | 888 | { |
885 | int r; | ||
886 | struct ro_spine spine; | ||
887 | |||
888 | BUG_ON(info->levels > 1); | 889 | BUG_ON(info->levels > 1); |
889 | 890 | return walk_node(info, root, fn, context); | |
890 | init_ro_spine(&spine, info); | ||
891 | r = walk_node(&spine, root, fn, context); | ||
892 | exit_ro_spine(&spine); | ||
893 | |||
894 | return r; | ||
895 | } | 891 | } |
896 | EXPORT_SYMBOL_GPL(dm_btree_walk); | 892 | EXPORT_SYMBOL_GPL(dm_btree_walk); |