diff options
Diffstat (limited to 'drivers/md/bitmap.c')
| -rw-r--r-- | drivers/md/bitmap.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 41df4cda66e2..2925219f0881 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
| @@ -520,6 +520,8 @@ success: | |||
| 520 | bitmap->daemon_sleep = daemon_sleep; | 520 | bitmap->daemon_sleep = daemon_sleep; |
| 521 | bitmap->flags |= sb->state; | 521 | bitmap->flags |= sb->state; |
| 522 | bitmap->events_cleared = le64_to_cpu(sb->events_cleared); | 522 | bitmap->events_cleared = le64_to_cpu(sb->events_cleared); |
| 523 | if (sb->state & BITMAP_STALE) | ||
| 524 | bitmap->events_cleared = bitmap->mddev->events; | ||
| 523 | err = 0; | 525 | err = 0; |
| 524 | out: | 526 | out: |
| 525 | kunmap(bitmap->sb_page); | 527 | kunmap(bitmap->sb_page); |
| @@ -818,7 +820,7 @@ int bitmap_unplug(struct bitmap *bitmap) | |||
| 818 | return 0; | 820 | return 0; |
| 819 | } | 821 | } |
| 820 | 822 | ||
| 821 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset); | 823 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed); |
| 822 | /* * bitmap_init_from_disk -- called at bitmap_create time to initialize | 824 | /* * bitmap_init_from_disk -- called at bitmap_create time to initialize |
| 823 | * the in-memory bitmap from the on-disk bitmap -- also, sets up the | 825 | * the in-memory bitmap from the on-disk bitmap -- also, sets up the |
| 824 | * memory mapping of the bitmap file | 826 | * memory mapping of the bitmap file |
| @@ -826,8 +828,11 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset); | |||
| 826 | * if there's no bitmap file, or if the bitmap file had been | 828 | * if there's no bitmap file, or if the bitmap file had been |
| 827 | * previously kicked from the array, we mark all the bits as | 829 | * previously kicked from the array, we mark all the bits as |
| 828 | * 1's in order to cause a full resync. | 830 | * 1's in order to cause a full resync. |
| 831 | * | ||
| 832 | * We ignore all bits for sectors that end earlier than 'start'. | ||
| 833 | * This is used when reading an out-of-date bitmap... | ||
| 829 | */ | 834 | */ |
| 830 | static int bitmap_init_from_disk(struct bitmap *bitmap) | 835 | static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) |
| 831 | { | 836 | { |
| 832 | unsigned long i, chunks, index, oldindex, bit; | 837 | unsigned long i, chunks, index, oldindex, bit; |
| 833 | struct page *page = NULL, *oldpage = NULL; | 838 | struct page *page = NULL, *oldpage = NULL; |
| @@ -914,7 +919,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap) | |||
| 914 | * whole page and write it out | 919 | * whole page and write it out |
| 915 | */ | 920 | */ |
| 916 | memset(page_address(page) + offset, 0xff, | 921 | memset(page_address(page) + offset, 0xff, |
| 917 | PAGE_SIZE - offset); | 922 | PAGE_SIZE - offset); |
| 918 | ret = write_page(bitmap, page, 1); | 923 | ret = write_page(bitmap, page, 1); |
| 919 | if (ret) { | 924 | if (ret) { |
| 920 | kunmap(page); | 925 | kunmap(page); |
| @@ -928,8 +933,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap) | |||
| 928 | } | 933 | } |
| 929 | if (test_bit(bit, page_address(page))) { | 934 | if (test_bit(bit, page_address(page))) { |
| 930 | /* if the disk bit is set, set the memory bit */ | 935 | /* if the disk bit is set, set the memory bit */ |
| 931 | bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap)); | 936 | bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap), |
| 937 | ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start) | ||
| 938 | ); | ||
| 932 | bit_cnt++; | 939 | bit_cnt++; |
| 940 | set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); | ||
| 933 | } | 941 | } |
| 934 | } | 942 | } |
| 935 | 943 | ||
| @@ -1424,7 +1432,7 @@ void bitmap_close_sync(struct bitmap *bitmap) | |||
| 1424 | } | 1432 | } |
| 1425 | } | 1433 | } |
| 1426 | 1434 | ||
| 1427 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset) | 1435 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) |
| 1428 | { | 1436 | { |
| 1429 | /* For each chunk covered by any of these sectors, set the | 1437 | /* For each chunk covered by any of these sectors, set the |
| 1430 | * counter to 1 and set resync_needed. They should all | 1438 | * counter to 1 and set resync_needed. They should all |
| @@ -1441,7 +1449,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset) | |||
| 1441 | } | 1449 | } |
| 1442 | if (! *bmc) { | 1450 | if (! *bmc) { |
| 1443 | struct page *page; | 1451 | struct page *page; |
| 1444 | *bmc = 1 | NEEDED_MASK; | 1452 | *bmc = 1 | (needed?NEEDED_MASK:0); |
| 1445 | bitmap_count_page(bitmap, offset, 1); | 1453 | bitmap_count_page(bitmap, offset, 1); |
| 1446 | page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); | 1454 | page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); |
| 1447 | set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); | 1455 | set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); |
| @@ -1517,6 +1525,7 @@ int bitmap_create(mddev_t *mddev) | |||
| 1517 | unsigned long pages; | 1525 | unsigned long pages; |
| 1518 | struct file *file = mddev->bitmap_file; | 1526 | struct file *file = mddev->bitmap_file; |
| 1519 | int err; | 1527 | int err; |
| 1528 | sector_t start; | ||
| 1520 | 1529 | ||
| 1521 | BUG_ON(sizeof(bitmap_super_t) != 256); | 1530 | BUG_ON(sizeof(bitmap_super_t) != 256); |
| 1522 | 1531 | ||
| @@ -1581,7 +1590,12 @@ int bitmap_create(mddev_t *mddev) | |||
| 1581 | 1590 | ||
| 1582 | /* now that we have some pages available, initialize the in-memory | 1591 | /* now that we have some pages available, initialize the in-memory |
| 1583 | * bitmap from the on-disk bitmap */ | 1592 | * bitmap from the on-disk bitmap */ |
| 1584 | err = bitmap_init_from_disk(bitmap); | 1593 | start = 0; |
| 1594 | if (mddev->degraded == 0 | ||
| 1595 | || bitmap->events_cleared == mddev->events) | ||
| 1596 | /* no need to keep dirty bits to optimise a re-add of a missing device */ | ||
| 1597 | start = mddev->recovery_cp; | ||
| 1598 | err = bitmap_init_from_disk(bitmap, start); | ||
| 1585 | 1599 | ||
| 1586 | if (err) | 1600 | if (err) |
| 1587 | return err; | 1601 | return err; |
