ARC: Remove b_cv from struct l1arc_buf_hdr

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
This commit is contained in:
Alexander Motin 2023-10-04 17:45:00 -04:00 committed by Brian Behlendorf
parent 1611b8e56e
commit bc77a0c85e
2 changed files with 22 additions and 14 deletions

View File

@ -159,8 +159,6 @@ struct arc_write_callback {
* these two allocation states. * these two allocation states.
*/ */
typedef struct l1arc_buf_hdr { typedef struct l1arc_buf_hdr {
/* for waiting on reads to complete */
kcondvar_t b_cv;
uint8_t b_byteswap; uint8_t b_byteswap;
/* protected by arc state mutex */ /* protected by arc state mutex */

View File

@ -1151,7 +1151,6 @@ hdr_full_cons(void *vbuf, void *unused, int kmflag)
memset(hdr, 0, HDR_FULL_SIZE); memset(hdr, 0, HDR_FULL_SIZE);
hdr->b_l1hdr.b_byteswap = DMU_BSWAP_NUMFUNCS; 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); zfs_refcount_create(&hdr->b_l1hdr.b_refcnt);
#ifdef ZFS_DEBUG #ifdef ZFS_DEBUG
mutex_init(&hdr->b_l1hdr.b_freeze_lock, NULL, MUTEX_DEFAULT, NULL); 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; arc_buf_hdr_t *hdr = vbuf;
ASSERT(HDR_EMPTY(hdr)); ASSERT(HDR_EMPTY(hdr));
cv_destroy(&hdr->b_l1hdr.b_cv);
zfs_refcount_destroy(&hdr->b_l1hdr.b_refcnt); zfs_refcount_destroy(&hdr->b_l1hdr.b_refcnt);
#ifdef ZFS_DEBUG #ifdef ZFS_DEBUG
mutex_destroy(&hdr->b_l1hdr.b_freeze_lock); mutex_destroy(&hdr->b_l1hdr.b_freeze_lock);
@ -5586,13 +5584,6 @@ arc_read_done(zio_t *zio)
buf_hash_remove(hdr); 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); arc_hdr_clear_flags(hdr, ARC_FLAG_IO_IN_PROGRESS);
(void) remove_reference(hdr, hdr); (void) remove_reference(hdr, hdr);
@ -5787,8 +5778,7 @@ top:
} }
acb->acb_zio_head = head_zio; acb->acb_zio_head = head_zio;
acb->acb_next = hdr->b_l1hdr.b_acb; 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; hdr->b_l1hdr.b_acb = acb;
} }
mutex_exit(hash_lock); mutex_exit(hash_lock);
@ -5928,8 +5918,28 @@ top:
* and so the performance impact shouldn't * and so the performance impact shouldn't
* matter. * 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_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; goto top;
} }
} }