diff options
Diffstat (limited to 'drivers/block/drbd/drbd_bitmap.c')
-rw-r--r-- | drivers/block/drbd/drbd_bitmap.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index f440a02dfdb1..1e89a74ddb17 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c | |||
@@ -112,9 +112,6 @@ struct drbd_bitmap { | |||
112 | struct task_struct *bm_task; | 112 | struct task_struct *bm_task; |
113 | }; | 113 | }; |
114 | 114 | ||
115 | static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, | ||
116 | unsigned long e, int val, const enum km_type km); | ||
117 | |||
118 | #define bm_print_lock_info(m) __bm_print_lock_info(m, __func__) | 115 | #define bm_print_lock_info(m) __bm_print_lock_info(m, __func__) |
119 | static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func) | 116 | static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func) |
120 | { | 117 | { |
@@ -1256,7 +1253,7 @@ unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_f | |||
1256 | * expected to be called for only a few bits (e - s about BITS_PER_LONG). | 1253 | * expected to be called for only a few bits (e - s about BITS_PER_LONG). |
1257 | * Must hold bitmap lock already. */ | 1254 | * Must hold bitmap lock already. */ |
1258 | static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, | 1255 | static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, |
1259 | unsigned long e, int val, const enum km_type km) | 1256 | unsigned long e, int val) |
1260 | { | 1257 | { |
1261 | struct drbd_bitmap *b = mdev->bitmap; | 1258 | struct drbd_bitmap *b = mdev->bitmap; |
1262 | unsigned long *p_addr = NULL; | 1259 | unsigned long *p_addr = NULL; |
@@ -1274,14 +1271,14 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, | |||
1274 | unsigned int page_nr = bm_bit_to_page_idx(b, bitnr); | 1271 | unsigned int page_nr = bm_bit_to_page_idx(b, bitnr); |
1275 | if (page_nr != last_page_nr) { | 1272 | if (page_nr != last_page_nr) { |
1276 | if (p_addr) | 1273 | if (p_addr) |
1277 | __bm_unmap(p_addr, km); | 1274 | __bm_unmap(p_addr, KM_IRQ1); |
1278 | if (c < 0) | 1275 | if (c < 0) |
1279 | bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]); | 1276 | bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]); |
1280 | else if (c > 0) | 1277 | else if (c > 0) |
1281 | bm_set_page_need_writeout(b->bm_pages[last_page_nr]); | 1278 | bm_set_page_need_writeout(b->bm_pages[last_page_nr]); |
1282 | changed_total += c; | 1279 | changed_total += c; |
1283 | c = 0; | 1280 | c = 0; |
1284 | p_addr = __bm_map_pidx(b, page_nr, km); | 1281 | p_addr = __bm_map_pidx(b, page_nr, KM_IRQ1); |
1285 | last_page_nr = page_nr; | 1282 | last_page_nr = page_nr; |
1286 | } | 1283 | } |
1287 | if (val) | 1284 | if (val) |
@@ -1290,7 +1287,7 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, | |||
1290 | c -= (0 != __test_and_clear_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr)); | 1287 | c -= (0 != __test_and_clear_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr)); |
1291 | } | 1288 | } |
1292 | if (p_addr) | 1289 | if (p_addr) |
1293 | __bm_unmap(p_addr, km); | 1290 | __bm_unmap(p_addr, KM_IRQ1); |
1294 | if (c < 0) | 1291 | if (c < 0) |
1295 | bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]); | 1292 | bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]); |
1296 | else if (c > 0) | 1293 | else if (c > 0) |
@@ -1318,7 +1315,7 @@ static int bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s, | |||
1318 | if ((val ? BM_DONT_SET : BM_DONT_CLEAR) & b->bm_flags) | 1315 | if ((val ? BM_DONT_SET : BM_DONT_CLEAR) & b->bm_flags) |
1319 | bm_print_lock_info(mdev); | 1316 | bm_print_lock_info(mdev); |
1320 | 1317 | ||
1321 | c = __bm_change_bits_to(mdev, s, e, val, KM_IRQ1); | 1318 | c = __bm_change_bits_to(mdev, s, e, val); |
1322 | 1319 | ||
1323 | spin_unlock_irqrestore(&b->bm_lock, flags); | 1320 | spin_unlock_irqrestore(&b->bm_lock, flags); |
1324 | return c; | 1321 | return c; |
@@ -1343,16 +1340,17 @@ static inline void bm_set_full_words_within_one_page(struct drbd_bitmap *b, | |||
1343 | { | 1340 | { |
1344 | int i; | 1341 | int i; |
1345 | int bits; | 1342 | int bits; |
1346 | unsigned long *paddr = kmap_atomic(b->bm_pages[page_nr], KM_USER0); | 1343 | unsigned long *paddr = kmap_atomic(b->bm_pages[page_nr], KM_IRQ1); |
1347 | for (i = first_word; i < last_word; i++) { | 1344 | for (i = first_word; i < last_word; i++) { |
1348 | bits = hweight_long(paddr[i]); | 1345 | bits = hweight_long(paddr[i]); |
1349 | paddr[i] = ~0UL; | 1346 | paddr[i] = ~0UL; |
1350 | b->bm_set += BITS_PER_LONG - bits; | 1347 | b->bm_set += BITS_PER_LONG - bits; |
1351 | } | 1348 | } |
1352 | kunmap_atomic(paddr, KM_USER0); | 1349 | kunmap_atomic(paddr, KM_IRQ1); |
1353 | } | 1350 | } |
1354 | 1351 | ||
1355 | /* Same thing as drbd_bm_set_bits, but without taking the spin_lock_irqsave. | 1352 | /* Same thing as drbd_bm_set_bits, |
1353 | * but more efficient for a large bit range. | ||
1356 | * You must first drbd_bm_lock(). | 1354 | * You must first drbd_bm_lock(). |
1357 | * Can be called to set the whole bitmap in one go. | 1355 | * Can be called to set the whole bitmap in one go. |
1358 | * Sets bits from s to e _inclusive_. */ | 1356 | * Sets bits from s to e _inclusive_. */ |
@@ -1366,6 +1364,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi | |||
1366 | * Do not use memset, because we must account for changes, | 1364 | * Do not use memset, because we must account for changes, |
1367 | * so we need to loop over the words with hweight() anyways. | 1365 | * so we need to loop over the words with hweight() anyways. |
1368 | */ | 1366 | */ |
1367 | struct drbd_bitmap *b = mdev->bitmap; | ||
1369 | unsigned long sl = ALIGN(s,BITS_PER_LONG); | 1368 | unsigned long sl = ALIGN(s,BITS_PER_LONG); |
1370 | unsigned long el = (e+1) & ~((unsigned long)BITS_PER_LONG-1); | 1369 | unsigned long el = (e+1) & ~((unsigned long)BITS_PER_LONG-1); |
1371 | int first_page; | 1370 | int first_page; |
@@ -1376,15 +1375,19 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi | |||
1376 | 1375 | ||
1377 | if (e - s <= 3*BITS_PER_LONG) { | 1376 | if (e - s <= 3*BITS_PER_LONG) { |
1378 | /* don't bother; el and sl may even be wrong. */ | 1377 | /* don't bother; el and sl may even be wrong. */ |
1379 | __bm_change_bits_to(mdev, s, e, 1, KM_USER0); | 1378 | spin_lock_irq(&b->bm_lock); |
1379 | __bm_change_bits_to(mdev, s, e, 1); | ||
1380 | spin_unlock_irq(&b->bm_lock); | ||
1380 | return; | 1381 | return; |
1381 | } | 1382 | } |
1382 | 1383 | ||
1383 | /* difference is large enough that we can trust sl and el */ | 1384 | /* difference is large enough that we can trust sl and el */ |
1384 | 1385 | ||
1386 | spin_lock_irq(&b->bm_lock); | ||
1387 | |||
1385 | /* bits filling the current long */ | 1388 | /* bits filling the current long */ |
1386 | if (sl) | 1389 | if (sl) |
1387 | __bm_change_bits_to(mdev, s, sl-1, 1, KM_USER0); | 1390 | __bm_change_bits_to(mdev, s, sl-1, 1); |
1388 | 1391 | ||
1389 | first_page = sl >> (3 + PAGE_SHIFT); | 1392 | first_page = sl >> (3 + PAGE_SHIFT); |
1390 | last_page = el >> (3 + PAGE_SHIFT); | 1393 | last_page = el >> (3 + PAGE_SHIFT); |
@@ -1397,7 +1400,7 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi | |||
1397 | /* first and full pages, unless first page == last page */ | 1400 | /* first and full pages, unless first page == last page */ |
1398 | for (page_nr = first_page; page_nr < last_page; page_nr++) { | 1401 | for (page_nr = first_page; page_nr < last_page; page_nr++) { |
1399 | bm_set_full_words_within_one_page(mdev->bitmap, page_nr, first_word, last_word); | 1402 | bm_set_full_words_within_one_page(mdev->bitmap, page_nr, first_word, last_word); |
1400 | cond_resched(); | 1403 | cond_resched_lock(&b->bm_lock); |
1401 | first_word = 0; | 1404 | first_word = 0; |
1402 | } | 1405 | } |
1403 | 1406 | ||
@@ -1411,7 +1414,8 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi | |||
1411 | * it would trigger an assert in __bm_change_bits_to() | 1414 | * it would trigger an assert in __bm_change_bits_to() |
1412 | */ | 1415 | */ |
1413 | if (el <= e) | 1416 | if (el <= e) |
1414 | __bm_change_bits_to(mdev, el, e, 1, KM_USER0); | 1417 | __bm_change_bits_to(mdev, el, e, 1); |
1418 | spin_unlock_irq(&b->bm_lock); | ||
1415 | } | 1419 | } |
1416 | 1420 | ||
1417 | /* returns bit state | 1421 | /* returns bit state |