patch: portable dirhash

Ted Unangst tedu at zeitbombe.org
Tue Dec 16 19:12:14 PST 2003


can somebody please review/commit this to freebsd?  it is most of the 
differences to permit openbsd to use the code.  it should not change the 
code in any functional way.


Index: ufs_dirhash.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_dirhash.c,v
retrieving revision 1.17
diff -u -r1.17 ufs_dirhash.c
--- ufs_dirhash.c	11 Jun 2003 06:34:30 -0000	1.17
+++ ufs_dirhash.c	17 Dec 2003 03:04:58 -0000
@@ -89,13 +89,28 @@
 static doff_t ufsdirhash_getprev(struct direct *dp, doff_t offset);
 static int ufsdirhash_recycle(int wanted);
 
-static uma_zone_t	ufsdirhash_zone;
-
 /* Dirhash list; recently-used entries are near the tail. */
 static TAILQ_HEAD(, dirhash) ufsdirhash_list;
 
 /* Protects: ufsdirhash_list, `dh_list' field, ufs_dirhashmem. */
+#ifdef __FreeBSD__
+static uma_zone_t	ufsdirhash_zone;
+#define         DIRHASH_ALLOC() uma_zalloc(ufsdirhash_zone, M_WAITOK)
+#define         DIRHASH_FREE(v) uma_zfree(ufsdirhash_zone, v)
+
 static struct mtx	ufsdirhash_mtx;
+#define         LOCK(l)         mtx_lock(l)
+#define         UNLOCK(l)       mtx_unlock(l)
+#else
+struct pool             ufsdirhash_pool;
+#define         DIRHASH_ALLOC() pool_get(&ufsdirhash_pool, PR_WAITOK)
+#define         DIRHASH_FREE(v) pool_put(&ufsdirhash_pool, v)
+
+struct rwlock           ufsdirhash_mtx;
+#define         LOCK(l)         rw_enter_write(l, curproc)
+#define         UNLOCK(l)       rw_exit_write(l)
+#define         mtx_assert(l, f)        /* nothing */
+#endif
 
 /*
  * Locking order:
@@ -156,9 +171,9 @@
 	memreqd = sizeof(*dh) + narrays * sizeof(*dh->dh_hash) +
 	    narrays * DH_NBLKOFF * sizeof(**dh->dh_hash) +
 	    nblocks * sizeof(*dh->dh_blkfree);
-	mtx_lock(&ufsdirhash_mtx);
+	LOCK(&ufsdirhash_mtx);
 	if (memreqd + ufs_dirhashmem > ufs_dirhashmaxmem) {
-		mtx_unlock(&ufsdirhash_mtx);
+		UNLOCK(&ufsdirhash_mtx);
 		if (memreqd > ufs_dirhashmaxmem / 2)
 			return (-1);
 
@@ -168,7 +183,7 @@
 		/* Enough was freed, and ufsdirhash_mtx has been locked. */
 	}
 	ufs_dirhashmem += memreqd;
