aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bitmap.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2007-05-23 16:58:10 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-23 23:14:14 -0400
commitab6085c795a71b6a21afe7469d30a365338add7a (patch)
treed9d901ea1c3401906553ef9e684a1094a1b3083a /drivers/md/bitmap.c
parent787f17feb204ed1c6331892fb8124b80dc9fe288 (diff)
md: don't write more than is required of the last page of a bitmap
It is possible that real data or metadata follows the bitmap without full page alignment. So limit the last write to be only the required number of bytes, rounded up to the hard sector size of the device. Signed-off-by: Neil Brown <neilb@suse.de> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r--drivers/md/bitmap.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 5a4a74c1097c..9620d452d030 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -255,19 +255,25 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
255 255
256} 256}
257 257
258static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait) 258static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
259{ 259{
260 mdk_rdev_t *rdev; 260 mdk_rdev_t *rdev;
261 struct list_head *tmp; 261 struct list_head *tmp;
262 mddev_t *mddev = bitmap->mddev;
262 263
263 ITERATE_RDEV(mddev, rdev, tmp) 264 ITERATE_RDEV(mddev, rdev, tmp)
264 if (test_bit(In_sync, &rdev->flags) 265 if (test_bit(In_sync, &rdev->flags)
265 && !test_bit(Faulty, &rdev->flags)) 266 && !test_bit(Faulty, &rdev->flags)) {
267 int size = PAGE_SIZE;
268 if (page->index == bitmap->file_pages-1)
269 size = roundup(bitmap->last_page_size,
270 bdev_hardsect_size(rdev->bdev));
266 md_super_write(mddev, rdev, 271 md_super_write(mddev, rdev,
267 (rdev->sb_offset<<1) + offset 272 (rdev->sb_offset<<1) + bitmap->offset
268 + page->index * (PAGE_SIZE/512), 273 + page->index * (PAGE_SIZE/512),
269 PAGE_SIZE, 274 size,
270 page); 275 page);
276 }
271 277
272 if (wait) 278 if (wait)
273 md_super_wait(mddev); 279 md_super_wait(mddev);
@@ -282,7 +288,7 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
282 struct buffer_head *bh; 288 struct buffer_head *bh;
283 289
284 if (bitmap->file == NULL) 290 if (bitmap->file == NULL)
285 return write_sb_page(bitmap->mddev, bitmap->offset, page, wait); 291 return write_sb_page(bitmap, page, wait);
286 292
287 bh = page_buffers(page); 293 bh = page_buffers(page);
288 294
@@ -923,6 +929,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
923 } 929 }
924 930
925 bitmap->filemap[bitmap->file_pages++] = page; 931 bitmap->filemap[bitmap->file_pages++] = page;
932 bitmap->last_page_size = count;
926 } 933 }
927 paddr = kmap_atomic(page, KM_USER0); 934 paddr = kmap_atomic(page, KM_USER0);
928 if (bitmap->flags & BITMAP_HOSTENDIAN) 935 if (bitmap->flags & BITMAP_HOSTENDIAN)