diff options
-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; |