-	mtx_unlock(&ufsdirhash_mtx);
+	UNLOCK(&ufsdirhash_mtx);
 
 	/*
 	 * Use non-blocking mallocs so that we will revert to a linear
@@ -176,9 +191,9 @@
 	 */
 	MALLOC(dh, struct dirhash *, sizeof *dh, M_DIRHASH, M_NOWAIT | M_ZERO);
 	if (dh == NULL) {
-		mtx_lock(&ufsdirhash_mtx);
+		LOCK(&ufsdirhash_mtx);
 		ufs_dirhashmem -= memreqd;
-		mtx_unlock(&ufsdirhash_mtx);
+		UNLOCK(&ufsdirhash_mtx);
 		return (-1);
 	}
 	MALLOC(dh->dh_hash, doff_t **, narrays * sizeof(dh->dh_hash[0]),
@@ -188,15 +203,18 @@
 	if (dh->dh_hash == NULL || dh->dh_blkfree == NULL)
 		goto fail;
 	for (i = 0; i < narrays; i++) {
-		if ((dh->dh_hash[i] = uma_zalloc(ufsdirhash_zone,
-		    M_WAITOK)) == NULL)
+		if ((dh->dh_hash[i] = DIRHASH_ALLOC()) == NULL)
 			goto fail;
 		for (j = 0; j < DH_NBLKOFF; j++)
 			dh->dh_hash[i][j] = DIRHASH_EMPTY;
 	}
 
 	/* Initialise the hash table and block statistics. */
+#ifdef __FreeBSD__
 	mtx_init(&dh->dh_mtx, "dirhash", NULL, MTX_DEF);
+#else
+	rw_init(&dh->dh_mtx);
+#endif
 	dh->dh_narrays = narrays;
 	dh->dh_hlen = nslots;
 	dh->dh_nblk = nblocks;
@@ -244,26 +262,26 @@
 
 	if (bp != NULL)
 		brelse(bp);
-	mtx_lock(&ufsdirhash_mtx);
+	LOCK(&ufsdirhash_mtx);
 	TAILQ_INSERT_TAIL(&ufsdirhash_list, dh, dh_list);
 	dh->dh_onlist = 1;
-	mtx_unlock(&ufsdirhash_mtx);
+	UNLOCK(&ufsdirhash_mtx);
 	return (0);
 
 fail:
 	if (dh->dh_hash != NULL) {
 		for (i = 0; i < narrays; i++)
 			if (dh->dh_hash[i] != NULL)
-				uma_zfree(ufsdirhash_zone, dh->dh_hash[i]);
+				DIRHASH_FREE(dh->dh_hash[i]);
 		FREE(dh->dh_hash, M_DIRHASH);
 	}
 	if (dh->dh_blkfree != NULL)
 		FREE(dh->dh_blkfree, M_DIRHASH);
 	FREE(dh, M_DIRHASH);
 	ip->i_dirhash = NULL;
-	mtx_lock(&ufsdirhash_mtx);
+	LOCK(&ufsdirhash_mtx);
 	ufs_dirhashmem -= memreqd;
-	mtx_unlock(&ufsdirhash_mtx);
+	UNLOCK(&ufsdirhash_mtx);
 	return (-1);
 }
 
@@ -278,32 +296,34 @@
 
 	if ((dh = ip->i_dirhash) == NULL)
 		return;
-	mtx_lock(&ufsdirhash_mtx);
-	mtx_lock(&dh->dh_mtx);
+	LOCK(&ufsdirhash_mtx);
+	LOCK(&dh->dh_mtx);
 	if (dh->dh_onlist)
 		TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list);
-	mtx_unlock(&dh->dh_mtx);
-	mtx_unlock(&ufsdirhash_mtx);
+	UNLOCK(&dh->dh_mtx);
+	UNLOCK(&ufsdirhash_mtx);
 
 	/* The dirhash pointed to by 'dh' is exclusively ours now. */
 
 	mem = sizeof(*dh);
 	if (dh->dh_hash != NULL) {
 		for (i = 0; i < dh->dh_narrays; i++)
-			uma_zfree(ufsdirhash_zone, dh->dh_hash[i]);
+			DIRHASH_FREE(dh->dh_hash[i]);
 		FREE(dh->dh_hash, M_DIRHASH);
 		FREE(dh->dh_blkfree, M_DIRHASH);
 		mem += dh->dh_narrays * sizeof(*dh->dh_hash) +
 		    dh->dh_narrays * DH_NBLKOFF * sizeof(**dh->dh_hash) +
 		    dh->dh_nblk * sizeof(*dh->dh_blkfree);
 	}
+#ifdef __FreeBSD__
 	mtx_destroy(&dh->dh_mtx);
+#endif
 	FREE(dh, M_DIRHASH);
 	ip->i_dirhash = NULL;
 
-	mtx_lock(&ufsdirhash_mtx);
+	LOCK(&ufsdirhash_mtx);
 	ufs_dirhashmem -= mem;
