4.9-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Mikulas Patocka <mpato...@redhat.com>

commit 390020ad2af9ca04844c4f3b1f299ad8746d84c8 upstream.

dm-bufio checks a watermark when it allocates a new buffer in
__bufio_new().  However, it doesn't check the watermark when the user
changes /sys/module/dm_bufio/parameters/max_cache_size_bytes.

This may result in a problem - if the watermark is high enough so that
all possible buffers are allocated and if the user lowers the value of
"max_cache_size_bytes", the watermark will never be checked against the
new value because no new buffer would be allocated.

To fix this, change __evict_old_buffers() so that it checks the
watermark.  __evict_old_buffers() is called every 30 seconds, so if the
user reduces "max_cache_size_bytes", dm-bufio will react to this change
within 30 seconds and decrease memory consumption.

Depends-on: 1b0fb5a5b2 ("dm bufio: avoid a possible ABBA deadlock")
Signed-off-by: Mikulas Patocka <mpato...@redhat.com>
Signed-off-by: Mike Snitzer <snit...@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 drivers/md/dm-bufio.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1782,9 +1782,17 @@ static void __evict_old_buffers(struct d
        struct dm_buffer *b, *tmp;
        unsigned retain_target = get_retain_buffers(c);
        unsigned count;
+       LIST_HEAD(write_list);
 
        dm_bufio_lock(c);
 
+       __check_watermark(c, &write_list);
+       if (unlikely(!list_empty(&write_list))) {
+               dm_bufio_unlock(c);
+               __flush_write_list(&write_list);
+               dm_bufio_lock(c);
+       }
+
        count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
        list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_CLEAN], lru_list) 
{
                if (count <= retain_target)
@@ -1809,6 +1817,8 @@ static void cleanup_old_buffers(void)
 
        mutex_lock(&dm_bufio_clients_lock);
 
+       __cache_size_refresh();
+
        list_for_each_entry(c, &dm_bufio_all_clients, client_list)
                __evict_old_buffers(c, max_age_hz);
 


Reply via email to