Skip to content

Commit

Permalink
[PATCH] md: always honour md bitmap being read from disk
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
NeilBrown authored and Linus Torvalds committed Aug 4, 2005
1 parent aa1595e commit 193f1c9
Showing 1 changed file with 23 additions and 29 deletions.
52 changes: 23 additions & 29 deletions drivers/md/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap)
return 0;
}

static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
unsigned long sectors, int in_sync);
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
* the in-memory bitmap from the on-disk bitmap -- also, sets up the
* memory mapping of the bitmap file
Expand All @@ -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
* 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;
struct page *page = NULL, *oldpage = NULL;
Expand Down Expand Up @@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
}
if (test_bit(bit, page_address(page))) {
/* if the disk bit is set, set the memory bit */
bitmap_set_memory_bits(bitmap,
i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap));
bit_cnt++;
}
}
Expand Down Expand Up @@ -1426,35 +1424,30 @@ void bitmap_close_sync(struct bitmap *bitmap)
}
}

static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
unsigned long sectors, int in_sync)
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
{
/* 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
*/
while (sectors) {
int secs;
bitmap_counter_t *bmc;
spin_lock_irq(&bitmap->lock);
bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
if (!bmc) {
spin_unlock_irq(&bitmap->lock);
return;
}
if (! *bmc) {
struct page *page;
*bmc = 1 | (in_sync? 0 : NEEDED_MASK);
bitmap_count_page(bitmap, offset, 1);
page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}

int secs;
bitmap_counter_t *bmc;
spin_lock_irq(&bitmap->lock);
bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
if (!bmc) {
spin_unlock_irq(&bitmap->lock);
if (sectors > secs)
sectors -= secs;
else
sectors = 0;
return;
}
if (! *bmc) {
struct page *page;
*bmc = 1 | NEEDED_MASK;
bitmap_count_page(bitmap, offset, 1);
page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
spin_unlock_irq(&bitmap->lock);

}

/*
Expand Down Expand Up @@ -1565,7 +1558,8 @@ int bitmap_create(mddev_t *mddev)

/* now that we have some pages available, initialize the in-memory
* bitmap from the on-disk bitmap */
err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
err = bitmap_init_from_disk(bitmap);

if (err)
return err;

Expand Down

0 comments on commit 193f1c9

Please sign in to comment.