Commit 193f1c93 authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

[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: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent aa1595e9
...@@ -818,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap) ...@@ -818,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap)
return 0; return 0;
} }
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
unsigned long sectors, int in_sync);
/* * bitmap_init_from_disk -- called at bitmap_create time to initialize /* * bitmap_init_from_disk -- called at bitmap_create time to initialize
* the in-memory bitmap from the on-disk bitmap -- also, sets up the * the in-memory bitmap from the on-disk bitmap -- also, sets up the
* memory mapping of the bitmap file * memory mapping of the bitmap file
...@@ -828,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, ...@@ -828,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
* previously kicked from the array, we mark all the bits as * previously kicked from the array, we mark all the bits as
* 1's in order to cause a full resync. * 1's in order to cause a full resync.
*/ */
static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) static int bitmap_init_from_disk(struct bitmap *bitmap)
{ {
unsigned long i, chunks, index, oldindex, bit; unsigned long i, chunks, index, oldindex, bit;
struct page *page = NULL, *oldpage = NULL; struct page *page = NULL, *oldpage = NULL;
...@@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) ...@@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
} }
if (test_bit(bit, page_address(page))) { if (test_bit(bit, page_address(page))) {
/* if the disk bit is set, set the memory bit */ /* if the disk bit is set, set the memory bit */
bitmap_set_memory_bits(bitmap, bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap));
i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
bit_cnt++; bit_cnt++;
} }
} }
...@@ -1426,14 +1424,13 @@ void bitmap_close_sync(struct bitmap *bitmap) ...@@ -1426,14 +1424,13 @@ void bitmap_close_sync(struct bitmap *bitmap)
} }
} }
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
unsigned long sectors, int in_sync)
{ {
/* For each chunk covered by any of these sectors, set the /* For each chunk covered by any of these sectors, set the
* counter to 1 and set resync_needed unless in_sync. They should all * counter to 1 and set resync_needed. They should all
* be 0 at this point * be 0 at this point
*/ */
while (sectors) {
int secs; int secs;
bitmap_counter_t *bmc; bitmap_counter_t *bmc;
spin_lock_irq(&bitmap->lock); spin_lock_irq(&bitmap->lock);
...@@ -1444,17 +1441,13 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, ...@@ -1444,17 +1441,13 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
} }
if (! *bmc) { if (! *bmc) {
struct page *page; struct page *page;
*bmc = 1 | (in_sync? 0 : NEEDED_MASK); *bmc = 1 | NEEDED_MASK;
bitmap_count_page(bitmap, offset, 1); bitmap_count_page(bitmap, offset, 1);
page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
} }
spin_unlock_irq(&bitmap->lock); spin_unlock_irq(&bitmap->lock);
if (sectors > secs)
sectors -= secs;
else
sectors = 0;
}
} }
/* /*
...@@ -1565,7 +1558,8 @@ int bitmap_create(mddev_t *mddev) ...@@ -1565,7 +1558,8 @@ int bitmap_create(mddev_t *mddev)
/* now that we have some pages available, initialize the in-memory /* now that we have some pages available, initialize the in-memory
* bitmap from the on-disk bitmap */ * bitmap from the on-disk bitmap */
err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector); err = bitmap_init_from_disk(bitmap);
if (err) if (err)
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment