diff options
author | NeilBrown <neilb@suse.de> | 2012-05-21 23:55:22 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-05-21 23:55:22 -0400 |
commit | bdfd1140731a67c74fd74814f222c8078171adcd (patch) | |
tree | e244aa26d983b56c61fb8d53eb9a1a4105476a85 | |
parent | fae7d326cd0905624c173337fdfcfe9b86b9e6e2 (diff) |
md/bitmap: make _page_attr bitops atomic.
Using e.g. set_bit instead of __set_bit and using test_and_clear_bit
allow us to remove some locking and contract other locked ranges.
It is rare that we set or clear a lot of these bits, so gain should
outweigh any cost.
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/md/bitmap.c | 55 |
1 files changed, 23 insertions, 32 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index d2ab7d3df3ea..2e2f53cd5b21 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -799,21 +799,27 @@ enum bitmap_page_attr { | |||
799 | static inline void set_page_attr(struct bitmap *bitmap, int pnum, | 799 | static inline void set_page_attr(struct bitmap *bitmap, int pnum, |
800 | enum bitmap_page_attr attr) | 800 | enum bitmap_page_attr attr) |
801 | { | 801 | { |
802 | __set_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); | 802 | set_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); |
803 | } | 803 | } |
804 | 804 | ||
805 | static inline void clear_page_attr(struct bitmap *bitmap, int pnum, | 805 | static inline void clear_page_attr(struct bitmap *bitmap, int pnum, |
806 | enum bitmap_page_attr attr) | 806 | enum bitmap_page_attr attr) |
807 | { | 807 | { |
808 | __clear_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); | 808 | clear_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); |
809 | } | 809 | } |
810 | 810 | ||
811 | static inline unsigned long test_page_attr(struct bitmap *bitmap, int pnum, | 811 | static inline int test_page_attr(struct bitmap *bitmap, int pnum, |
812 | enum bitmap_page_attr attr) | 812 | enum bitmap_page_attr attr) |
813 | { | 813 | { |
814 | return test_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); | 814 | return test_bit((pnum<<2) + attr, bitmap->storage.filemap_attr); |
815 | } | 815 | } |
816 | 816 | ||
817 | static inline int test_and_clear_page_attr(struct bitmap *bitmap, int pnum, | ||
818 | enum bitmap_page_attr attr) | ||
819 | { | ||
820 | return test_and_clear_bit((pnum<<2) + attr, | ||
821 | bitmap->storage.filemap_attr); | ||
822 | } | ||
817 | /* | 823 | /* |
818 | * bitmap_file_set_bit -- called before performing a write to the md device | 824 | * bitmap_file_set_bit -- called before performing a write to the md device |
819 | * to set (and eventually sync) a particular bit in the bitmap file | 825 | * to set (and eventually sync) a particular bit in the bitmap file |
@@ -884,23 +890,17 @@ void bitmap_unplug(struct bitmap *bitmap) | |||
884 | /* look at each page to see if there are any set bits that need to be | 890 | /* look at each page to see if there are any set bits that need to be |
885 | * flushed out to disk */ | 891 | * flushed out to disk */ |
886 | for (i = 0; i < bitmap->storage.file_pages; i++) { | 892 | for (i = 0; i < bitmap->storage.file_pages; i++) { |
887 | spin_lock_irq(&bitmap->lock); | 893 | if (!bitmap->storage.filemap) |
888 | if (!bitmap->storage.filemap) { | ||
889 | spin_unlock_irq(&bitmap->lock); | ||
890 | return; | 894 | return; |
891 | } | 895 | dirty = test_and_clear_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); |
892 | dirty = test_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); | 896 | need_write = test_and_clear_page_attr(bitmap, i, |
893 | need_write = test_page_attr(bitmap, i, BITMAP_PAGE_NEEDWRITE); | 897 | BITMAP_PAGE_NEEDWRITE); |
894 | clear_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); | 898 | if (dirty || need_write) { |
895 | clear_page_attr(bitmap, i, BITMAP_PAGE_NEEDWRITE); | ||
896 | if (dirty || need_write) | ||
897 | clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING); | 899 | clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING); |
900 | write_page(bitmap, bitmap->storage.filemap[i], 0); | ||
901 | } | ||
898 | if (dirty) | 902 | if (dirty) |
899 | wait = 1; | 903 | wait = 1; |
900 | spin_unlock_irq(&bitmap->lock); | ||
901 | |||
902 | if (dirty || need_write) | ||
903 | write_page(bitmap, bitmap->storage.filemap[i], 0); | ||
904 | } | 904 | } |
905 | if (wait) { /* if any writes were performed, we need to wait on them */ | 905 | if (wait) { /* if any writes were performed, we need to wait on them */ |
906 | if (bitmap->storage.file) | 906 | if (bitmap->storage.file) |
@@ -1062,12 +1062,10 @@ void bitmap_write_all(struct bitmap *bitmap) | |||
1062 | /* Only one copy, so nothing needed */ | 1062 | /* Only one copy, so nothing needed */ |
1063 | return; | 1063 | return; |
1064 | 1064 | ||
1065 | spin_lock_irq(&bitmap->lock); | ||
1066 | for (i = 0; i < bitmap->storage.file_pages; i++) | 1065 | for (i = 0; i < bitmap->storage.file_pages; i++) |
1067 | set_page_attr(bitmap, i, | 1066 | set_page_attr(bitmap, i, |
1068 | BITMAP_PAGE_NEEDWRITE); | 1067 | BITMAP_PAGE_NEEDWRITE); |
1069 | bitmap->allclean = 0; | 1068 | bitmap->allclean = 0; |
1070 | spin_unlock_irq(&bitmap->lock); | ||
1071 | } | 1069 | } |
1072 | 1070 | ||
1073 | static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc) | 1071 | static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc) |
@@ -1128,15 +1126,11 @@ void bitmap_daemon_work(struct mddev *mddev) | |||
1128 | * So set NEEDWRITE now, then after we make any last-minute changes | 1126 | * So set NEEDWRITE now, then after we make any last-minute changes |
1129 | * we will write it. | 1127 | * we will write it. |
1130 | */ | 1128 | */ |
1131 | spin_lock_irq(&bitmap->lock); | ||
1132 | for (j = 0; j < bitmap->storage.file_pages; j++) | 1129 | for (j = 0; j < bitmap->storage.file_pages; j++) |
1133 | if (test_page_attr(bitmap, j, | 1130 | if (test_and_clear_page_attr(bitmap, j, |
1134 | BITMAP_PAGE_PENDING)) { | 1131 | BITMAP_PAGE_PENDING)) |
1135 | set_page_attr(bitmap, j, | 1132 | set_page_attr(bitmap, j, |
1136 | BITMAP_PAGE_NEEDWRITE); | 1133 | BITMAP_PAGE_NEEDWRITE); |
1137 | clear_page_attr(bitmap, j, | ||
1138 | BITMAP_PAGE_PENDING); | ||
1139 | } | ||
1140 | 1134 | ||
1141 | if (bitmap->need_sync && | 1135 | if (bitmap->need_sync && |
1142 | mddev->bitmap_info.external == 0) { | 1136 | mddev->bitmap_info.external == 0) { |
@@ -1156,6 +1150,7 @@ void bitmap_daemon_work(struct mddev *mddev) | |||
1156 | /* Now look at the bitmap counters and if any are '2' or '1', | 1150 | /* Now look at the bitmap counters and if any are '2' or '1', |
1157 | * decrement and handle accordingly. | 1151 | * decrement and handle accordingly. |
1158 | */ | 1152 | */ |
1153 | spin_lock_irq(&bitmap->lock); | ||
1159 | nextpage = 0; | 1154 | nextpage = 0; |
1160 | for (j = 0; j < bitmap->chunks; j++) { | 1155 | for (j = 0; j < bitmap->chunks; j++) { |
1161 | bitmap_counter_t *bmc; | 1156 | bitmap_counter_t *bmc; |
@@ -1188,6 +1183,7 @@ void bitmap_daemon_work(struct mddev *mddev) | |||
1188 | bitmap->allclean = 0; | 1183 | bitmap->allclean = 0; |
1189 | } | 1184 | } |
1190 | } | 1185 | } |
1186 | spin_unlock_irq(&bitmap->lock); | ||
1191 | 1187 | ||
1192 | /* Now start writeout on any page in NEEDWRITE that isn't DIRTY. | 1188 | /* Now start writeout on any page in NEEDWRITE that isn't DIRTY. |
1193 | * DIRTY pages need to be written by bitmap_unplug so it can wait | 1189 | * DIRTY pages need to be written by bitmap_unplug so it can wait |
@@ -1206,16 +1202,11 @@ void bitmap_daemon_work(struct mddev *mddev) | |||
1206 | BITMAP_PAGE_DIRTY)) | 1202 | BITMAP_PAGE_DIRTY)) |
1207 | /* bitmap_unplug will handle the rest */ | 1203 | /* bitmap_unplug will handle the rest */ |
1208 | break; | 1204 | break; |
1209 | if (test_page_attr(bitmap, j, | 1205 | if (test_and_clear_page_attr(bitmap, j, |
1210 | BITMAP_PAGE_NEEDWRITE)) { | 1206 | BITMAP_PAGE_NEEDWRITE)) { |
1211 | clear_page_attr(bitmap, j, | ||
1212 | BITMAP_PAGE_NEEDWRITE); | ||
1213 | spin_unlock_irq(&bitmap->lock); | ||
1214 | write_page(bitmap, bitmap->storage.filemap[j], 0); | 1207 | write_page(bitmap, bitmap->storage.filemap[j], 0); |
1215 | spin_lock_irq(&bitmap->lock); | ||
1216 | } | 1208 | } |
1217 | } | 1209 | } |
1218 | spin_unlock_irq(&bitmap->lock); | ||
1219 | 1210 | ||
1220 | done: | 1211 | done: |
1221 | if (bitmap->allclean == 0) | 1212 | if (bitmap->allclean == 0) |