Skip to content

Commit

Permalink
md: Don't read past end of bitmap when reading bitmap.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
NeilBrown committed Dec 19, 2008
1 parent 55dac3a commit a2ed961
Showing 1 changed file with 17 additions and 5 deletions.
22 changes: 17 additions & 5 deletions drivers/md/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit a2ed961

Please sign in to comment.