]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bcachefs: Improve bch2_extent_ptr_set_cached()
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 4 May 2025 19:02:53 +0000 (15:02 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 22 May 2025 00:14:47 +0000 (20:14 -0400)
Preferentially keep existing cached pointers instead of adding new ones.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/extents.c

index c4fe4ffd41f1d16036373f8d9e3bc458b6d72335..d3af841e48ef034e922f46dbf6daf0def9640916 100644 (file)
@@ -1136,33 +1136,50 @@ void bch2_extent_ptr_set_cached(struct bch_fs *c,
                                struct bkey_s k,
                                struct bch_extent_ptr *ptr)
 {
-       struct bkey_ptrs ptrs = bch2_bkey_ptrs(k);
+       struct bkey_ptrs ptrs;
        union bch_extent_entry *entry;
        struct extent_ptr_decoded p;
+       bool have_cached_ptr;
+       unsigned drop_dev = ptr->dev;
 
        rcu_read_lock();
-       if (!want_cached_ptr(c, opts, ptr)) {
-               bch2_bkey_drop_ptr_noerror(k, ptr);
-               goto out;
-       }
+restart_drop_ptrs:
+       ptrs = bch2_bkey_ptrs(k);
+       have_cached_ptr = false;
 
-       /*
-        * Stripes can't contain cached data, for - reasons.
-        *
-        * Possibly something we can fix in the future?
-        */
-       bkey_for_each_ptr_decode(k.k, ptrs, p, entry)
-               if (&entry->ptr == ptr) {
-                       if (p.has_ec)
-                               bch2_bkey_drop_ptr_noerror(k, ptr);
-                       else
-                               ptr->cached = true;
-                       goto out;
+       bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
+               /*
+                * Check if it's erasure coded - stripes can't contain cached
+                * data. Possibly something we can fix in the future?
+                */
+               if (&entry->ptr == ptr && p.has_ec)
+                       goto drop;
+
+               if (p.ptr.cached) {
+                       if (have_cached_ptr || !want_cached_ptr(c, opts, &p.ptr)) {
+                               bch2_bkey_drop_ptr_noerror(k, &entry->ptr);
+                               ptr = NULL;
+                               goto restart_drop_ptrs;
+                       }
+
+                       have_cached_ptr = true;
                }
+       }
+
+       if (!ptr)
+               bkey_for_each_ptr(ptrs, ptr2)
+                       if (ptr2->dev == drop_dev)
+                               ptr = ptr2;
 
-       BUG();
-out:
+       if (have_cached_ptr || !want_cached_ptr(c, opts, ptr))
+               goto drop;
+
+       ptr->cached = true;
+       rcu_read_unlock();
+       return;
+drop:
        rcu_read_unlock();
+       bch2_bkey_drop_ptr_noerror(k, ptr);
 }
 
 /*