diff options
author | NeilBrown <neilb@cse.unsw.edu.au> | 2005-08-04 15:53:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-08-04 16:00:54 -0400 |
commit | 193f1c931517592ec4188d15bf261e4bff368207 (patch) | |
tree | 5ba1f6a220f796422cf7314b17813e94aeb3e978 | |
parent | aa1595e9f3d0d731bcfc6c2680d5483b78f663dc (diff) |
[PATCH] md: always honour md bitmap being read from disk
The code currently will ignore the bitmap if the array seem to be in-sync.
This is wrong if the array is degraded, and probably wrong anyway. If the
bitmap says some chunks are not in in-sync, and the superblock says everything
IS in sync, then something is clearly wrong, and it is safer to trust the
bitmap.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/md/bitmap.c | 52 |
1 files changed, 23 insertions, 29 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 70bca955e0de..09d32db06d20 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -818,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap) | |||
818 | return 0; | 818 | return 0; |
819 | } | 819 | } |
820 | 820 | ||
821 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, | 821 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset); |
822 | unsigned long sectors, int in_sync); | ||
823 | /* * bitmap_init_from_disk -- called at bitmap_create time to initialize | 822 | /* * bitmap_init_from_disk -- called at bitmap_create time to initialize |
824 | * the in-memory bitmap from the on-disk bitmap -- also, sets up the | 823 | * the in-memory bitmap from the on-disk bitmap -- also, sets up the |
825 | * memory mapping of the bitmap file | 824 | * memory mapping of the bitmap file |
@@ -828,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, | |||
828 | * previously kicked from the array, we mark all the bits as | 827 | * previously kicked from the array, we mark all the bits as |
829 | * 1's in order to cause a full resync. | 828 | * 1's in order to cause a full resync. |
830 | */ | 829 | */ |
831 | static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) | 830 | static int bitmap_init_from_disk(struct bitmap *bitmap) |
832 | { | 831 | { |
833 | unsigned long i, chunks, index, oldindex, bit; | 832 | unsigned long i, chunks, index, oldindex, bit; |
834 | struct page *page = NULL, *oldpage = NULL; | 833 | struct page *page = NULL, *oldpage = NULL; |
@@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) | |||
929 | } | 928 | } |
930 | if (test_bit(bit, page_address(page))) { | 929 | if (test_bit(bit, page_address(page))) { |
931 | /* if the disk bit is set, set the memory bit */ | 930 | /* if the disk bit is set, set the memory bit */ |
932 | bitmap_set_memory_bits(bitmap, | 931 | bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap)); |
933 | i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync); | ||
934 | bit_cnt++; | 932 | bit_cnt++; |
935 | } | 933 | } |
936 | } | 934 | } |
@@ -1426,35 +1424,30 @@ void bitmap_close_sync(struct bitmap *bitmap) | |||
1426 | } | 1424 | } |
1427 | } | 1425 | } |
1428 | 1426 | ||
1429 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, | 1427 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset) |
1430 | unsigned long sectors, int in_sync) | ||
1431 | { | 1428 | { |
1432 | /* For each chunk covered by any of these sectors, set the | 1429 | /* For each chunk covered by any of these sectors, set the |
1433 | * counter to 1 and set resync_needed unless in_sync. They should all | 1430 | * counter to 1 and set resync_needed. They should all |
1434 | * be 0 at this point | 1431 | * be 0 at this point |
1435 | */ | 1432 | */ |
1436 | while (sectors) { | 1433 | |
1437 | int secs; | 1434 | int secs; |
1438 | bitmap_counter_t *bmc; | 1435 | bitmap_counter_t *bmc; |
1439 | spin_lock_irq(&bitmap->lock); | 1436 | spin_lock_irq(&bitmap->lock); |
1440 | bmc = bitmap_get_counter(bitmap, offset, &secs, 1); | 1437 | bmc = bitmap_get_counter(bitmap, offset, &secs, 1); |
1441 | if (!bmc) { | 1438 | if (!bmc) { |
1442 | spin_unlock_irq(&bitmap->lock); | ||
1443 | return; | ||
1444 | } | ||
1445 | if (! *bmc) { | ||
1446 | struct page *page; | ||
1447 | *bmc = 1 | (in_sync? 0 : NEEDED_MASK); | ||
1448 | bitmap_count_page(bitmap, offset, 1); | ||
1449 | page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); | ||
1450 | set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); | ||
1451 | } | ||
1452 | spin_unlock_irq(&bitmap->lock); | 1439 | spin_unlock_irq(&bitmap->lock); |
1453 | if (sectors > secs) | 1440 | return; |
1454 | sectors -= secs; | ||
1455 | else | ||
1456 | sectors = 0; | ||
1457 | } | 1441 | } |
1442 | if (! *bmc) { | ||
1443 | struct page *page; | ||
1444 | *bmc = 1 | NEEDED_MASK; | ||
1445 | bitmap_count_page(bitmap, offset, 1); | ||
1446 | page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); | ||
1447 | set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); | ||
1448 | } | ||
1449 | spin_unlock_irq(&bitmap->lock); | ||
1450 | |||
1458 | } | 1451 | } |
1459 | 1452 | ||
1460 | /* | 1453 | /* |
@@ -1565,7 +1558,8 @@ int bitmap_create(mddev_t *mddev) | |||
1565 | 1558 | ||
1566 | /* now that we have some pages available, initialize the in-memory | 1559 | /* now that we have some pages available, initialize the in-memory |
1567 | * bitmap from the on-disk bitmap */ | 1560 | * bitmap from the on-disk bitmap */ |
1568 | err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector); | 1561 | err = bitmap_init_from_disk(bitmap); |
1562 | |||
1569 | if (err) | 1563 | if (err) |
1570 | return err; | 1564 | return err; |
1571 | 1565 | ||