diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/bitmap.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 719943763391..8fa3277f72dc 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -111,9 +111,10 @@ static int bitmap_checkpage(struct bitmap *bitmap, unsigned long page, int creat | |||
111 | unsigned char *mappage; | 111 | unsigned char *mappage; |
112 | 112 | ||
113 | if (page >= bitmap->pages) { | 113 | if (page >= bitmap->pages) { |
114 | printk(KERN_ALERT | 114 | /* This can happen if bitmap_start_sync goes beyond |
115 | "%s: invalid bitmap page request: %lu (> %lu)\n", | 115 | * End-of-device while looking for a whole page. |
116 | bmname(bitmap), page, bitmap->pages-1); | 116 | * It is harmless. |
117 | */ | ||
117 | return -EINVAL; | 118 | return -EINVAL; |
118 | } | 119 | } |
119 | 120 | ||
@@ -570,7 +571,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) | |||
570 | else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO || | 571 | else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO || |
571 | le32_to_cpu(sb->version) > BITMAP_MAJOR_HI) | 572 | le32_to_cpu(sb->version) > BITMAP_MAJOR_HI) |
572 | reason = "unrecognized superblock version"; | 573 | reason = "unrecognized superblock version"; |
573 | else if (chunksize < PAGE_SIZE) | 574 | else if (chunksize < 512) |
574 | reason = "bitmap chunksize too small"; | 575 | reason = "bitmap chunksize too small"; |
575 | else if ((1 << ffz(~chunksize)) != chunksize) | 576 | else if ((1 << ffz(~chunksize)) != chunksize) |
576 | reason = "bitmap chunksize not a power of 2"; | 577 | reason = "bitmap chunksize not a power of 2"; |
@@ -1345,8 +1346,8 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto | |||
1345 | } | 1346 | } |
1346 | } | 1347 | } |
1347 | 1348 | ||
1348 | int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, | 1349 | static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, |
1349 | int degraded) | 1350 | int degraded) |
1350 | { | 1351 | { |
1351 | bitmap_counter_t *bmc; | 1352 | bitmap_counter_t *bmc; |
1352 | int rv; | 1353 | int rv; |
@@ -1374,6 +1375,29 @@ int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, | |||
1374 | return rv; | 1375 | return rv; |
1375 | } | 1376 | } |
1376 | 1377 | ||
1378 | int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, | ||
1379 | int degraded) | ||
1380 | { | ||
1381 | /* bitmap_start_sync must always report on multiples of whole | ||
1382 | * pages, otherwise resync (which is very PAGE_SIZE based) will | ||
1383 | * get confused. | ||
1384 | * So call __bitmap_start_sync repeatedly (if needed) until | ||
1385 | * At least PAGE_SIZE>>9 blocks are covered. | ||
1386 | * Return the 'or' of the result. | ||
1387 | */ | ||
1388 | int rv = 0; | ||
1389 | int blocks1; | ||
1390 | |||
1391 | *blocks = 0; | ||
1392 | while (*blocks < (PAGE_SIZE>>9)) { | ||
1393 | rv |= __bitmap_start_sync(bitmap, offset, | ||
1394 | &blocks1, degraded); | ||
1395 | offset += blocks1; | ||
1396 | *blocks += blocks1; | ||
1397 | } | ||
1398 | return rv; | ||
1399 | } | ||
1400 | |||
1377 | void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted) | 1401 | void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted) |
1378 | { | 1402 | { |
1379 | bitmap_counter_t *bmc; | 1403 | bitmap_counter_t *bmc; |