diff options
| author | NeilBrown <neilb@suse.de> | 2009-05-06 22:47:19 -0400 |
|---|---|---|
| committer | NeilBrown <neilb@suse.de> | 2009-05-06 22:47:19 -0400 |
| commit | b74fd2826c5acce20e6f691437b2d19372bc2057 (patch) | |
| tree | 818e1fa7a7f91b1ca37279f19ce215f19256d7f0 | |
| parent | b4348f32dae3cb6eb4bc21c7ed8f76c0b11e9d6a (diff) | |
md: fix loading of out-of-date bitmap.
When md is loading a bitmap which it knows is out of date, it fills
each page with 1s and writes it back out again. However the
write_page call makes used of bitmap->file_pages and
bitmap->last_page_size which haven't been set correctly yet. So this
can sometimes fail.
Move the setting of file_pages and last_page_size to before the call
to write_page.
This bug can cause the assembly on an array to fail, thus making the
data inaccessible. Hence I think it is a suitable candidate for
-stable.
Cc: stable@kernel.org
Reported-by: Vojtech Pavlik <vojtech@suse.cz>
Signed-off-by: NeilBrown <neilb@suse.de>
| -rw-r--r-- | drivers/md/bitmap.c | 11 |
1 files changed, 4 insertions, 7 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 1fb91edc7de2..bc1d64b7b63b 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
| @@ -986,6 +986,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | |||
| 986 | oldindex = index; | 986 | oldindex = index; |
| 987 | oldpage = page; | 987 | oldpage = page; |
| 988 | 988 | ||
| 989 | bitmap->filemap[bitmap->file_pages++] = page; | ||
| 990 | bitmap->last_page_size = count; | ||
| 991 | |||
| 989 | if (outofdate) { | 992 | if (outofdate) { |
| 990 | /* | 993 | /* |
| 991 | * if bitmap is out of date, dirty the | 994 | * if bitmap is out of date, dirty the |
| @@ -998,15 +1001,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | |||
| 998 | write_page(bitmap, page, 1); | 1001 | write_page(bitmap, page, 1); |
| 999 | 1002 | ||
| 1000 | ret = -EIO; | 1003 | ret = -EIO; |
| 1001 | if (bitmap->flags & BITMAP_WRITE_ERROR) { | 1004 | if (bitmap->flags & BITMAP_WRITE_ERROR) |
| 1002 | /* release, page not in filemap yet */ | ||
| 1003 | put_page(page); | ||
| 1004 | goto err; | 1005 | goto err; |
| 1005 | } | ||
| 1006 | } | 1006 | } |
| 1007 | |||
| 1008 | bitmap->filemap[bitmap->file_pages++] = page; | ||
| 1009 | bitmap->last_page_size = count; | ||
| 1010 | } | 1007 | } |
| 1011 | paddr = kmap_atomic(page, KM_USER0); | 1008 | paddr = kmap_atomic(page, KM_USER0); |
| 1012 | if (bitmap->flags & BITMAP_HOSTENDIAN) | 1009 | if (bitmap->flags & BITMAP_HOSTENDIAN) |
