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
));