]> git.proxmox.com Git - mirror_zfs.git/commitdiff
ARC: Remove b_cv from struct l1arc_buf_hdr
authorAlexander Motin <mav@FreeBSD.org>
Wed, 4 Oct 2023 21:45:00 +0000 (17:45 -0400)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Sat, 7 Oct 2023 16:08:20 +0000 (09:08 -0700)
Earlier as part of #14123 I've removed one use of b_cv.  This patch
reuses the same approach to remove the other one from much more
rare code path.

This saves 16 bytes of L1 ARC header on FreeBSD (reducing it from
200 to 184 bytes) and seems even more on Linux.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <mav@FreeBSD.org>
Sponsored by: iXsystems, Inc.
Closes #15340

include/sys/arc_impl.h
module/zfs/arc.c

index 78774792f3676abb29495c8ecf7ee01d73c61d97..da07fd4f8fae419d3e87d7514e02cf3f1852b58a 100644 (file)
@@ -159,8 +159,6 @@ struct arc_write_callback {
  * these two allocation states.
  */
 typedef struct l1arc_buf_hdr {
-       /* for waiting on reads to complete */
-       kcondvar_t              b_cv;
        uint8_t                 b_byteswap;
 
        /* protected by arc state mutex */
index 22dc0ed5e3b6adfde7f5fef1435f42ee409ecf6a..919684a589d873d0c95b1fe0a384f419e5c8ebd8 100644 (file)
@@ -1151,7 +1151,6 @@ hdr_full_cons(void *vbuf, void *unused, int kmflag)
 
        memset(hdr, 0, HDR_FULL_SIZE);
        hdr->b_l1hdr.b_byteswap = DMU_BSWAP_NUMFUNCS;
-       cv_init(&hdr->b_l1hdr.b_cv, NULL, CV_DEFAULT, NULL);
        zfs_refcount_create(&hdr->b_l1hdr.b_refcnt);
 #ifdef ZFS_DEBUG
        mutex_init(&hdr->b_l1hdr.b_freeze_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -1211,7 +1210,6 @@ hdr_full_dest(void *vbuf, void *unused)
        arc_buf_hdr_t *hdr = vbuf;
 
        ASSERT(HDR_EMPTY(hdr));
-       cv_destroy(&hdr->b_l1hdr.b_cv);
        zfs_refcount_destroy(&hdr->b_l1hdr.b_refcnt);
 #ifdef ZFS_DEBUG
        mutex_destroy(&hdr->b_l1hdr.b_freeze_lock);
@@ -5586,13 +5584,6 @@ arc_read_done(zio_t *zio)
                        buf_hash_remove(hdr);
        }
 
-       /*
-        * Broadcast before we drop the hash_lock to avoid the possibility
-        * that the hdr (and hence the cv) might be freed before we get to
-        * the cv_broadcast().
-        */
-       cv_broadcast(&hdr->b_l1hdr.b_cv);
-
        arc_hdr_clear_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
        (void) remove_reference(hdr, hdr);
 
@@ -5787,8 +5778,7 @@ top:
                                }
                                acb->acb_zio_head = head_zio;
                                acb->acb_next = hdr->b_l1hdr.b_acb;
-                               if (hdr->b_l1hdr.b_acb)
-                                       hdr->b_l1hdr.b_acb->acb_prev = acb;
+                               hdr->b_l1hdr.b_acb->acb_prev = acb;
                                hdr->b_l1hdr.b_acb = acb;
                        }
                        mutex_exit(hash_lock);
@@ -5928,8 +5918,28 @@ top:
                                 * and so the performance impact shouldn't
                                 * matter.
                                 */
-                               cv_wait(&hdr->b_l1hdr.b_cv, hash_lock);
+                               arc_callback_t *acb = kmem_zalloc(
+                                   sizeof (arc_callback_t), KM_SLEEP);
+                               acb->acb_wait = B_TRUE;
+                               mutex_init(&acb->acb_wait_lock, NULL,
+                                   MUTEX_DEFAULT, NULL);
+                               cv_init(&acb->acb_wait_cv, NULL, CV_DEFAULT,
+                                   NULL);
+                               acb->acb_zio_head =
+                                   hdr->b_l1hdr.b_acb->acb_zio_head;
+                               acb->acb_next = hdr->b_l1hdr.b_acb;
+                               hdr->b_l1hdr.b_acb->acb_prev = acb;
+                               hdr->b_l1hdr.b_acb = acb;
                                mutex_exit(hash_lock);
+                               mutex_enter(&acb->acb_wait_lock);
+                               while (acb->acb_wait) {
+                                       cv_wait(&acb->acb_wait_cv,
+                                           &acb->acb_wait_lock);
+                               }
+                               mutex_exit(&acb->acb_wait_lock);
+                               mutex_destroy(&acb->acb_wait_lock);
+                               cv_destroy(&acb->acb_wait_cv);
+                               kmem_free(acb, sizeof (arc_callback_t));
                                goto top;
                        }
                }