ufs: Avoid M_WAITOK allocations when building a dirhash

At this point the directory's vnode lock is held, so blocking while
waiting for free pages makes the system more susceptible to deadlock in
low memory conditions.  This is particularly problematic on NUMA systems
as UMA currently implements a strict first-touch policy.

ufsdirhash_build() already uses M_NOWAIT for other allocations and
already handled failures for the block array allocation, so just convert
to M_NOWAIT.

PR:		253992
Reviewed by:	markj, mckusick, vangyzen

(cherry picked from commit f17a590085)
This commit is contained in:
Don Morris 2021-05-20 10:54:38 -04:00 committed by Mark Johnston
parent 7fd88ba72e
commit 640c2ff8ae

View file

@ -108,7 +108,7 @@ static uma_zone_t ufsdirhash_zone;
#define DIRHASHLIST_LOCK() mtx_lock(&ufsdirhash_mtx)
#define DIRHASHLIST_UNLOCK() mtx_unlock(&ufsdirhash_mtx)
#define DIRHASH_BLKALLOC_WAITOK() uma_zalloc(ufsdirhash_zone, M_WAITOK)
#define DIRHASH_BLKALLOC() uma_zalloc(ufsdirhash_zone, M_NOWAIT)
#define DIRHASH_BLKFREE(ptr) uma_zfree(ufsdirhash_zone, (ptr))
#define DIRHASH_ASSERT_LOCKED(dh) \
sx_assert(&(dh)->dh_lock, SA_LOCKED)
@ -425,7 +425,7 @@ ufsdirhash_build(struct inode *ip)
if (dh->dh_blkfree == NULL)
goto fail;
for (i = 0; i < narrays; i++) {
if ((dh->dh_hash[i] = DIRHASH_BLKALLOC_WAITOK()) == NULL)
if ((dh->dh_hash[i] = DIRHASH_BLKALLOC()) == NULL)
goto fail;
for (j = 0; j < DH_NBLKOFF; j++)
dh->dh_hash[i][j] = DIRHASH_EMPTY;