-	mtx_unlock(&ufsdirhash_mtx);
+	UNLOCK(&ufsdirhash_mtx);
 }
 
 /*
@@ -339,8 +359,8 @@
 	 * In both cases, end up holding just dh_mtx.
 	 */
 	if (TAILQ_NEXT(dh, dh_list) != NULL) {
-		mtx_lock(&ufsdirhash_mtx);
-		mtx_lock(&dh->dh_mtx);
+		LOCK(&ufsdirhash_mtx);
+		LOCK(&dh->dh_mtx);
 		/*
 		 * If the new score will be greater than that of the next
 		 * entry, then move this entry past it. With both mutexes
@@ -355,13 +375,13 @@
 			TAILQ_INSERT_AFTER(&ufsdirhash_list, dh_next, dh,
 			    dh_list);
 		}
-		mtx_unlock(&ufsdirhash_mtx);
+		UNLOCK(&ufsdirhash_mtx);
 	} else {
 		/* Already the last, though that could change as we wait. */
-		mtx_lock(&dh->dh_mtx);
+		LOCK(&dh->dh_mtx);
 	}
 	if (dh->dh_hash == NULL) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return (EJUSTRETURN);
 	}
@@ -403,7 +423,7 @@
 	    slot = WRAPINCR(slot, dh->dh_hlen)) {
 		if (offset == DIRHASH_DEL)
 			continue;
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 
 		if (offset < 0 || offset >= ip->i_size)
 			panic("ufsdirhash_lookup: bad offset in hash array");
@@ -447,9 +467,9 @@
 			return (0);
 		}
 
-		mtx_lock(&dh->dh_mtx);
+		LOCK(&dh->dh_mtx);
 		if (dh->dh_hash == NULL) {
-			mtx_unlock(&dh->dh_mtx);
+			UNLOCK(&dh->dh_mtx);
 			if (bp != NULL)
 				brelse(bp);
 			ufsdirhash_free(ip);
@@ -464,7 +484,7 @@
 			goto restart;
 		}
 	}
-	mtx_unlock(&dh->dh_mtx);
+	UNLOCK(&dh->dh_mtx);
 	if (bp != NULL)
 		brelse(bp);
 	return (ENOENT);
@@ -497,9 +517,9 @@
 
 	if ((dh = ip->i_dirhash) == NULL)
 		return (-1);
-	mtx_lock(&dh->dh_mtx);
+	LOCK(&dh->dh_mtx);
 	if (dh->dh_hash == NULL) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return (-1);
 	}
@@ -510,14 +530,14 @@
 		if ((dirblock = dh->dh_firstfree[i]) != -1)
 			break;
 	if (dirblock == -1) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		return (-1);
 	}
 
 	KASSERT(dirblock < dh->dh_nblk &&
 	    dh->dh_blkfree[dirblock] >= howmany(slotneeded, DIRALIGN),
 	    ("ufsdirhash_findfree: bad stats"));
-	mtx_unlock(&dh->dh_mtx);
+	UNLOCK(&dh->dh_mtx);
 	pos = dirblock * DIRBLKSIZ;
 	error = UFS_BLKATOFF(ip->i_vnode, (off_t)pos, (char **)&dp, &bp);
 	if (error)
@@ -577,22 +597,22 @@
 
 	if ((dh = ip->i_dirhash) == NULL)
 		return (-1);
-	mtx_lock(&dh->dh_mtx);
+	LOCK(&dh->dh_mtx);
 	if (dh->dh_hash == NULL) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return (-1);
 	}
 
 	if (dh->dh_blkfree[dh->dh_dirblks - 1] != DIRBLKSIZ / DIRALIGN) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		return (-1);
 	}
 
 	for (i = dh->dh_dirblks - 1; i >= 0; i--)
 		if (dh->dh_blkfree[i] != DIRBLKSIZ / DIRALIGN)
 			break;
-	mtx_unlock(&dh->dh_mtx);
+	UNLOCK(&dh->dh_mtx);
 	return ((doff_t)(i + 1) * DIRBLKSIZ);
 }
 
@@ -609,9 +629,9 @@
 
 	if ((dh = ip->i_dirhash) == NULL)
 		return;
-	mtx_lock(&dh->dh_mtx);
+	LOCK(&dh->dh_mtx);
 	if (dh->dh_hash == NULL) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return;
 	}
@@ -623,7 +643,7 @@
 	 * remove the hash entirely and let it be rebuilt later.
 	 */
 	if (dh->dh_hused >= (dh->dh_hlen * 3) / 4) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return;
 	}
@@ -638,7 +658,7 @@
 
 	/* Update the per-block summary info. */
 	ufsdirhash_adjfree(dh, offset, -DIRSIZ(0, dirp));
-	mtx_unlock(&dh->dh_mtx);
+	UNLOCK(&dh->dh_mtx);
 }
 
 /*
@@ -654,9 +674,9 @@
 
 	if ((dh = ip->i_dirhash) == NULL)
 		return;
-	mtx_lock(&dh->dh_mtx);
+	LOCK(&dh->dh_mtx);
 	if (dh->dh_hash == NULL) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return;
 	}
@@ -671,7 +691,7 @@
 
 	/* Update the per-block summary info. */
 	ufsdirhash_adjfree(dh, offset, DIRSIZ(0, dirp));
-	mtx_unlock(&dh->dh_mtx);
+	UNLOCK(&dh->dh_mtx);
 }
 
 /*
@@ -687,9 +707,9 @@
 
 	if ((dh = ip->i_dirhash) == NULL)
 		return;
-	mtx_lock(&dh->dh_mtx);
+	LOCK(&dh->dh_mtx);
 	if (dh->dh_hash == NULL) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return;
 	}
@@ -700,7 +720,7 @@
 	/* Find the entry, and update the offset. */
 	slot = ufsdirhash_findslot(dh, dirp->d_name, dirp->d_namlen, oldoff);
 	DH_ENTRY(dh, slot) = newoff;
-	mtx_unlock(&dh->dh_mtx);
+	UNLOCK(&dh->dh_mtx);
 }
 
 /*
@@ -715,9 +735,9 @@
 
 	if ((dh = ip->i_dirhash) == NULL)
 		return;
-	mtx_lock(&dh->dh_mtx);
+	LOCK(&dh->dh_mtx);
 	if (dh->dh_hash == NULL) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return;
 	}
@@ -727,7 +747,7 @@
 	block = offset / DIRBLKSIZ;
 	if (block >= dh->dh_nblk) {
 		/* Out of space; must rebuild. */
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return;
 	}
@@ -737,7 +757,7 @@
 	dh->dh_blkfree[block] = DIRBLKSIZ / DIRALIGN;
 	if (dh->dh_firstfree[DH_NFSTATS] == -1)
 		dh->dh_firstfree[DH_NFSTATS] = block;
-	mtx_unlock(&dh->dh_mtx);
+	UNLOCK(&dh->dh_mtx);
 }
 
 /*
@@ -751,9 +771,9 @@
 
 	if ((dh = ip->i_dirhash) == NULL)
 		return;
-	mtx_lock(&dh->dh_mtx);
+	LOCK(&dh->dh_mtx);
 	if (dh->dh_hash == NULL) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return;
 	}
@@ -768,7 +788,7 @@
 	 * if necessary.
 	 */
 	if (block < dh->dh_nblk / 8 && dh->dh_narrays > 1) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return;
 	}
@@ -787,7 +807,7 @@
 		if (dh->dh_firstfree[i] >= block)
 			panic("ufsdirhash_dirtrunc: first free corrupt");
 	dh->dh_dirblks = block;
-	mtx_unlock(&dh->dh_mtx);
+	UNLOCK(&dh->dh_mtx);
 }
 
 /*
@@ -810,9 +830,9 @@
 		return;
 	if ((dh = ip->i_dirhash) == NULL)
 		return;
-	mtx_lock(&dh->dh_mtx);
+	LOCK(&dh->dh_mtx);
 	if (dh->dh_hash == NULL) {
-		mtx_unlock(&dh->dh_mtx);
+		UNLOCK(&dh->dh_mtx);
 		ufsdirhash_free(ip);
 		return;
 	}
@@ -859,7 +879,7 @@
 			panic("ufsdirhash_checkblock: bad first-free");
 	if (dh->dh_firstfree[ffslot] == -1)
 		panic("ufsdirhash_checkblock: missing first-free entry");
-	mtx_unlock(&dh->dh_mtx);
+	UNLOCK(&dh->dh_mtx);
 }
 
 /*
@@ -1018,20 +1038,20 @@
 	u_int8_t *blkfree;
 	int i, mem, narrays;
 
-	mtx_lock(&ufsdirhash_mtx);
+	LOCK(&ufsdirhash_mtx);
 	while (wanted + ufs_dirhashmem > ufs_dirhashmaxmem) {
 		/* Find a dirhash, and lock it. */
 		if ((dh = TAILQ_FIRST(&ufsdirhash_list)) == NULL) {
-			mtx_unlock(&ufsdirhash_mtx);
+			UNLOCK(&ufsdirhash_mtx);
 			return (-1);
 		}
-		mtx_lock(&dh->dh_mtx);
+		LOCK(&dh->dh_mtx);
 		KASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list"));
 
 		/* Decrement the score; only recycle if it becomes zero. */
 		if (--dh->dh_score > 0) {
-			mtx_unlock(&dh->dh_mtx);
-			mtx_unlock(&ufsdirhash_mtx);
+			UNLOCK(&dh->dh_mtx);
+			UNLOCK(&ufsdirhash_mtx);
 			return (-1);
 		}
 
@@ -1048,15 +1068,15 @@
 		    dh->dh_nblk * sizeof(*dh->dh_blkfree);
 
 		/* Unlock everything, free the detached memory. */
-		mtx_unlock(&dh->dh_mtx);
-		mtx_unlock(&ufsdirhash_mtx);
+		UNLOCK(&dh->dh_mtx);
+		UNLOCK(&ufsdirhash_mtx);
 		for (i = 0; i < narrays; i++)
-			uma_zfree(ufsdirhash_zone, hash[i]);
+			DIRHASH_FREE(hash[i]);
 		FREE(hash, M_DIRHASH);
 		FREE(blkfree, M_DIRHASH);
 
 		/* Account for the returned memory, and repeat if necessary. */
-		mtx_lock(&ufsdirhash_mtx);
+		LOCK(&ufsdirhash_mtx);
 		ufs_dirhashmem -= mem;
 	}
 	/* Success; return with ufsdirhash_mtx locked. */
@@ -1067,9 +1087,15 @@
 void
 ufsdirhash_init()
 {
+#ifdef __FreeBSD__
 	ufsdirhash_zone = uma_zcreate("DIRHASH", DH_NBLKOFF * sizeof(doff_t),
 	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
 	mtx_init(&ufsdirhash_mtx, "dirhash list", NULL, MTX_DEF);
+#else
+	pool_init(&umadirhash_pool, DH_NBLKOFF * sizeof(doff_t), 0, 0,
+	    "dirhash", &pool_allocator_nointr);
+	rw_init(&ufsdirhash_mtx);
+#endif
 	TAILQ_INIT(&ufsdirhash_list);
 }
 
@@ -1077,8 +1103,12 @@
 ufsdirhash_uninit()
 {
 	KASSERT(TAILQ_EMPTY(&ufsdirhash_list), ("ufsdirhash_uninit"));
+#ifdef __FreeBSD__
 	uma_zdestroy(ufsdirhash_zone);
 	mtx_destroy(&ufsdirhash_mtx);
+#else
+	pool_destroy(&ufsdirhash_pool);
+#endif
 }
 
 #endif /* UFS_DIRHASH */


-- 
you are more than the sum of what you consume


More information about the freebsd-hackers mailing list