diff options
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r-- | drivers/md/bitmap.c | 213 |
1 files changed, 112 insertions, 101 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 17e2b472e16d..c7784a985676 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -883,6 +883,8 @@ void bitmap_unplug(struct bitmap *bitmap) | |||
883 | need_write = test_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); | 883 | need_write = test_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); |
884 | clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY); | 884 | clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY); |
885 | clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); | 885 | clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); |
886 | if (dirty || need_write) | ||
887 | clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING); | ||
886 | if (dirty) | 888 | if (dirty) |
887 | wait = 1; | 889 | wait = 1; |
888 | spin_unlock_irqrestore(&bitmap->lock, flags); | 890 | spin_unlock_irqrestore(&bitmap->lock, flags); |
@@ -1086,6 +1088,17 @@ static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc) | |||
1086 | bitmap->bp[page].count += inc; | 1088 | bitmap->bp[page].count += inc; |
1087 | bitmap_checkfree(bitmap, page); | 1089 | bitmap_checkfree(bitmap, page); |
1088 | } | 1090 | } |
1091 | |||
1092 | static void bitmap_set_pending(struct bitmap *bitmap, sector_t offset) | ||
1093 | { | ||
1094 | sector_t chunk = offset >> bitmap->chunkshift; | ||
1095 | unsigned long page = chunk >> PAGE_COUNTER_SHIFT; | ||
1096 | struct bitmap_page *bp = &bitmap->bp[page]; | ||
1097 | |||
1098 | if (!bp->pending) | ||
1099 | bp->pending = 1; | ||
1100 | } | ||
1101 | |||
1089 | static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, | 1102 | static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, |
1090 | sector_t offset, sector_t *blocks, | 1103 | sector_t offset, sector_t *blocks, |
1091 | int create); | 1104 | int create); |
@@ -1099,8 +1112,8 @@ void bitmap_daemon_work(struct mddev *mddev) | |||
1099 | { | 1112 | { |
1100 | struct bitmap *bitmap; | 1113 | struct bitmap *bitmap; |
1101 | unsigned long j; | 1114 | unsigned long j; |
1115 | unsigned long nextpage; | ||
1102 | unsigned long flags; | 1116 | unsigned long flags; |
1103 | struct page *page = NULL, *lastpage = NULL; | ||
1104 | sector_t blocks; | 1117 | sector_t blocks; |
1105 | void *paddr; | 1118 | void *paddr; |
1106 | 1119 | ||
@@ -1124,114 +1137,120 @@ void bitmap_daemon_work(struct mddev *mddev) | |||
1124 | } | 1137 | } |
1125 | bitmap->allclean = 1; | 1138 | bitmap->allclean = 1; |
1126 | 1139 | ||
1140 | /* Any file-page which is PENDING now needs to be written. | ||
1141 | * So set NEEDWRITE now, then after we make any last-minute changes | ||
1142 | * we will write it. | ||
1143 | */ | ||
1127 | spin_lock_irqsave(&bitmap->lock, flags); | 1144 | spin_lock_irqsave(&bitmap->lock, flags); |
1145 | if (!bitmap->filemap) | ||
1146 | /* error or shutdown */ | ||
1147 | goto out; | ||
1148 | |||
1149 | for (j = 0; j < bitmap->file_pages; j++) | ||
1150 | if (test_page_attr(bitmap, bitmap->filemap[j], | ||
1151 | BITMAP_PAGE_PENDING)) { | ||
1152 | set_page_attr(bitmap, bitmap->filemap[j], | ||
1153 | BITMAP_PAGE_NEEDWRITE); | ||
1154 | clear_page_attr(bitmap, bitmap->filemap[j], | ||
1155 | BITMAP_PAGE_PENDING); | ||
1156 | } | ||
1157 | |||
1158 | if (bitmap->need_sync && | ||
1159 | mddev->bitmap_info.external == 0) { | ||
1160 | /* Arrange for superblock update as well as | ||
1161 | * other changes */ | ||
1162 | bitmap_super_t *sb; | ||
1163 | bitmap->need_sync = 0; | ||
1164 | sb = kmap_atomic(bitmap->sb_page); | ||
1165 | sb->events_cleared = | ||
1166 | cpu_to_le64(bitmap->events_cleared); | ||
1167 | kunmap_atomic(sb); | ||
1168 | set_page_attr(bitmap, bitmap->sb_page, BITMAP_PAGE_NEEDWRITE); | ||
1169 | } | ||
1170 | /* Now look at the bitmap counters and if any are '2' or '1', | ||
1171 | * decrement and handle accordingly. | ||
1172 | */ | ||
1173 | nextpage = 0; | ||
1128 | for (j = 0; j < bitmap->chunks; j++) { | 1174 | for (j = 0; j < bitmap->chunks; j++) { |
1129 | bitmap_counter_t *bmc; | 1175 | bitmap_counter_t *bmc; |
1130 | if (!bitmap->filemap) | ||
1131 | /* error or shutdown */ | ||
1132 | break; | ||
1133 | 1176 | ||
1134 | page = filemap_get_page(bitmap, j); | 1177 | if (j == nextpage) { |
1135 | 1178 | nextpage += PAGE_COUNTER_RATIO; | |
1136 | if (page != lastpage) { | 1179 | if (!bitmap->bp[j >> PAGE_COUNTER_SHIFT].pending) { |
1137 | /* skip this page unless it's marked as needing cleaning */ | 1180 | j |= PAGE_COUNTER_MASK; |
1138 | if (!test_page_attr(bitmap, page, BITMAP_PAGE_PENDING)) { | ||
1139 | int need_write = test_page_attr(bitmap, page, | ||
1140 | BITMAP_PAGE_NEEDWRITE); | ||
1141 | if (need_write) | ||
1142 | clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); | ||
1143 | |||
1144 | spin_unlock_irqrestore(&bitmap->lock, flags); | ||
1145 | if (need_write) | ||
1146 | write_page(bitmap, page, 0); | ||
1147 | spin_lock_irqsave(&bitmap->lock, flags); | ||
1148 | j |= (PAGE_BITS - 1); | ||
1149 | continue; | 1181 | continue; |
1150 | } | 1182 | } |
1151 | 1183 | bitmap->bp[j >> PAGE_COUNTER_SHIFT].pending = 0; | |
1152 | /* grab the new page, sync and release the old */ | ||
1153 | if (lastpage != NULL) { | ||
1154 | if (test_page_attr(bitmap, lastpage, | ||
1155 | BITMAP_PAGE_NEEDWRITE)) { | ||
1156 | clear_page_attr(bitmap, lastpage, | ||
1157 | BITMAP_PAGE_NEEDWRITE); | ||
1158 | spin_unlock_irqrestore(&bitmap->lock, flags); | ||
1159 | write_page(bitmap, lastpage, 0); | ||
1160 | } else { | ||
1161 | set_page_attr(bitmap, lastpage, | ||
1162 | BITMAP_PAGE_NEEDWRITE); | ||
1163 | bitmap->allclean = 0; | ||
1164 | spin_unlock_irqrestore(&bitmap->lock, flags); | ||
1165 | } | ||
1166 | } else | ||
1167 | spin_unlock_irqrestore(&bitmap->lock, flags); | ||
1168 | lastpage = page; | ||
1169 | |||
1170 | /* We are possibly going to clear some bits, so make | ||
1171 | * sure that events_cleared is up-to-date. | ||
1172 | */ | ||
1173 | if (bitmap->need_sync && | ||
1174 | mddev->bitmap_info.external == 0) { | ||
1175 | bitmap_super_t *sb; | ||
1176 | bitmap->need_sync = 0; | ||
1177 | sb = kmap_atomic(bitmap->sb_page); | ||
1178 | sb->events_cleared = | ||
1179 | cpu_to_le64(bitmap->events_cleared); | ||
1180 | kunmap_atomic(sb); | ||
1181 | write_page(bitmap, bitmap->sb_page, 1); | ||
1182 | } | ||
1183 | spin_lock_irqsave(&bitmap->lock, flags); | ||
1184 | if (!bitmap->need_sync) | ||
1185 | clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING); | ||
1186 | else | ||
1187 | bitmap->allclean = 0; | ||
1188 | } | 1184 | } |
1189 | bmc = bitmap_get_counter(bitmap, | 1185 | bmc = bitmap_get_counter(bitmap, |
1190 | (sector_t)j << bitmap->chunkshift, | 1186 | (sector_t)j << bitmap->chunkshift, |
1191 | &blocks, 0); | 1187 | &blocks, 0); |
1192 | if (!bmc) | 1188 | |
1189 | if (!bmc) { | ||
1193 | j |= PAGE_COUNTER_MASK; | 1190 | j |= PAGE_COUNTER_MASK; |
1194 | else if (*bmc) { | 1191 | continue; |
1195 | if (*bmc == 1 && !bitmap->need_sync) { | 1192 | } |
1196 | /* we can clear the bit */ | 1193 | if (*bmc == 1 && !bitmap->need_sync) { |
1197 | *bmc = 0; | 1194 | /* We can clear the bit */ |
1198 | bitmap_count_page(bitmap, | 1195 | struct page *page; |
1199 | (sector_t)j << bitmap->chunkshift, | 1196 | *bmc = 0; |
1200 | -1); | 1197 | bitmap_count_page( |
1201 | 1198 | bitmap, | |
1202 | /* clear the bit */ | 1199 | (sector_t)j << bitmap->chunkshift, |
1203 | paddr = kmap_atomic(page); | 1200 | -1); |
1204 | if (bitmap->flags & BITMAP_HOSTENDIAN) | 1201 | |
1205 | clear_bit(file_page_offset(bitmap, j), | 1202 | page = filemap_get_page(bitmap, j); |
1206 | paddr); | 1203 | paddr = kmap_atomic(page); |
1207 | else | 1204 | if (bitmap->flags & BITMAP_HOSTENDIAN) |
1208 | __clear_bit_le( | 1205 | clear_bit(file_page_offset(bitmap, j), |
1209 | file_page_offset(bitmap, | 1206 | paddr); |
1210 | j), | 1207 | else |
1211 | paddr); | 1208 | __clear_bit_le(file_page_offset(bitmap, j), |
1212 | kunmap_atomic(paddr); | 1209 | paddr); |
1213 | } else if (*bmc <= 2) { | 1210 | kunmap_atomic(paddr); |
1214 | *bmc = 1; /* maybe clear the bit next time */ | 1211 | if (!test_page_attr(bitmap, page, |
1215 | set_page_attr(bitmap, page, BITMAP_PAGE_PENDING); | 1212 | BITMAP_PAGE_NEEDWRITE)) { |
1213 | set_page_attr(bitmap, page, | ||
1214 | BITMAP_PAGE_PENDING); | ||
1216 | bitmap->allclean = 0; | 1215 | bitmap->allclean = 0; |
1217 | } | 1216 | } |
1217 | } else if (*bmc && *bmc <= 2) { | ||
1218 | *bmc = 1; | ||
1219 | bitmap_set_pending( | ||
1220 | bitmap, | ||
1221 | (sector_t)j << bitmap->chunkshift); | ||
1222 | bitmap->allclean = 0; | ||
1218 | } | 1223 | } |
1219 | } | 1224 | } |
1220 | spin_unlock_irqrestore(&bitmap->lock, flags); | ||
1221 | 1225 | ||
1222 | /* now sync the final page */ | 1226 | /* Now start writeout on any page in NEEDWRITE that isn't DIRTY. |
1223 | if (lastpage != NULL) { | 1227 | * DIRTY pages need to be written by bitmap_unplug so it can wait |
1224 | spin_lock_irqsave(&bitmap->lock, flags); | 1228 | * for them. |
1225 | if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) { | 1229 | * If we find any DIRTY page we stop there and let bitmap_unplug |
1226 | clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); | 1230 | * handle all the rest. This is important in the case where |
1227 | spin_unlock_irqrestore(&bitmap->lock, flags); | 1231 | * the first blocking holds the superblock and it has been updated. |
1228 | write_page(bitmap, lastpage, 0); | 1232 | * We mustn't write any other blocks before the superblock. |
1229 | } else { | 1233 | */ |
1230 | set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); | 1234 | for (j = 0; j < bitmap->file_pages; j++) { |
1231 | bitmap->allclean = 0; | 1235 | struct page *page = bitmap->filemap[j]; |
1236 | |||
1237 | if (test_page_attr(bitmap, page, | ||
1238 | BITMAP_PAGE_DIRTY)) | ||
1239 | /* bitmap_unplug will handle the rest */ | ||
1240 | break; | ||
1241 | if (test_page_attr(bitmap, page, | ||
1242 | BITMAP_PAGE_NEEDWRITE)) { | ||
1243 | clear_page_attr(bitmap, page, | ||
1244 | BITMAP_PAGE_NEEDWRITE); | ||
1232 | spin_unlock_irqrestore(&bitmap->lock, flags); | 1245 | spin_unlock_irqrestore(&bitmap->lock, flags); |
1246 | write_page(bitmap, page, 0); | ||
1247 | spin_lock_irqsave(&bitmap->lock, flags); | ||
1248 | if (!bitmap->filemap) | ||
1249 | break; | ||
1233 | } | 1250 | } |
1234 | } | 1251 | } |
1252 | out: | ||
1253 | spin_unlock_irqrestore(&bitmap->lock, flags); | ||
1235 | 1254 | ||
1236 | done: | 1255 | done: |
1237 | if (bitmap->allclean == 0) | 1256 | if (bitmap->allclean == 0) |
@@ -1386,11 +1405,7 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto | |||
1386 | 1405 | ||
1387 | (*bmc)--; | 1406 | (*bmc)--; |
1388 | if (*bmc <= 2) { | 1407 | if (*bmc <= 2) { |
1389 | set_page_attr(bitmap, | 1408 | bitmap_set_pending(bitmap, offset); |
1390 | filemap_get_page( | ||
1391 | bitmap, | ||
1392 | offset >> bitmap->chunkshift), | ||
1393 | BITMAP_PAGE_PENDING); | ||
1394 | bitmap->allclean = 0; | 1409 | bitmap->allclean = 0; |
1395 | } | 1410 | } |
1396 | spin_unlock_irqrestore(&bitmap->lock, flags); | 1411 | spin_unlock_irqrestore(&bitmap->lock, flags); |
@@ -1476,9 +1491,7 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i | |||
1476 | *bmc |= NEEDED_MASK; | 1491 | *bmc |= NEEDED_MASK; |
1477 | else { | 1492 | else { |
1478 | if (*bmc <= 2) { | 1493 | if (*bmc <= 2) { |
1479 | set_page_attr(bitmap, | 1494 | bitmap_set_pending(bitmap, offset); |
1480 | filemap_get_page(bitmap, offset >> bitmap->chunkshift), | ||
1481 | BITMAP_PAGE_PENDING); | ||
1482 | bitmap->allclean = 0; | 1495 | bitmap->allclean = 0; |
1483 | } | 1496 | } |
1484 | } | 1497 | } |
@@ -1551,11 +1564,9 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n | |||
1551 | return; | 1564 | return; |
1552 | } | 1565 | } |
1553 | if (!*bmc) { | 1566 | if (!*bmc) { |
1554 | struct page *page; | ||
1555 | *bmc = 2 | (needed ? NEEDED_MASK : 0); | 1567 | *bmc = 2 | (needed ? NEEDED_MASK : 0); |
1556 | bitmap_count_page(bitmap, offset, 1); | 1568 | bitmap_count_page(bitmap, offset, 1); |
1557 | page = filemap_get_page(bitmap, offset >> bitmap->chunkshift); | 1569 | bitmap_set_pending(bitmap, offset); |
1558 | set_page_attr(bitmap, page, BITMAP_PAGE_PENDING); | ||
1559 | bitmap->allclean = 0; | 1570 | bitmap->allclean = 0; |
1560 | } | 1571 | } |
1561 | spin_unlock_irq(&bitmap->lock); | 1572 | spin_unlock_irq(&bitmap->lock); |