1
0
Fork 0

md: Don't read past end of bitmap when reading bitmap.

When we read the write-intent-bitmap off the device, we currently
read a whole number of pages.
When PAGE_SIZE is 4K, this works due to the alignment we enforce
on the superblock and bitmap.
When PAGE_SIZE is 64K, this case read past the end-of-device
which causes an error.

When we write the superblock, we ensure to clip the last page
to just be the required size.  Copy that code into the read path
to just read the required number of sectors.

Signed-off-by: Neil Brown <neilb@suse.de>
Cc: stable@kernel.org
wifi-calibration
NeilBrown 2008-12-19 16:25:01 +11:00
parent 55dac3a555
commit a2ed9615e3
1 changed files with 17 additions and 5 deletions

View File

@ -208,15 +208,18 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
*/
/* IO operations when bitmap is stored near all superblocks */
static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long index)
static struct page *read_sb_page(mddev_t *mddev, long offset,
struct page *page,
unsigned long index, int size)
{
/* choose a good rdev and read the page from there */
mdk_rdev_t *rdev;
struct list_head *tmp;
struct page *page = alloc_page(GFP_KERNEL);
sector_t target;
if (!page)
page = alloc_page(GFP_KERNEL);
if (!page)
return ERR_PTR(-ENOMEM);
@ -227,7 +230,9 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
target = rdev->sb_start + offset + index * (PAGE_SIZE/512);
if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
if (sync_page_io(rdev->bdev, target,
roundup(size, bdev_hardsect_size(rdev->bdev)),
page, READ)) {
page->index = index;
attach_page_buffers(page, NULL); /* so that free_buffer will
* quietly no-op */
@ -544,7 +549,9 @@ static int bitmap_read_sb(struct bitmap *bitmap)
bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes);
} else {
bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0);
bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset,
NULL,
0, sizeof(bitmap_super_t));
}
if (IS_ERR(bitmap->sb_page)) {
err = PTR_ERR(bitmap->sb_page);
@ -957,11 +964,16 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
*/
page = bitmap->sb_page;
offset = sizeof(bitmap_super_t);
read_sb_page(bitmap->mddev, bitmap->offset,
page,
index, count);
} else if (file) {
page = read_page(file, index, bitmap, count);
offset = 0;
} else {
page = read_sb_page(bitmap->mddev, bitmap->offset, index);
page = read_sb_page(bitmap->mddev, bitmap->offset,
NULL,
index, count);
offset = 0;
}
if (IS_ERR(page)) { /* read error */