[dm-devel] [PATCH v2 5/5] dm-bufio: introduce a global cache replacement

Mike Snitzer snitzer at redhat.com
Fri Sep 13 16:00:06 UTC 2019


On Thu, Sep 12 2019 at 12:07P -0400,
Mikulas Patocka <mpatocka at redhat.com> wrote:

> 
> 
> On Thu, 12 Sep 2019, Heinz Mauelshagen wrote:
> 
> > Mikulas,
> > 
> > please use list_move instead of list_del/list_add pairs.
> > 
> > Heinz
> 
> OK. Here I resend it.
> 
> 
> 
> From: Mikulas Patocka <mpatocka at redhat.com>
> 
> This patch introduces a global cache replacement (instead of per-client
> cleanup).
> 
> If one bufio client uses the cache heavily and another client is not using
> it, we want to let the first client use most of the cache. The old
> algorithm would partition the cache equally betwen the clients and that is
> inoptimal.
> 
> For cache replacement, we use the clock algorithm because it doesn't
> require taking any lock when the buffer is accessed.
> 
> Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>

I'd like to fold in this cleanup if you're OK with it.

Rather use a main control structure for the loop rather than gotos.

You OK with this?

diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 8c6edec8a838..2d519c223562 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -230,7 +230,6 @@ static LIST_HEAD(dm_bufio_all_clients);
  */
 static DEFINE_MUTEX(dm_bufio_clients_lock);
 
-
 static struct workqueue_struct *dm_bufio_wq;
 static struct delayed_work dm_bufio_cleanup_old_work;
 static struct work_struct dm_bufio_replacement_work;
@@ -1827,62 +1826,60 @@ static void do_global_cleanup(struct work_struct *w)
 	struct dm_bufio_client *current_client;
 	struct dm_buffer *b;
 	unsigned spinlock_hold_count;
-	unsigned long threshold = dm_bufio_cache_size - dm_bufio_cache_size / DM_BUFIO_LOW_WATERMARK_RATIO;
+	unsigned long threshold = dm_bufio_cache_size -
+		dm_bufio_cache_size / DM_BUFIO_LOW_WATERMARK_RATIO;
 	unsigned long loops = global_num * 2;
 
 	mutex_lock(&dm_bufio_clients_lock);
 
-reacquire_spinlock:
-	cond_resched();
+	while (1) {
+		cond_resched();
 
-	spin_lock(&global_spinlock);
-	if (unlikely(dm_bufio_current_allocated <= threshold))
-		goto exit;
+		spin_lock(&global_spinlock);
+		if (unlikely(dm_bufio_current_allocated <= threshold))
+			break;
 
-	spinlock_hold_count = 0;
+		spinlock_hold_count = 0;
 get_next:
-	if (!loops--)
-		goto exit;
-	if (unlikely(list_empty(&global_queue)))
-		goto exit;
-	b = list_entry(global_queue.prev, struct dm_buffer, global_list);
-
-	if (b->accessed) {
-		b->accessed = 0;
-		list_move(&b->global_list, &global_queue);
-		if (likely(++spinlock_hold_count < 16)) {
-			goto get_next;
-		}
-		spin_unlock(&global_spinlock);
-		goto reacquire_spinlock;
-	}
-
-	current_client = b->c;
-	if (unlikely(current_client != locked_client)) {
-		if (locked_client)
-			dm_bufio_unlock(locked_client);
+		if (!loops--)
+			break;
+		if (unlikely(list_empty(&global_queue)))
+			break;
+		b = list_entry(global_queue.prev, struct dm_buffer, global_list);
 
-		if (!dm_bufio_trylock(current_client)) {
+		if (b->accessed) {
+			b->accessed = 0;
+			list_move(&b->global_list, &global_queue);
+			if (likely(++spinlock_hold_count < 16))
+				goto get_next;
 			spin_unlock(&global_spinlock);
-			dm_bufio_lock(current_client);
-			locked_client = current_client;
-			goto reacquire_spinlock;
+			continue;
 		}
 
-		locked_client = current_client;
-	}
+		current_client = b->c;
+		if (unlikely(current_client != locked_client)) {
+			if (locked_client)
+				dm_bufio_unlock(locked_client);
 
-	spin_unlock(&global_spinlock);
+			if (!dm_bufio_trylock(current_client)) {
+				spin_unlock(&global_spinlock);
+				dm_bufio_lock(current_client);
+				locked_client = current_client;
+				continue;
+			}
+
+			locked_client = current_client;
+		}
 
-	if (unlikely(!__try_evict_buffer(b, GFP_KERNEL))) {
-		spin_lock(&global_spinlock);
-		list_move(&b->global_list, &global_queue);
 		spin_unlock(&global_spinlock);
-	}
 
-	goto reacquire_spinlock;
+		if (unlikely(!__try_evict_buffer(b, GFP_KERNEL))) {
+			spin_lock(&global_spinlock);
+			list_move(&b->global_list, &global_queue);
+			spin_unlock(&global_spinlock);
+		}
+	}
 
-exit:
 	spin_unlock(&global_spinlock);
 
 	if (locked_client)




More information about the dm-devel mailing list