diff options
Diffstat (limited to 'drivers/md/dm-bufio.c')
-rw-r--r-- | drivers/md/dm-bufio.c | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 5227e079a6e3..173cbb20d104 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c | |||
@@ -1425,62 +1425,75 @@ static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp, | |||
1425 | unsigned long max_jiffies) | 1425 | unsigned long max_jiffies) |
1426 | { | 1426 | { |
1427 | if (jiffies - b->last_accessed < max_jiffies) | 1427 | if (jiffies - b->last_accessed < max_jiffies) |
1428 | return 1; | 1428 | return 0; |
1429 | 1429 | ||
1430 | if (!(gfp & __GFP_IO)) { | 1430 | if (!(gfp & __GFP_IO)) { |
1431 | if (test_bit(B_READING, &b->state) || | 1431 | if (test_bit(B_READING, &b->state) || |
1432 | test_bit(B_WRITING, &b->state) || | 1432 | test_bit(B_WRITING, &b->state) || |
1433 | test_bit(B_DIRTY, &b->state)) | 1433 | test_bit(B_DIRTY, &b->state)) |
1434 | return 1; | 1434 | return 0; |
1435 | } | 1435 | } |
1436 | 1436 | ||
1437 | if (b->hold_count) | 1437 | if (b->hold_count) |
1438 | return 1; | 1438 | return 0; |
1439 | 1439 | ||
1440 | __make_buffer_clean(b); | 1440 | __make_buffer_clean(b); |
1441 | __unlink_buffer(b); | 1441 | __unlink_buffer(b); |
1442 | __free_buffer_wake(b); | 1442 | __free_buffer_wake(b); |
1443 | 1443 | ||
1444 | return 0; | 1444 | return 1; |
1445 | } | 1445 | } |
1446 | 1446 | ||
1447 | static void __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, | 1447 | static long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, |
1448 | struct shrink_control *sc) | 1448 | gfp_t gfp_mask) |
1449 | { | 1449 | { |
1450 | int l; | 1450 | int l; |
1451 | struct dm_buffer *b, *tmp; | 1451 | struct dm_buffer *b, *tmp; |
1452 | long freed = 0; | ||
1452 | 1453 | ||
1453 | for (l = 0; l < LIST_SIZE; l++) { | 1454 | for (l = 0; l < LIST_SIZE; l++) { |
1454 | list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) | 1455 | list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) { |
1455 | if (!__cleanup_old_buffer(b, sc->gfp_mask, 0) && | 1456 | freed += __cleanup_old_buffer(b, gfp_mask, 0); |
1456 | !--nr_to_scan) | 1457 | if (!--nr_to_scan) |
1457 | return; | 1458 | break; |
1459 | } | ||
1458 | dm_bufio_cond_resched(); | 1460 | dm_bufio_cond_resched(); |
1459 | } | 1461 | } |
1462 | return freed; | ||
1460 | } | 1463 | } |
1461 | 1464 | ||
1462 | static int shrink(struct shrinker *shrinker, struct shrink_control *sc) | 1465 | static unsigned long |
1466 | dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) | ||
1463 | { | 1467 | { |
1464 | struct dm_bufio_client *c = | 1468 | struct dm_bufio_client *c; |
1465 | container_of(shrinker, struct dm_bufio_client, shrinker); | 1469 | unsigned long freed; |
1466 | unsigned long r; | ||
1467 | unsigned long nr_to_scan = sc->nr_to_scan; | ||
1468 | 1470 | ||
1471 | c = container_of(shrink, struct dm_bufio_client, shrinker); | ||
1469 | if (sc->gfp_mask & __GFP_IO) | 1472 | if (sc->gfp_mask & __GFP_IO) |
1470 | dm_bufio_lock(c); | 1473 | dm_bufio_lock(c); |
1471 | else if (!dm_bufio_trylock(c)) | 1474 | else if (!dm_bufio_trylock(c)) |
1472 | return !nr_to_scan ? 0 : -1; | 1475 | return SHRINK_STOP; |
1473 | 1476 | ||
1474 | if (nr_to_scan) | 1477 | freed = __scan(c, sc->nr_to_scan, sc->gfp_mask); |
1475 | __scan(c, nr_to_scan, sc); | 1478 | dm_bufio_unlock(c); |
1479 | return freed; | ||
1480 | } | ||
1476 | 1481 | ||
1477 | r = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY]; | 1482 | static unsigned long |
1478 | if (r > INT_MAX) | 1483 | dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc) |
1479 | r = INT_MAX; | 1484 | { |
1485 | struct dm_bufio_client *c; | ||
1486 | unsigned long count; | ||
1480 | 1487 | ||
1481 | dm_bufio_unlock(c); | 1488 | c = container_of(shrink, struct dm_bufio_client, shrinker); |
1489 | if (sc->gfp_mask & __GFP_IO) | ||
1490 | dm_bufio_lock(c); | ||
1491 | else if (!dm_bufio_trylock(c)) | ||
1492 | return 0; | ||
1482 | 1493 | ||
1483 | return r; | 1494 | count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY]; |
1495 | dm_bufio_unlock(c); | ||
1496 | return count; | ||
1484 | } | 1497 | } |
1485 | 1498 | ||
1486 | /* | 1499 | /* |
@@ -1582,7 +1595,8 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign | |||
1582 | __cache_size_refresh(); | 1595 | __cache_size_refresh(); |
1583 | mutex_unlock(&dm_bufio_clients_lock); | 1596 | mutex_unlock(&dm_bufio_clients_lock); |
1584 | 1597 | ||
1585 | c->shrinker.shrink = shrink; | 1598 | c->shrinker.count_objects = dm_bufio_shrink_count; |
1599 | c->shrinker.scan_objects = dm_bufio_shrink_scan; | ||
1586 | c->shrinker.seeks = 1; | 1600 | c->shrinker.seeks = 1; |
1587 | c->shrinker.batch = 0; | 1601 | c->shrinker.batch = 0; |
1588 | register_shrinker(&c->shrinker); | 1602 | register_shrinker(&c->shrinker); |
@@ -1669,7 +1683,7 @@ static void cleanup_old_buffers(void) | |||
1669 | struct dm_buffer *b; | 1683 | struct dm_buffer *b; |
1670 | b = list_entry(c->lru[LIST_CLEAN].prev, | 1684 | b = list_entry(c->lru[LIST_CLEAN].prev, |
1671 | struct dm_buffer, lru_list); | 1685 | struct dm_buffer, lru_list); |
1672 | if (__cleanup_old_buffer(b, 0, max_age * HZ)) | 1686 | if (!__cleanup_old_buffer(b, 0, max_age * HZ)) |
1673 | break; | 1687 | break; |
1674 | dm_bufio_cond_resched(); | 1688 | dm_bufio_cond_resched(); |
1675 | } | 1689 | } |