xref: /minix3/minix/tests/test72.c (revision 6c46a77d9509a6aefda1522eee2103e194ced4b3)
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
dowriteblock(int b,int blocksize,u32_t seed,char * data)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
readblock(int b,int blocksize,u32_t seed,char * data)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 
testend(void)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 
allocate(int b)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
bdev_gather(dev_t dev,u64_t pos,iovec_t * vec,int count,int flags)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
bdev_scatter(dev_t dev,u64_t pos,iovec_t * vec,int count,int flags)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
bdev_read(dev_t dev,u64_t pos,char * data,size_t count,int flags)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
panic(const char * fmt,...)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
vm_info_stats(struct vm_stats_info * vsi)201 vm_info_stats(struct vm_stats_info *vsi)
202 {
203 	return ENOSYS;
204 }
205 
206 void
util_stacktrace(void)207 util_stacktrace(void)
208 {
209 	fprintf(stderr, "fake stacktrace\n");
210 }
211 
alloc_contig(size_t len,int flags,phys_bytes * phys)212 void *alloc_contig(size_t len, int flags, phys_bytes *phys)
213 {
214 	return malloc(len);
215 }
216 
free_contig(void * addr,size_t len)217 int free_contig(void *addr, size_t len)
218 {
219 	free(addr);
220 	return 0;
221 }
222 
sqrt_approx(u32_t v)223 u32_t sqrt_approx(u32_t v)
224 {
225 	return (u32_t) sqrt(v);
226 }
227 
vm_set_cacheblock(void * block,dev_t dev,off_t dev_offset,ino_t ino,off_t ino_offset,u32_t * flags,int blocksize,int setflags)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 
vm_map_cacheblock(dev_t dev,off_t dev_offset,ino_t ino,off_t ino_offset,u32_t * flags,int blocksize)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 
vm_forget_cacheblock(dev_t dev,off_t dev_offset,int blocksize)240 int vm_forget_cacheblock(dev_t dev, off_t dev_offset, int blocksize)
241 {
242 	return 0;
243 }
244 
vm_clear_cache(dev_t dev)245 int vm_clear_cache(dev_t dev)
246 {
247 	return 0;
248 }
249 
250 int
main(int argc,char * argv[])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