14 #include <sys/vnode.h>
17 #include <ufs/fsdir.h>
18 #include <ufs/inode.h>
20 #include <ufs/ufs/dir.h>
21 #include <ufs/ufs/dinode.h>
22 #include <ufs/ffs/fs.h>
25 #include <protocols/dumprestore.h>
37 typedef struct Block {
38 struct Block *b_HNext; /* must be first field */
46 static char *DataBase;
47 static Block **BlockHash;
59 if ((BlockSize = sblock->fs_bsize * BLKFACTOR) > MAXBSIZE)
61 NBlocks = cachesize / BlockSize;
62 HSize = NBlocks / HFACTOR;
64 msg("Cache %d MB, blocksize = %d\n",
65 NBlocks * BlockSize / (1024 * 1024), BlockSize);
67 base = calloc(sizeof(Block), NBlocks);
68 BlockHash = calloc(sizeof(Block *), HSize);
69 DataBase = mmap(NULL, NBlocks * BlockSize,
70 PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
71 for (i = 0; i < NBlocks; ++i) {
72 base[i].b_Data = DataBase + i * BlockSize;
73 base[i].b_Offset = (off_t)-1;
75 base[i].b_HNext = BlockHash[hi];
76 BlockHash[hi] = &base[i];
81 cread(int fd, void *buf, size_t nbytes, off_t offset)
91 * If the cache is disabled, or we do not yet know the filesystem
92 * block size, then revert to pread. Otherwise initialize the
93 * cache as necessary and continue.
95 if (cachesize <= 0 || sblock->fs_bsize == 0)
96 return(pread(fd, buf, nbytes, offset));
101 * If the request crosses a cache block boundary, or the
102 * request is larger or equal to the cache block size,
103 * revert to pread(). Full-block-reads are typically
104 * one-time calls and caching would be detrimental.
106 mask = ~(off_t)(BlockSize - 1);
107 if (nbytes >= BlockSize ||
108 ((offset ^ (offset + nbytes - 1)) & mask) != 0) {
109 return(pread(fd, buf, nbytes, offset));
113 * Obtain and access the cache block. Cache a successful
114 * result. If an error occurs, revert to pread() (this might
115 * occur near the end of the media).
117 hi = (offset / BlockSize) % HSize;
118 pblk = &BlockHash[hi];
120 while ((blk = *pblk) != NULL) {
121 if (((blk->b_Offset ^ offset) & mask) == 0)
124 pblk = &blk->b_HNext;
129 blk->b_Offset = offset & mask;
130 n = pread(fd, blk->b_Data, BlockSize, blk->b_Offset);
131 if (n != BlockSize) {
132 blk->b_Offset = (off_t)-1;
137 bcopy(blk->b_Data + (offset - blk->b_Offset), buf, nbytes);
138 *pblk = blk->b_HNext;
139 blk->b_HNext = BlockHash[hi];
143 return(pread(fd, buf, nbytes, offset));