1 /* Test 72 - libminixfs unit test. 2 * 3 * Exercise the caching functionality of libminixfs in isolation. 4 */ 5 6 #define _MINIX_SYSTEM 7 8 #include <minix/sysutil.h> 9 #include <minix/syslib.h> 10 #include <minix/vm.h> 11 #include <minix/bdev.h> 12 #include <sys/types.h> 13 #include <sys/mman.h> 14 #include <sys/ioc_memory.h> 15 #include <stdio.h> 16 #include <stdarg.h> 17 #include <assert.h> 18 #include <string.h> 19 #include <stdlib.h> 20 #include <unistd.h> 21 #include <fcntl.h> 22 #include <math.h> 23 #include <minix/libminixfs.h> 24 25 int max_error = 0; 26 27 #include "common.h" 28 #include "testcache.h" 29 30 #define MYMAJOR 40 /* doesn't really matter, shouldn't be NO_DEV though */ 31 32 #define MYDEV makedev(MYMAJOR, 1) 33 34 static int curblocksize = -1; 35 36 static char *writtenblocks[MAXBLOCKS]; 37 38 /* Some functions used by testcache.c */ 39 40 int 41 dowriteblock(int b, int blocksize, u32_t seed, char *data) 42 { 43 struct buf *bp; 44 int r; 45 46 assert(blocksize == curblocksize); 47 48 if ((r = lmfs_get_block(&bp, MYDEV, b, NORMAL)) != 0) { 49 e(30); 50 return 0; 51 } 52 53 memcpy(bp->data, data, blocksize); 54 55 lmfs_markdirty(bp); 56 57 lmfs_put_block(bp); 58 59 return blocksize; 60 } 61 62 int 63 readblock(int b, int blocksize, u32_t seed, char *data) 64 { 65 struct buf *bp; 66 int r; 67 68 assert(blocksize == curblocksize); 69 70 if ((r = lmfs_get_block(&bp, MYDEV, b, NORMAL)) != 0) { 71 e(30); 72 return 0; 73 } 74 75 memcpy(data, bp->data, blocksize); 76 77 lmfs_put_block(bp); 78 79 return blocksize; 80 } 81 82 void testend(void) 83 { 84 int i; 85 for(i = 0; i < MAXBLOCKS; i++) { 86 if(writtenblocks[i]) { 87 free(writtenblocks[i]); 88 writtenblocks[i] = NULL; 89 } 90 } 91 } 92 93 /* Fake some libminixfs client functions */ 94 95 static void allocate(int b) 96 { 97 assert(curblocksize > 0); 98 assert(!writtenblocks[b]); 99 if(!(writtenblocks[b] = calloc(1, curblocksize))) { 100 fprintf(stderr, "out of memory allocating block %d\n", b); 101 exit(1); 102 } 103 } 104 105 /* Fake some libblockdriver functions */ 106 ssize_t 107 bdev_gather(dev_t dev, u64_t pos, iovec_t *vec, int count, int flags) 108 { 109 int i, block; 110 size_t size, block_off; 111 ssize_t tot = 0; 112 assert(dev == MYDEV); 113 assert(curblocksize > 0); 114 assert(!(pos % curblocksize)); 115 for(i = 0; i < count; i++) { 116 char *data = (char *) vec[i].iov_addr; 117 block = pos / curblocksize; 118 block_off = (size_t)(pos % curblocksize); 119 size = vec[i].iov_size; 120 assert(size == PAGE_SIZE); 121 assert(block >= 0); 122 assert(block < MAXBLOCKS); 123 assert(block_off + size <= curblocksize); 124 if(!writtenblocks[block]) { 125 allocate(block); 126 } 127 memcpy(data, writtenblocks[block] + block_off, size); 128 pos += size; 129 tot += size; 130 } 131 132 return tot; 133 } 134 135 ssize_t 136 bdev_scatter(dev_t dev, u64_t pos, iovec_t *vec, int count, int flags) 137 { 138 int i, block; 139 size_t size, block_off; 140 ssize_t tot = 0; 141 assert(dev == MYDEV); 142 assert(curblocksize > 0); 143 assert(!(pos % curblocksize)); 144 for(i = 0; i < count; i++) { 145 char *data = (char *) vec[i].iov_addr; 146 block = pos / curblocksize; 147 block_off = (size_t)(pos % curblocksize); 148 size = vec[i].iov_size; 149 assert(size == PAGE_SIZE); 150 assert(block >= 0); 151 assert(block < MAXBLOCKS); 152 assert(block_off + size <= curblocksize); 153 if(!writtenblocks[block]) { 154 allocate(block); 155 } 156 memcpy(writtenblocks[block] + block_off, data, size); 157 pos += size; 158 tot += size; 159 } 160 161 return tot; 162 } 163 164 ssize_t 165 bdev_read(dev_t dev, u64_t pos, char *data, size_t count, int flags) 166 { 167 int block; 168 169 assert(dev == MYDEV); 170 assert(curblocksize > 0); 171 assert(!(pos % curblocksize)); 172 assert(count > 0); 173 assert(!(count % curblocksize)); 174 assert(count == PAGE_SIZE); 175 assert(curblocksize == PAGE_SIZE); 176 177 block = pos / curblocksize; 178 assert(block >= 0); 179 assert(block < MAXBLOCKS); 180 if(!writtenblocks[block]) { 181 allocate(block); 182 } 183 memcpy(data, writtenblocks[block], curblocksize); 184 return count; 185 } 186 187 /* Fake some libsys functions */ 188 189 __dead void 190 panic(const char *fmt, ...) 191 { 192 va_list va; 193 va_start(va, fmt); 194 vfprintf(stderr, fmt, va); 195 va_end(va); 196 197 exit(1); 198 } 199 200 int 201 vm_info_stats(struct vm_stats_info *vsi) 202 { 203 return ENOSYS; 204 } 205 206 void 207 util_stacktrace(void) 208 { 209 fprintf(stderr, "fake stacktrace\n"); 210 } 211 212 void *alloc_contig(size_t len, int flags, phys_bytes *phys) 213 { 214 return malloc(len); 215 } 216 217 int free_contig(void *addr, size_t len) 218 { 219 free(addr); 220 return 0; 221 } 222 223 u32_t sqrt_approx(u32_t v) 224 { 225 return (u32_t) sqrt(v); 226 } 227 228 int vm_set_cacheblock(void *block, dev_t dev, off_t dev_offset, 229 ino_t ino, off_t ino_offset, u32_t *flags, int blocksize, int setflags) 230 { 231 return ENOSYS; 232 } 233 234 void *vm_map_cacheblock(dev_t dev, off_t dev_offset, 235 ino_t ino, off_t ino_offset, u32_t *flags, int blocksize) 236 { 237 return MAP_FAILED; 238 } 239 240 int vm_forget_cacheblock(dev_t dev, off_t dev_offset, int blocksize) 241 { 242 return 0; 243 } 244 245 int vm_clear_cache(dev_t dev) 246 { 247 return 0; 248 } 249 250 int 251 main(int argc, char *argv[]) 252 { 253 size_t newblocksize; 254 int wss, cs, n = 0, p; 255 256 #define ITER 3 257 #define BLOCKS 200 258 259 start(72); 260 261 lmfs_setquiet(1); 262 263 /* Can the cache handle differently sized blocks? */ 264 265 for(p = 1; p <= 3; p++) { 266 /* Do not update curblocksize until the cache is flushed. */ 267 newblocksize = PAGE_SIZE*p; 268 lmfs_set_blocksize(newblocksize); 269 curblocksize = newblocksize; /* now it's safe to update */ 270 lmfs_buf_pool(BLOCKS); 271 if(dotest(curblocksize, BLOCKS, ITER)) e(n); 272 n++; 273 } 274 275 /* Can the cache handle various combinations of the working set 276 * being larger and smaller than the cache? 277 */ 278 for(wss = 2; wss <= 3; wss++) { 279 int wsblocks = 10*wss*wss*wss*wss*wss; 280 for(cs = wsblocks/4; cs <= wsblocks*3; cs *= 1.5) { 281 lmfs_set_blocksize(PAGE_SIZE); 282 curblocksize = PAGE_SIZE; /* same as above */ 283 lmfs_buf_pool(cs); 284 if(dotest(curblocksize, wsblocks, ITER)) e(n); 285 n++; 286 } 287 } 288 289 quit(); 290 291 return 0; 292 } 293 294