aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bitmap.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-09-21 01:37:46 -0400
committerNeilBrown <neilb@suse.de>2011-09-21 01:37:46 -0400
commit2585f3ef8c7fffe750ef1feb2775023716d799a8 (patch)
tree3faccf1f22eb01bea55f49926a913446134df1d2 /drivers/md/bitmap.c
parent5a537df44d52331a3d2792ca21a296959bd2ac3a (diff)
md/bitmap: improve handling of 'allclean'.
The 'allclean' flag is used to cache the fact that there is nothing to do, so we can avoid waking up and scanning the bitmap regularly. The two sorts of pages that might need the attention of the bitmap daemon are BITMAP_PAGE_PENDING and BITMAP_PAGE_NEEDWRITE pages. So make sure allclean reflects exactly when there are none of those. So: set it before scanning all pages with either bit set. clear it whenever these bits are set clear it when we desire not to clear one of these bits. don't clear it any other time. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r--drivers/md/bitmap.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 69a6f256ce35..689623c3cffa 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1146,6 +1146,7 @@ void bitmap_write_all(struct bitmap *bitmap)
1146 for (i = 0; i < bitmap->file_pages; i++) 1146 for (i = 0; i < bitmap->file_pages; i++)
1147 set_page_attr(bitmap, bitmap->filemap[i], 1147 set_page_attr(bitmap, bitmap->filemap[i],
1148 BITMAP_PAGE_NEEDWRITE); 1148 BITMAP_PAGE_NEEDWRITE);
1149 bitmap->allclean = 0;
1149} 1150}
1150 1151
1151static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc) 1152static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
@@ -1211,10 +1212,8 @@ void bitmap_daemon_work(mddev_t *mddev)
1211 clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); 1212 clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
1212 1213
1213 spin_unlock_irqrestore(&bitmap->lock, flags); 1214 spin_unlock_irqrestore(&bitmap->lock, flags);
1214 if (need_write) { 1215 if (need_write)
1215 write_page(bitmap, page, 0); 1216 write_page(bitmap, page, 0);
1216 bitmap->allclean = 0;
1217 }
1218 spin_lock_irqsave(&bitmap->lock, flags); 1217 spin_lock_irqsave(&bitmap->lock, flags);
1219 j |= (PAGE_BITS - 1); 1218 j |= (PAGE_BITS - 1);
1220 continue; 1219 continue;
@@ -1222,12 +1221,16 @@ void bitmap_daemon_work(mddev_t *mddev)
1222 1221
1223 /* grab the new page, sync and release the old */ 1222 /* grab the new page, sync and release the old */
1224 if (lastpage != NULL) { 1223 if (lastpage != NULL) {
1225 if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) { 1224 if (test_page_attr(bitmap, lastpage,
1226 clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); 1225 BITMAP_PAGE_NEEDWRITE)) {
1226 clear_page_attr(bitmap, lastpage,
1227 BITMAP_PAGE_NEEDWRITE);
1227 spin_unlock_irqrestore(&bitmap->lock, flags); 1228 spin_unlock_irqrestore(&bitmap->lock, flags);
1228 write_page(bitmap, lastpage, 0); 1229 write_page(bitmap, lastpage, 0);
1229 } else { 1230 } else {
1230 set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); 1231 set_page_attr(bitmap, lastpage,
1232 BITMAP_PAGE_NEEDWRITE);
1233 bitmap->allclean = 0;
1231 spin_unlock_irqrestore(&bitmap->lock, flags); 1234 spin_unlock_irqrestore(&bitmap->lock, flags);
1232 } 1235 }
1233 } else 1236 } else
@@ -1250,6 +1253,8 @@ void bitmap_daemon_work(mddev_t *mddev)
1250 spin_lock_irqsave(&bitmap->lock, flags); 1253 spin_lock_irqsave(&bitmap->lock, flags);
1251 if (!bitmap->need_sync) 1254 if (!bitmap->need_sync)
1252 clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING); 1255 clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
1256 else
1257 bitmap->allclean = 0;
1253 } 1258 }
1254 bmc = bitmap_get_counter(bitmap, 1259 bmc = bitmap_get_counter(bitmap,
1255 (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap), 1260 (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
@@ -1257,8 +1262,6 @@ void bitmap_daemon_work(mddev_t *mddev)
1257 if (!bmc) 1262 if (!bmc)
1258 j |= PAGE_COUNTER_MASK; 1263 j |= PAGE_COUNTER_MASK;
1259 else if (*bmc) { 1264 else if (*bmc) {
1260 bitmap->allclean = 0;
1261
1262 if (*bmc == 1 && !bitmap->need_sync) { 1265 if (*bmc == 1 && !bitmap->need_sync) {
1263 /* we can clear the bit */ 1266 /* we can clear the bit */
1264 *bmc = 0; 1267 *bmc = 0;
@@ -1280,6 +1283,7 @@ void bitmap_daemon_work(mddev_t *mddev)
1280 } else if (*bmc <= 2) { 1283 } else if (*bmc <= 2) {
1281 *bmc = 1; /* maybe clear the bit next time */ 1284 *bmc = 1; /* maybe clear the bit next time */
1282 set_page_attr(bitmap, page, BITMAP_PAGE_PENDING); 1285 set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
1286 bitmap->allclean = 0;
1283 } 1287 }
1284 } 1288 }
1285 } 1289 }
@@ -1294,6 +1298,7 @@ void bitmap_daemon_work(mddev_t *mddev)
1294 write_page(bitmap, lastpage, 0); 1298 write_page(bitmap, lastpage, 0);
1295 } else { 1299 } else {
1296 set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); 1300 set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
1301 bitmap->allclean = 0;
1297 spin_unlock_irqrestore(&bitmap->lock, flags); 1302 spin_unlock_irqrestore(&bitmap->lock, flags);
1298 } 1303 }
1299 } 1304 }
@@ -1407,7 +1412,6 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
1407 else 1412 else
1408 sectors = 0; 1413 sectors = 0;
1409 } 1414 }
1410 bitmap->allclean = 0;
1411 return 0; 1415 return 0;
1412} 1416}
1413EXPORT_SYMBOL(bitmap_startwrite); 1417EXPORT_SYMBOL(bitmap_startwrite);
@@ -1453,13 +1457,14 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
1453 wake_up(&bitmap->overflow_wait); 1457 wake_up(&bitmap->overflow_wait);
1454 1458
1455 (*bmc)--; 1459 (*bmc)--;
1456 if (*bmc <= 2) 1460 if (*bmc <= 2) {
1457 set_page_attr(bitmap, 1461 set_page_attr(bitmap,
1458 filemap_get_page( 1462 filemap_get_page(
1459 bitmap, 1463 bitmap,
1460 offset >> CHUNK_BLOCK_SHIFT(bitmap)), 1464 offset >> CHUNK_BLOCK_SHIFT(bitmap)),
1461 BITMAP_PAGE_PENDING); 1465 BITMAP_PAGE_PENDING);
1462 1466 bitmap->allclean = 0;
1467 }
1463 spin_unlock_irqrestore(&bitmap->lock, flags); 1468 spin_unlock_irqrestore(&bitmap->lock, flags);
1464 offset += blocks; 1469 offset += blocks;
1465 if (sectors > blocks) 1470 if (sectors > blocks)
@@ -1495,7 +1500,6 @@ static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t
1495 } 1500 }
1496 } 1501 }
1497 spin_unlock_irq(&bitmap->lock); 1502 spin_unlock_irq(&bitmap->lock);
1498 bitmap->allclean = 0;
1499 return rv; 1503 return rv;
1500} 1504}
1501 1505
@@ -1543,15 +1547,16 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
1543 if (!NEEDED(*bmc) && aborted) 1547 if (!NEEDED(*bmc) && aborted)
1544 *bmc |= NEEDED_MASK; 1548 *bmc |= NEEDED_MASK;
1545 else { 1549 else {
1546 if (*bmc <= 2) 1550 if (*bmc <= 2) {
1547 set_page_attr(bitmap, 1551 set_page_attr(bitmap,
1548 filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)), 1552 filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
1549 BITMAP_PAGE_PENDING); 1553 BITMAP_PAGE_PENDING);
1554 bitmap->allclean = 0;
1555 }
1550 } 1556 }
1551 } 1557 }
1552 unlock: 1558 unlock:
1553 spin_unlock_irqrestore(&bitmap->lock, flags); 1559 spin_unlock_irqrestore(&bitmap->lock, flags);
1554 bitmap->allclean = 0;
1555} 1560}
1556EXPORT_SYMBOL(bitmap_end_sync); 1561EXPORT_SYMBOL(bitmap_end_sync);
1557 1562
@@ -1623,9 +1628,9 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
1623 bitmap_count_page(bitmap, offset, 1); 1628 bitmap_count_page(bitmap, offset, 1);
1624 page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); 1629 page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
1625 set_page_attr(bitmap, page, BITMAP_PAGE_PENDING); 1630 set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
1631 bitmap->allclean = 0;
1626 } 1632 }
1627 spin_unlock_irq(&bitmap->lock); 1633 spin_unlock_irq(&bitmap->lock);
1628 bitmap->allclean = 0;
1629} 1634}
1630 1635
1631/* dirty the memory and file bits for bitmap chunks "s" to "e" */ 1636/* dirty the memory and file bits for bitmap chunks "s" to "e" */