aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-05-21 23:55:22 -0400
committerNeilBrown <neilb@suse.de>2012-05-21 23:55:22 -0400
commitbdfd1140731a67c74fd74814f222c8078171adcd (patch)
treee244aa26d983b56c61fb8d53eb9a1a4105476a85
parentfae7d326cd0905624c173337fdfcfe9b86b9e6e2 (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.c55
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 {
799static inline void set_page_attr(struct bitmap *bitmap, int pnum, 799static 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
805static inline void clear_page_attr(struct bitmap *bitmap, int pnum, 805static 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
811static inline unsigned long test_page_attr(struct bitmap *bitmap, int pnum, 811static 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
817static 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
1073static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc) 1071static 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)