aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bitmap.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@cse.unsw.edu.au>2005-06-21 20:17:18 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-21 22:07:44 -0400
commitcdbb4cc2e5c30895709163d8544057db21ee23e0 (patch)
treeca5037bfa8c51f61fe2c7627f2cbed37697af882 /drivers/md/bitmap.c
parentbc7f77de2cd81718dd789a2cfe68a7cf1b48f016 (diff)
[PATCH] md: make sure md bitmap is cleared on a clean start.
As the array-wide clean bit (in the superblock) is set more agressively than the bits in the bitmap are cleared, it is possible to have an array which is clean despite there being bits set in the bitmap. These bits will currently never get cleared, as they can only be cleared by a resync pass, which never happens. No, when reading bits from disk, be aware of whether the whole array is known to be in sync, and act accordingly. 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>
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r--drivers/md/bitmap.c27
1 files changed, 12 insertions, 15 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 62fac2b3800..275a2aa79b7 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -747,7 +747,7 @@ int bitmap_unplug(struct bitmap *bitmap)
747} 747}
748 748
749static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, 749static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
750 unsigned long sectors, int set); 750 unsigned long sectors, int in_sync);
751/* * bitmap_init_from_disk -- called at bitmap_create time to initialize 751/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
752 * the in-memory bitmap from the on-disk bitmap -- also, sets up the 752 * the in-memory bitmap from the on-disk bitmap -- also, sets up the
753 * memory mapping of the bitmap file 753 * memory mapping of the bitmap file
@@ -756,7 +756,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
756 * previously kicked from the array, we mark all the bits as 756 * previously kicked from the array, we mark all the bits as
757 * 1's in order to cause a full resync. 757 * 1's in order to cause a full resync.
758 */ 758 */
759static int bitmap_init_from_disk(struct bitmap *bitmap) 759static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
760{ 760{
761 unsigned long i, chunks, index, oldindex, bit; 761 unsigned long i, chunks, index, oldindex, bit;
762 struct page *page = NULL, *oldpage = NULL; 762 struct page *page = NULL, *oldpage = NULL;
@@ -782,7 +782,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
782 782
783 bytes = (chunks + 7) / 8; 783 bytes = (chunks + 7) / 8;
784 784
785 num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE + 1; 785 num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE;
786 786
787 if (i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) { 787 if (i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
788 printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n", 788 printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
@@ -854,14 +854,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
854 if (test_bit(bit, page_address(page))) { 854 if (test_bit(bit, page_address(page))) {
855 /* if the disk bit is set, set the memory bit */ 855 /* if the disk bit is set, set the memory bit */
856 bitmap_set_memory_bits(bitmap, 856 bitmap_set_memory_bits(bitmap,
857 i << CHUNK_BLOCK_SHIFT(bitmap), 1, 1); 857 i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
858 bit_cnt++; 858 bit_cnt++;
859 } 859 }
860#if 0
861 else
862 bitmap_set_memory_bits(bitmap,
863 i << CHUNK_BLOCK_SHIFT(bitmap), 1, 0);
864#endif
865 } 860 }
866 861
867 /* everything went OK */ 862 /* everything went OK */
@@ -1331,10 +1326,10 @@ void bitmap_close_sync(struct bitmap *bitmap)
1331} 1326}
1332 1327
1333static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, 1328static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
1334 unsigned long sectors, int set) 1329 unsigned long sectors, int in_sync)
1335{ 1330{
1336 /* For each chunk covered by any of these sectors, set the 1331 /* For each chunk covered by any of these sectors, set the
1337 * resync needed bit, and the counter to 1. They should all 1332 * counter to 1 and set resync_needed unless in_sync. They should all
1338 * be 0 at this point 1333 * be 0 at this point
1339 */ 1334 */
1340 while (sectors) { 1335 while (sectors) {
@@ -1346,10 +1341,12 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
1346 spin_unlock_irq(&bitmap->lock); 1341 spin_unlock_irq(&bitmap->lock);
1347 return; 1342 return;
1348 } 1343 }
1349 if (set && !NEEDED(*bmc)) { 1344 if (! *bmc) {
1350 BUG_ON(*bmc); 1345 struct page *page;
1351 *bmc = NEEDED_MASK | 1; 1346 *bmc = 1 | (in_sync? 0 : NEEDED_MASK);
1352 bitmap_count_page(bitmap, offset, 1); 1347 bitmap_count_page(bitmap, offset, 1);
1348 page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
1349 set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
1353 } 1350 }
1354 spin_unlock_irq(&bitmap->lock); 1351 spin_unlock_irq(&bitmap->lock);
1355 if (sectors > secs) 1352 if (sectors > secs)
@@ -1489,7 +1486,7 @@ int bitmap_create(mddev_t *mddev)
1489 1486
1490 /* now that we have some pages available, initialize the in-memory 1487 /* now that we have some pages available, initialize the in-memory
1491 * bitmap from the on-disk bitmap */ 1488 * bitmap from the on-disk bitmap */
1492 err = bitmap_init_from_disk(bitmap); 1489 err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
1493 if (err) 1490 if (err)
1494 return err; 1491 return err;
1495 1492