aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@cse.unsw.edu.au>2005-08-04 15:53:33 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-08-04 16:00:54 -0400
commit193f1c931517592ec4188d15bf261e4bff368207 (patch)
tree5ba1f6a220f796422cf7314b17813e94aeb3e978
parentaa1595e9f3d0d731bcfc6c2680d5483b78f663dc (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.c52
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
821static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, 821static 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 */
831static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) 830static 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
1429static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, 1427static 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