From owner-freebsd-hackers@FreeBSD.ORG Tue Dec 16 19:12:13 2003 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E26AF16A4CF for ; Tue, 16 Dec 2003 19:12:13 -0800 (PST) Received: from mail.codefusionis.com (ns.codefusionis.com [208.33.29.188]) by mx1.FreeBSD.org (Postfix) with SMTP id A9FBA43D35 for ; Tue, 16 Dec 2003 19:11:44 -0800 (PST) (envelope-from tedu@zeitbombe.org) Received: (qmail 11395 invoked by uid 1049); 17 Dec 2003 03:12:08 -0000 Received: from localhost (sendmail-bs@127.0.0.1) by localhost with SMTP; 17 Dec 2003 03:12:08 -0000 Date: Tue, 16 Dec 2003 22:12:08 -0500 (EST) From: Ted Unangst X-X-Sender: tedu@ns.codefusionis.com To: freebsd-hackers@freebsd.org Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Subject: patch: portable dirhash X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Dec 2003 03:12:14 -0000 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