[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>
This commit is contained in:
parent
aa1595e9f3
commit
193f1c9315
|
@ -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,
|
||||||
* 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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
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)
|
||||||
|
|
||||||
/* 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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue