6 * $FreeBSD: src/sbin/dump/cache.c,v 1.1.2.1 2003/01/25 18:54:59 dillon Exp $
7 * $DragonFly: src/sbin/dump/cache.c,v 1.3 2003/08/08 04:18:37 dillon Exp $
10 #include <sys/param.h>
15 #include <sys/vnode.h>
18 #include <ufs/fsdir.h>
19 #include <ufs/inode.h>
21 #include <vfs/ufs/dir.h>
22 #include <vfs/ufs/dinode.h>
23 #include <vfs/ufs/fs.h>
26 #include <protocols/dumprestore.h>
38 typedef struct Block {
39 struct Block *b_HNext; /* must be first field */
47 static char *DataBase;
48 static Block **BlockHash;
60 if ((BlockSize = sblock->fs_bsize * BLKFACTOR) > MAXBSIZE)
62 NBlocks = cachesize / BlockSize;
63 HSize = NBlocks / HFACTOR;
65 msg("Cache %d MB, blocksize = %d\n",
66 NBlocks * BlockSize / (1024 * 1024), BlockSize);
68 base = calloc(sizeof(Block), NBlocks);
69 BlockHash = calloc(sizeof(Block *), HSize);
70 DataBase = mmap(NULL, NBlocks * BlockSize,
71 PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
72 for (i = 0; i < NBlocks; ++i) {
73 base[i].b_Data = DataBase + i * BlockSize;
74 base[i].b_Offset = (off_t)-1;
76 base[i].b_HNext = BlockHash[hi];
77 BlockHash[hi] = &base[i];
82 cread(int fd, void *buf, size_t nbytes, off_t offset)
92 * If the cache is disabled, or we do not yet know the filesystem
93 * block size, then revert to pread. Otherwise initialize the
94 * cache as necessary and continue.
96 if (cachesize <= 0 || sblock->fs_bsize == 0)
97 return(pread(fd, buf, nbytes, offset));
102 * If the request crosses a cache block boundary, or the
103 * request is larger or equal to the cache block size,
104 * revert to pread(). Full-block-reads are typically
105 * one-time calls and caching would be detrimental.
107 mask = ~(off_t)(BlockSize - 1);
108 if (nbytes >= BlockSize ||
109 ((offset ^ (offset + nbytes - 1)) & mask) != 0) {
110 return(pread(fd, buf, nbytes, offset));
114 * Obtain and access the cache block. Cache a successful
115 * result. If an error occurs, revert to pread() (this might
116 * occur near the end of the media).
118 hi = (offset / BlockSize) % HSize;
119 pblk = &BlockHash[hi];
121 while ((blk = *pblk) != NULL) {
122 if (((blk->b_Offset ^ offset) & mask) == 0)
125 pblk = &blk->b_HNext;
130 blk->b_Offset = offset & mask;
131 n = pread(fd, blk->b_Data, BlockSize, blk->b_Offset);
132 if (n != BlockSize) {
133 blk->b_Offset = (off_t)-1;
138 bcopy(blk->b_Data + (offset - blk->b_Offset), buf, nbytes);
139 *pblk = blk->b_HNext;
140 blk->b_HNext = BlockHash[hi];
144 return(pread(fd, buf, nbytes, offset));