diff options
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r-- | drivers/md/bitmap.c | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 814f412a410c..0f1732570770 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -717,9 +717,10 @@ static inline void clear_page_attr(struct bitmap *bitmap, struct page *page, | |||
717 | bitmap->filemap_attr[page->index] &= ~attr; | 717 | bitmap->filemap_attr[page->index] &= ~attr; |
718 | } | 718 | } |
719 | 719 | ||
720 | static inline unsigned long get_page_attr(struct bitmap *bitmap, struct page *page) | 720 | static inline unsigned long test_page_attr(struct bitmap *bitmap, struct page *page, |
721 | enum bitmap_page_attr attr) | ||
721 | { | 722 | { |
722 | return bitmap->filemap_attr[page->index]; | 723 | return bitmap->filemap_attr[page->index] & attr; |
723 | } | 724 | } |
724 | 725 | ||
725 | /* | 726 | /* |
@@ -745,7 +746,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) | |||
745 | 746 | ||
746 | 747 | ||
747 | /* make sure the page stays cached until it gets written out */ | 748 | /* make sure the page stays cached until it gets written out */ |
748 | if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY)) | 749 | if (! test_page_attr(bitmap, page, BITMAP_PAGE_DIRTY)) |
749 | get_page(page); | 750 | get_page(page); |
750 | 751 | ||
751 | /* set the bit */ | 752 | /* set the bit */ |
@@ -769,7 +770,8 @@ static void bitmap_writeback(struct bitmap *bitmap); | |||
769 | * sync the dirty pages of the bitmap file to disk */ | 770 | * sync the dirty pages of the bitmap file to disk */ |
770 | int bitmap_unplug(struct bitmap *bitmap) | 771 | int bitmap_unplug(struct bitmap *bitmap) |
771 | { | 772 | { |
772 | unsigned long i, attr, flags; | 773 | unsigned long i, flags; |
774 | int dirty, need_write; | ||
773 | struct page *page; | 775 | struct page *page; |
774 | int wait = 0; | 776 | int wait = 0; |
775 | int err; | 777 | int err; |
@@ -786,17 +788,18 @@ int bitmap_unplug(struct bitmap *bitmap) | |||
786 | return 0; | 788 | return 0; |
787 | } | 789 | } |
788 | page = bitmap->filemap[i]; | 790 | page = bitmap->filemap[i]; |
789 | attr = get_page_attr(bitmap, page); | 791 | dirty = test_page_attr(bitmap, page, BITMAP_PAGE_DIRTY); |
792 | need_write = test_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); | ||
790 | clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY); | 793 | clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY); |
791 | clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); | 794 | clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); |
792 | if ((attr & BITMAP_PAGE_DIRTY)) | 795 | if (dirty) |
793 | wait = 1; | 796 | wait = 1; |
794 | spin_unlock_irqrestore(&bitmap->lock, flags); | 797 | spin_unlock_irqrestore(&bitmap->lock, flags); |
795 | 798 | ||
796 | if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE)) { | 799 | if (dirty | need_write) { |
797 | err = write_page(bitmap, page, 0); | 800 | err = write_page(bitmap, page, 0); |
798 | if (err == -EAGAIN) { | 801 | if (err == -EAGAIN) { |
799 | if (attr & BITMAP_PAGE_DIRTY) | 802 | if (dirty) |
800 | err = write_page(bitmap, page, 1); | 803 | err = write_page(bitmap, page, 1); |
801 | else | 804 | else |
802 | err = 0; | 805 | err = 0; |
@@ -961,12 +964,11 @@ void bitmap_write_all(struct bitmap *bitmap) | |||
961 | /* We don't actually write all bitmap blocks here, | 964 | /* We don't actually write all bitmap blocks here, |
962 | * just flag them as needing to be written | 965 | * just flag them as needing to be written |
963 | */ | 966 | */ |
967 | int i; | ||
964 | 968 | ||
965 | unsigned long chunks = bitmap->chunks; | 969 | for (i=0; i < bitmap->file_pages; i++) |
966 | unsigned long bytes = (chunks+7)/8 + sizeof(bitmap_super_t); | 970 | set_page_attr(bitmap, bitmap->filemap[i], |
967 | unsigned long num_pages = (bytes + PAGE_SIZE-1) / PAGE_SIZE; | 971 | BITMAP_PAGE_NEEDWRITE); |
968 | while (num_pages--) | ||
969 | bitmap->filemap_attr[num_pages] |= BITMAP_PAGE_NEEDWRITE; | ||
970 | } | 972 | } |
971 | 973 | ||
972 | 974 | ||
@@ -997,7 +999,6 @@ int bitmap_daemon_work(struct bitmap *bitmap) | |||
997 | struct page *page = NULL, *lastpage = NULL; | 999 | struct page *page = NULL, *lastpage = NULL; |
998 | int err = 0; | 1000 | int err = 0; |
999 | int blocks; | 1001 | int blocks; |
1000 | int attr; | ||
1001 | void *paddr; | 1002 | void *paddr; |
1002 | 1003 | ||
1003 | if (bitmap == NULL) | 1004 | if (bitmap == NULL) |
@@ -1019,13 +1020,15 @@ int bitmap_daemon_work(struct bitmap *bitmap) | |||
1019 | 1020 | ||
1020 | if (page != lastpage) { | 1021 | if (page != lastpage) { |
1021 | /* skip this page unless it's marked as needing cleaning */ | 1022 | /* skip this page unless it's marked as needing cleaning */ |
1022 | if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) { | 1023 | if (!test_page_attr(bitmap, page, BITMAP_PAGE_CLEAN)) { |
1023 | if (attr & BITMAP_PAGE_NEEDWRITE) { | 1024 | int need_write = test_page_attr(bitmap, page, |
1025 | BITMAP_PAGE_NEEDWRITE); | ||
1026 | if (need_write) { | ||
1024 | get_page(page); | 1027 | get_page(page); |
1025 | clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); | 1028 | clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); |
1026 | } | 1029 | } |
1027 | spin_unlock_irqrestore(&bitmap->lock, flags); | 1030 | spin_unlock_irqrestore(&bitmap->lock, flags); |
1028 | if (attr & BITMAP_PAGE_NEEDWRITE) { | 1031 | if (need_write) { |
1029 | switch (write_page(bitmap, page, 0)) { | 1032 | switch (write_page(bitmap, page, 0)) { |
1030 | case -EAGAIN: | 1033 | case -EAGAIN: |
1031 | set_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); | 1034 | set_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); |
@@ -1043,7 +1046,7 @@ int bitmap_daemon_work(struct bitmap *bitmap) | |||
1043 | /* grab the new page, sync and release the old */ | 1046 | /* grab the new page, sync and release the old */ |
1044 | get_page(page); | 1047 | get_page(page); |
1045 | if (lastpage != NULL) { | 1048 | if (lastpage != NULL) { |
1046 | if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) { | 1049 | if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) { |
1047 | clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); | 1050 | clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); |
1048 | spin_unlock_irqrestore(&bitmap->lock, flags); | 1051 | spin_unlock_irqrestore(&bitmap->lock, flags); |
1049 | err = write_page(bitmap, lastpage, 0); | 1052 | err = write_page(bitmap, lastpage, 0); |
@@ -1097,7 +1100,7 @@ int bitmap_daemon_work(struct bitmap *bitmap) | |||
1097 | /* now sync the final page */ | 1100 | /* now sync the final page */ |
1098 | if (lastpage != NULL) { | 1101 | if (lastpage != NULL) { |
1099 | spin_lock_irqsave(&bitmap->lock, flags); | 1102 | spin_lock_irqsave(&bitmap->lock, flags); |
1100 | if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) { | 1103 | if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) { |
1101 | clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); | 1104 | clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); |
1102 | spin_unlock_irqrestore(&bitmap->lock, flags); | 1105 | spin_unlock_irqrestore(&bitmap->lock, flags); |
1103 | err = write_page(bitmap, lastpage, 0); | 1106 | err = write_page(bitmap, lastpage, 0); |