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