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
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D29045
This commit is contained in:
Don Morris 2021-05-20 10:54:38 -04:00 committed by Mark Johnston
parent 9938fcaa65
commit f17a590085

View File

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