Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+23 −29
Original line number Diff line number Diff line
@@ -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
@@ -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;
@@ -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++;
		}
	}
@@ -1426,14 +1424,13 @@ 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);
@@ -1444,17 +1441,13 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
	}
	if (! *bmc) {
		struct page *page;
			*bmc = 1 | (in_sync? 0 : NEEDED_MASK);
		*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);
		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
	 * 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;