158f0484fSRodney W. Grimes /*- 2f1e396bcSPaul Traina * Copyright (c) 1990, 1993, 1994 358f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 458f0484fSRodney W. Grimes * 558f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 658f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 758f0484fSRodney W. Grimes * are met: 858f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 958f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1058f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1158f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1258f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1358f0484fSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 1458f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 1558f0484fSRodney W. Grimes * without specific prior written permission. 1658f0484fSRodney W. Grimes * 1758f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1858f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1958f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2058f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2158f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2258f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2358f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2458f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2558f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2658f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2758f0484fSRodney W. Grimes * SUCH DAMAGE. 2858f0484fSRodney W. Grimes */ 2958f0484fSRodney W. Grimes 3058f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 31f1e396bcSPaul Traina static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94"; 3258f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 33333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 34333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 3558f0484fSRodney W. Grimes 36d201fe46SDaniel Eischen #include "namespace.h" 3758f0484fSRodney W. Grimes #include <sys/param.h> 38f1e396bcSPaul Traina #include <sys/queue.h> 3958f0484fSRodney W. Grimes #include <sys/stat.h> 4058f0484fSRodney W. Grimes 4158f0484fSRodney W. Grimes #include <errno.h> 4258f0484fSRodney W. Grimes #include <stdio.h> 4358f0484fSRodney W. Grimes #include <stdlib.h> 4458f0484fSRodney W. Grimes #include <string.h> 4558f0484fSRodney W. Grimes #include <unistd.h> 46d201fe46SDaniel Eischen #include "un-namespace.h" 4758f0484fSRodney W. Grimes 4858f0484fSRodney W. Grimes #include <db.h> 49f1e396bcSPaul Traina 5058f0484fSRodney W. Grimes #define __MPOOLINTERFACE_PRIVATE 51f1e396bcSPaul Traina #include <mpool.h> 5258f0484fSRodney W. Grimes 53c05ac53bSDavid E. O'Brien static BKT *mpool_bkt(MPOOL *); 54c05ac53bSDavid E. O'Brien static BKT *mpool_look(MPOOL *, pgno_t); 55c05ac53bSDavid E. O'Brien static int mpool_write(MPOOL *, BKT *); 5658f0484fSRodney W. Grimes 5758f0484fSRodney W. Grimes /* 58f1e396bcSPaul Traina * mpool_open -- 59f1e396bcSPaul Traina * Initialize a memory pool. 6058f0484fSRodney W. Grimes */ 610ac22237SXin LI /* ARGSUSED */ 6258f0484fSRodney W. Grimes MPOOL * 630ac22237SXin LI mpool_open(void *key, int fd, pgno_t pagesize, pgno_t maxcache) 6458f0484fSRodney W. Grimes { 6558f0484fSRodney W. Grimes struct stat sb; 6658f0484fSRodney W. Grimes MPOOL *mp; 6758f0484fSRodney W. Grimes int entry; 6858f0484fSRodney W. Grimes 69f1e396bcSPaul Traina /* 70f1e396bcSPaul Traina * Get information about the file. 71f1e396bcSPaul Traina * 72f1e396bcSPaul Traina * XXX 73f1e396bcSPaul Traina * We don't currently handle pipes, although we should. 74f1e396bcSPaul Traina */ 75d201fe46SDaniel Eischen if (_fstat(fd, &sb)) 7658f0484fSRodney W. Grimes return (NULL); 7758f0484fSRodney W. Grimes if (!S_ISREG(sb.st_mode)) { 7858f0484fSRodney W. Grimes errno = ESPIPE; 7958f0484fSRodney W. Grimes return (NULL); 8058f0484fSRodney W. Grimes } 8158f0484fSRodney W. Grimes 82f1e396bcSPaul Traina /* Allocate and initialize the MPOOL cookie. */ 83f1e396bcSPaul Traina if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL) 8458f0484fSRodney W. Grimes return (NULL); 85fabacd3aSPoul-Henning Kamp TAILQ_INIT(&mp->lqh); 8658f0484fSRodney W. Grimes for (entry = 0; entry < HASHSIZE; ++entry) 87fabacd3aSPoul-Henning Kamp TAILQ_INIT(&mp->hqh[entry]); 8858f0484fSRodney W. Grimes mp->maxcache = maxcache; 8958f0484fSRodney W. Grimes mp->npages = sb.st_size / pagesize; 90f1e396bcSPaul Traina mp->pagesize = pagesize; 9158f0484fSRodney W. Grimes mp->fd = fd; 9258f0484fSRodney W. Grimes return (mp); 9358f0484fSRodney W. Grimes } 9458f0484fSRodney W. Grimes 9558f0484fSRodney W. Grimes /* 96f1e396bcSPaul Traina * mpool_filter -- 97f1e396bcSPaul Traina * Initialize input/output filters. 9858f0484fSRodney W. Grimes */ 9958f0484fSRodney W. Grimes void 1000ac22237SXin LI mpool_filter(MPOOL *mp, void (*pgin) (void *, pgno_t, void *), 1010ac22237SXin LI void (*pgout) (void *, pgno_t, void *), void *pgcookie) 10258f0484fSRodney W. Grimes { 10358f0484fSRodney W. Grimes mp->pgin = pgin; 10458f0484fSRodney W. Grimes mp->pgout = pgout; 10558f0484fSRodney W. Grimes mp->pgcookie = pgcookie; 10658f0484fSRodney W. Grimes } 10758f0484fSRodney W. Grimes 10858f0484fSRodney W. Grimes /* 109f1e396bcSPaul Traina * mpool_new -- 110f1e396bcSPaul Traina * Get a new page of memory. 11158f0484fSRodney W. Grimes */ 11258f0484fSRodney W. Grimes void * 11358f0484fSRodney W. Grimes mpool_new(mp, pgnoaddr) 11458f0484fSRodney W. Grimes MPOOL *mp; 11558f0484fSRodney W. Grimes pgno_t *pgnoaddr; 11658f0484fSRodney W. Grimes { 117f1e396bcSPaul Traina struct _hqh *head; 118f1e396bcSPaul Traina BKT *bp; 11958f0484fSRodney W. Grimes 120f1e396bcSPaul Traina if (mp->npages == MAX_PAGE_NUMBER) { 121f1e396bcSPaul Traina (void)fprintf(stderr, "mpool_new: page allocation overflow.\n"); 122f1e396bcSPaul Traina abort(); 123f1e396bcSPaul Traina } 12458f0484fSRodney W. Grimes #ifdef STATISTICS 12558f0484fSRodney W. Grimes ++mp->pagenew; 12658f0484fSRodney W. Grimes #endif 12758f0484fSRodney W. Grimes /* 128f1e396bcSPaul Traina * Get a BKT from the cache. Assign a new page number, attach 129f1e396bcSPaul Traina * it to the head of the hash chain, the tail of the lru chain, 130f1e396bcSPaul Traina * and return. 13158f0484fSRodney W. Grimes */ 132f1e396bcSPaul Traina if ((bp = mpool_bkt(mp)) == NULL) 13358f0484fSRodney W. Grimes return (NULL); 134f1e396bcSPaul Traina *pgnoaddr = bp->pgno = mp->npages++; 135f1e396bcSPaul Traina bp->flags = MPOOL_PINNED; 136f1e396bcSPaul Traina 137f1e396bcSPaul Traina head = &mp->hqh[HASHKEY(bp->pgno)]; 138fabacd3aSPoul-Henning Kamp TAILQ_INSERT_HEAD(head, bp, hq); 139fabacd3aSPoul-Henning Kamp TAILQ_INSERT_TAIL(&mp->lqh, bp, q); 140f1e396bcSPaul Traina return (bp->page); 14158f0484fSRodney W. Grimes } 14258f0484fSRodney W. Grimes 14358f0484fSRodney W. Grimes /* 144f1e396bcSPaul Traina * mpool_get 145f1e396bcSPaul Traina * Get a page. 14658f0484fSRodney W. Grimes */ 1470ac22237SXin LI /* ARGSUSED */ 14858f0484fSRodney W. Grimes void * 1490ac22237SXin LI mpool_get(MPOOL *mp, pgno_t pgno, 1500ac22237SXin LI u_int flags) /* XXX not used? */ 15158f0484fSRodney W. Grimes { 152f1e396bcSPaul Traina struct _hqh *head; 153f1e396bcSPaul Traina BKT *bp; 15458f0484fSRodney W. Grimes off_t off; 15558f0484fSRodney W. Grimes int nr; 15658f0484fSRodney W. Grimes 157f1e396bcSPaul Traina /* Check for attempt to retrieve a non-existent page. */ 15858f0484fSRodney W. Grimes if (pgno >= mp->npages) { 15958f0484fSRodney W. Grimes errno = EINVAL; 16058f0484fSRodney W. Grimes return (NULL); 16158f0484fSRodney W. Grimes } 16258f0484fSRodney W. Grimes 163f1e396bcSPaul Traina #ifdef STATISTICS 164f1e396bcSPaul Traina ++mp->pageget; 165f1e396bcSPaul Traina #endif 16658f0484fSRodney W. Grimes 167f1e396bcSPaul Traina /* Check for a page that is cached. */ 168f1e396bcSPaul Traina if ((bp = mpool_look(mp, pgno)) != NULL) { 169f1e396bcSPaul Traina #ifdef DEBUG 170f1e396bcSPaul Traina if (bp->flags & MPOOL_PINNED) { 171f1e396bcSPaul Traina (void)fprintf(stderr, 172f1e396bcSPaul Traina "mpool_get: page %d already pinned\n", bp->pgno); 173f1e396bcSPaul Traina abort(); 174f1e396bcSPaul Traina } 175f1e396bcSPaul Traina #endif 176f1e396bcSPaul Traina /* 177f1e396bcSPaul Traina * Move the page to the head of the hash chain and the tail 178f1e396bcSPaul Traina * of the lru chain. 179f1e396bcSPaul Traina */ 180f1e396bcSPaul Traina head = &mp->hqh[HASHKEY(bp->pgno)]; 181fabacd3aSPoul-Henning Kamp TAILQ_REMOVE(head, bp, hq); 182fabacd3aSPoul-Henning Kamp TAILQ_INSERT_HEAD(head, bp, hq); 183fabacd3aSPoul-Henning Kamp TAILQ_REMOVE(&mp->lqh, bp, q); 184fabacd3aSPoul-Henning Kamp TAILQ_INSERT_TAIL(&mp->lqh, bp, q); 185f1e396bcSPaul Traina 186f1e396bcSPaul Traina /* Return a pinned page. */ 187f1e396bcSPaul Traina bp->flags |= MPOOL_PINNED; 188f1e396bcSPaul Traina return (bp->page); 189f1e396bcSPaul Traina } 190f1e396bcSPaul Traina 191f1e396bcSPaul Traina /* Get a page from the cache. */ 192f1e396bcSPaul Traina if ((bp = mpool_bkt(mp)) == NULL) 193f1e396bcSPaul Traina return (NULL); 194f1e396bcSPaul Traina 195f1e396bcSPaul Traina /* Read in the contents. */ 19658f0484fSRodney W. Grimes #ifdef STATISTICS 19758f0484fSRodney W. Grimes ++mp->pageread; 19858f0484fSRodney W. Grimes #endif 19958f0484fSRodney W. Grimes off = mp->pagesize * pgno; 200f4d14036SDavid Schultz nr = pread(mp->fd, bp->page, mp->pagesize, off); 201f4d14036SDavid Schultz if (nr != mp->pagesize) { 20258f0484fSRodney W. Grimes if (nr >= 0) 20358f0484fSRodney W. Grimes errno = EFTYPE; 20458f0484fSRodney W. Grimes return (NULL); 20558f0484fSRodney W. Grimes } 20658f0484fSRodney W. Grimes 207f1e396bcSPaul Traina /* Set the page number, pin the page. */ 208f1e396bcSPaul Traina bp->pgno = pgno; 209f1e396bcSPaul Traina bp->flags = MPOOL_PINNED; 210f1e396bcSPaul Traina 211f1e396bcSPaul Traina /* 212f1e396bcSPaul Traina * Add the page to the head of the hash chain and the tail 213f1e396bcSPaul Traina * of the lru chain. 214f1e396bcSPaul Traina */ 215f1e396bcSPaul Traina head = &mp->hqh[HASHKEY(bp->pgno)]; 216fabacd3aSPoul-Henning Kamp TAILQ_INSERT_HEAD(head, bp, hq); 217fabacd3aSPoul-Henning Kamp TAILQ_INSERT_TAIL(&mp->lqh, bp, q); 218f1e396bcSPaul Traina 219f1e396bcSPaul Traina /* Run through the user's filter. */ 220f1e396bcSPaul Traina if (mp->pgin != NULL) 221f1e396bcSPaul Traina (mp->pgin)(mp->pgcookie, bp->pgno, bp->page); 222f1e396bcSPaul Traina 223f1e396bcSPaul Traina return (bp->page); 22458f0484fSRodney W. Grimes } 22558f0484fSRodney W. Grimes 22658f0484fSRodney W. Grimes /* 227f1e396bcSPaul Traina * mpool_put 228f1e396bcSPaul Traina * Return a page. 22958f0484fSRodney W. Grimes */ 2300ac22237SXin LI /* ARGSUSED */ 23158f0484fSRodney W. Grimes int 2320ac22237SXin LI mpool_put(MPOOL *mp, void *page, u_int flags) 23358f0484fSRodney W. Grimes { 234f1e396bcSPaul Traina BKT *bp; 23558f0484fSRodney W. Grimes 23658f0484fSRodney W. Grimes #ifdef STATISTICS 23758f0484fSRodney W. Grimes ++mp->pageput; 23858f0484fSRodney W. Grimes #endif 239f1e396bcSPaul Traina bp = (BKT *)((char *)page - sizeof(BKT)); 24058f0484fSRodney W. Grimes #ifdef DEBUG 241f1e396bcSPaul Traina if (!(bp->flags & MPOOL_PINNED)) { 242f1e396bcSPaul Traina (void)fprintf(stderr, 243f1e396bcSPaul Traina "mpool_put: page %d not pinned\n", bp->pgno); 244f1e396bcSPaul Traina abort(); 24558f0484fSRodney W. Grimes } 24658f0484fSRodney W. Grimes #endif 247f1e396bcSPaul Traina bp->flags &= ~MPOOL_PINNED; 248f1e396bcSPaul Traina bp->flags |= flags & MPOOL_DIRTY; 24958f0484fSRodney W. Grimes return (RET_SUCCESS); 25058f0484fSRodney W. Grimes } 25158f0484fSRodney W. Grimes 25258f0484fSRodney W. Grimes /* 253f1e396bcSPaul Traina * mpool_close 254f1e396bcSPaul Traina * Close the buffer pool. 25558f0484fSRodney W. Grimes */ 25658f0484fSRodney W. Grimes int 2570ac22237SXin LI mpool_close(MPOOL *mp) 25858f0484fSRodney W. Grimes { 259f1e396bcSPaul Traina BKT *bp; 26058f0484fSRodney W. Grimes 26158f0484fSRodney W. Grimes /* Free up any space allocated to the lru pages. */ 262429d4912SBrian Feldman while (!TAILQ_EMPTY(&mp->lqh)) { 263429d4912SBrian Feldman bp = TAILQ_FIRST(&mp->lqh); 264fabacd3aSPoul-Henning Kamp TAILQ_REMOVE(&mp->lqh, bp, q); 265f1e396bcSPaul Traina free(bp); 26658f0484fSRodney W. Grimes } 267f1e396bcSPaul Traina 268f1e396bcSPaul Traina /* Free the MPOOL cookie. */ 26958f0484fSRodney W. Grimes free(mp); 27058f0484fSRodney W. Grimes return (RET_SUCCESS); 27158f0484fSRodney W. Grimes } 27258f0484fSRodney W. Grimes 27358f0484fSRodney W. Grimes /* 274f1e396bcSPaul Traina * mpool_sync 275f1e396bcSPaul Traina * Sync the pool to disk. 27658f0484fSRodney W. Grimes */ 27758f0484fSRodney W. Grimes int 2780ac22237SXin LI mpool_sync(MPOOL *mp) 27958f0484fSRodney W. Grimes { 280f1e396bcSPaul Traina BKT *bp; 28158f0484fSRodney W. Grimes 282f1e396bcSPaul Traina /* Walk the lru chain, flushing any dirty pages to disk. */ 283fabacd3aSPoul-Henning Kamp TAILQ_FOREACH(bp, &mp->lqh, q) 284f1e396bcSPaul Traina if (bp->flags & MPOOL_DIRTY && 285f1e396bcSPaul Traina mpool_write(mp, bp) == RET_ERROR) 28658f0484fSRodney W. Grimes return (RET_ERROR); 287f1e396bcSPaul Traina 288f1e396bcSPaul Traina /* Sync the file descriptor. */ 2899233c4d9SJason Evans return (_fsync(mp->fd) ? RET_ERROR : RET_SUCCESS); 29058f0484fSRodney W. Grimes } 29158f0484fSRodney W. Grimes 29258f0484fSRodney W. Grimes /* 293f1e396bcSPaul Traina * mpool_bkt 294f1e396bcSPaul Traina * Get a page from the cache (or create one). 29558f0484fSRodney W. Grimes */ 29658f0484fSRodney W. Grimes static BKT * 2970ac22237SXin LI mpool_bkt(MPOOL *mp) 29858f0484fSRodney W. Grimes { 299f1e396bcSPaul Traina struct _hqh *head; 300f1e396bcSPaul Traina BKT *bp; 30158f0484fSRodney W. Grimes 302f1e396bcSPaul Traina /* If under the max cached, always create a new page. */ 30358f0484fSRodney W. Grimes if (mp->curcache < mp->maxcache) 30458f0484fSRodney W. Grimes goto new; 30558f0484fSRodney W. Grimes 30658f0484fSRodney W. Grimes /* 307f1e396bcSPaul Traina * If the cache is max'd out, walk the lru list for a buffer we 308f1e396bcSPaul Traina * can flush. If we find one, write it (if necessary) and take it 309f1e396bcSPaul Traina * off any lists. If we don't find anything we grow the cache anyway. 31058f0484fSRodney W. Grimes * The cache never shrinks. 31158f0484fSRodney W. Grimes */ 312fabacd3aSPoul-Henning Kamp TAILQ_FOREACH(bp, &mp->lqh, q) 313f1e396bcSPaul Traina if (!(bp->flags & MPOOL_PINNED)) { 314f1e396bcSPaul Traina /* Flush if dirty. */ 315f1e396bcSPaul Traina if (bp->flags & MPOOL_DIRTY && 316f1e396bcSPaul Traina mpool_write(mp, bp) == RET_ERROR) 31758f0484fSRodney W. Grimes return (NULL); 31858f0484fSRodney W. Grimes #ifdef STATISTICS 31958f0484fSRodney W. Grimes ++mp->pageflush; 32058f0484fSRodney W. Grimes #endif 321f1e396bcSPaul Traina /* Remove from the hash and lru queues. */ 322f1e396bcSPaul Traina head = &mp->hqh[HASHKEY(bp->pgno)]; 323fabacd3aSPoul-Henning Kamp TAILQ_REMOVE(head, bp, hq); 324fabacd3aSPoul-Henning Kamp TAILQ_REMOVE(&mp->lqh, bp, q); 32558f0484fSRodney W. Grimes #ifdef DEBUG 326f1e396bcSPaul Traina { void *spage; 327f1e396bcSPaul Traina spage = bp->page; 328f1e396bcSPaul Traina memset(bp, 0xff, sizeof(BKT) + mp->pagesize); 329f1e396bcSPaul Traina bp->page = spage; 33058f0484fSRodney W. Grimes } 33158f0484fSRodney W. Grimes #endif 332f1e396bcSPaul Traina return (bp); 33358f0484fSRodney W. Grimes } 33458f0484fSRodney W. Grimes 335f1e396bcSPaul Traina new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL) 33658f0484fSRodney W. Grimes return (NULL); 33758f0484fSRodney W. Grimes #ifdef STATISTICS 33858f0484fSRodney W. Grimes ++mp->pagealloc; 33958f0484fSRodney W. Grimes #endif 340f1e396bcSPaul Traina #if defined(DEBUG) || defined(PURIFY) 341f1e396bcSPaul Traina memset(bp, 0xff, sizeof(BKT) + mp->pagesize); 34258f0484fSRodney W. Grimes #endif 343f1e396bcSPaul Traina bp->page = (char *)bp + sizeof(BKT); 34458f0484fSRodney W. Grimes ++mp->curcache; 345f1e396bcSPaul Traina return (bp); 34658f0484fSRodney W. Grimes } 34758f0484fSRodney W. Grimes 34858f0484fSRodney W. Grimes /* 349f1e396bcSPaul Traina * mpool_write 350f1e396bcSPaul Traina * Write a page to disk. 35158f0484fSRodney W. Grimes */ 35258f0484fSRodney W. Grimes static int 3530ac22237SXin LI mpool_write(MPOOL *mp, BKT *bp) 35458f0484fSRodney W. Grimes { 35558f0484fSRodney W. Grimes off_t off; 35658f0484fSRodney W. Grimes 35758f0484fSRodney W. Grimes #ifdef STATISTICS 35858f0484fSRodney W. Grimes ++mp->pagewrite; 35958f0484fSRodney W. Grimes #endif 360f1e396bcSPaul Traina 361f1e396bcSPaul Traina /* Run through the user's filter. */ 362f1e396bcSPaul Traina if (mp->pgout) 363f1e396bcSPaul Traina (mp->pgout)(mp->pgcookie, bp->pgno, bp->page); 364f1e396bcSPaul Traina 365f1e396bcSPaul Traina off = mp->pagesize * bp->pgno; 366f4d14036SDavid Schultz if (pwrite(mp->fd, bp->page, mp->pagesize, off) != mp->pagesize) 36758f0484fSRodney W. Grimes return (RET_ERROR); 368f1e396bcSPaul Traina 369f1e396bcSPaul Traina bp->flags &= ~MPOOL_DIRTY; 37058f0484fSRodney W. Grimes return (RET_SUCCESS); 37158f0484fSRodney W. Grimes } 37258f0484fSRodney W. Grimes 37358f0484fSRodney W. Grimes /* 374f1e396bcSPaul Traina * mpool_look 375f1e396bcSPaul Traina * Lookup a page in the cache. 37658f0484fSRodney W. Grimes */ 37758f0484fSRodney W. Grimes static BKT * 3780ac22237SXin LI mpool_look(MPOOL *mp, pgno_t pgno) 37958f0484fSRodney W. Grimes { 380f1e396bcSPaul Traina struct _hqh *head; 381f1e396bcSPaul Traina BKT *bp; 38258f0484fSRodney W. Grimes 383f1e396bcSPaul Traina head = &mp->hqh[HASHKEY(pgno)]; 384fabacd3aSPoul-Henning Kamp TAILQ_FOREACH(bp, head, hq) 385f1e396bcSPaul Traina if (bp->pgno == pgno) { 38658f0484fSRodney W. Grimes #ifdef STATISTICS 38758f0484fSRodney W. Grimes ++mp->cachehit; 38858f0484fSRodney W. Grimes #endif 389f1e396bcSPaul Traina return (bp); 39058f0484fSRodney W. Grimes } 39158f0484fSRodney W. Grimes #ifdef STATISTICS 39258f0484fSRodney W. Grimes ++mp->cachemiss; 39358f0484fSRodney W. Grimes #endif 39458f0484fSRodney W. Grimes return (NULL); 39558f0484fSRodney W. Grimes } 39658f0484fSRodney W. Grimes 39758f0484fSRodney W. Grimes #ifdef STATISTICS 39858f0484fSRodney W. Grimes /* 399f1e396bcSPaul Traina * mpool_stat 400f1e396bcSPaul Traina * Print out cache statistics. 40158f0484fSRodney W. Grimes */ 40258f0484fSRodney W. Grimes void 4030ac22237SXin LI mpool_stat(MPOOL *mp) 40458f0484fSRodney W. Grimes { 405f1e396bcSPaul Traina BKT *bp; 40658f0484fSRodney W. Grimes int cnt; 40758f0484fSRodney W. Grimes char *sep; 40858f0484fSRodney W. Grimes 4097efabbb9SXin LI (void)fprintf(stderr, "%lu pages in the file\n", mp->npages); 41058f0484fSRodney W. Grimes (void)fprintf(stderr, 4117efabbb9SXin LI "page size %lu, cacheing %lu pages of %lu page max cache\n", 41258f0484fSRodney W. Grimes mp->pagesize, mp->curcache, mp->maxcache); 41358f0484fSRodney W. Grimes (void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n", 41458f0484fSRodney W. Grimes mp->pageput, mp->pageget, mp->pagenew); 41558f0484fSRodney W. Grimes (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n", 41658f0484fSRodney W. Grimes mp->pagealloc, mp->pageflush); 41758f0484fSRodney W. Grimes if (mp->cachehit + mp->cachemiss) 41858f0484fSRodney W. Grimes (void)fprintf(stderr, 41958f0484fSRodney W. Grimes "%.0f%% cache hit rate (%lu hits, %lu misses)\n", 42058f0484fSRodney W. Grimes ((double)mp->cachehit / (mp->cachehit + mp->cachemiss)) 42158f0484fSRodney W. Grimes * 100, mp->cachehit, mp->cachemiss); 42258f0484fSRodney W. Grimes (void)fprintf(stderr, "%lu page reads, %lu page writes\n", 42358f0484fSRodney W. Grimes mp->pageread, mp->pagewrite); 42458f0484fSRodney W. Grimes 42558f0484fSRodney W. Grimes sep = ""; 42658f0484fSRodney W. Grimes cnt = 0; 427fabacd3aSPoul-Henning Kamp TAILQ_FOREACH(bp, &mp->lqh, q) { 428f1e396bcSPaul Traina (void)fprintf(stderr, "%s%d", sep, bp->pgno); 429f1e396bcSPaul Traina if (bp->flags & MPOOL_DIRTY) 43058f0484fSRodney W. Grimes (void)fprintf(stderr, "d"); 431f1e396bcSPaul Traina if (bp->flags & MPOOL_PINNED) 43258f0484fSRodney W. Grimes (void)fprintf(stderr, "P"); 43358f0484fSRodney W. Grimes if (++cnt == 10) { 43458f0484fSRodney W. Grimes sep = "\n"; 43558f0484fSRodney W. Grimes cnt = 0; 43658f0484fSRodney W. Grimes } else 43758f0484fSRodney W. Grimes sep = ", "; 43858f0484fSRodney W. Grimes 43958f0484fSRodney W. Grimes } 44058f0484fSRodney W. Grimes (void)fprintf(stderr, "\n"); 44158f0484fSRodney W. Grimes } 44258f0484fSRodney W. Grimes #endif 443