10 #define BLOCK_SIZE 0x200
13 #define INDIRECT_SIZE 0x100
14 #define INDIRECT_SHIFT 8
16 #define TRANSFER_SIZE 821 // a prime number somewhat near the block size
18 bool hash_init(int file, struct cinode *inode, int base, int limit) {
20 for (int ptr = base; (count = limit - ptr) > 0; ptr += count) {
21 if (count > TRANSFER_SIZE)
22 count = TRANSFER_SIZE;
24 uint8_t buf[TRANSFER_SIZE];
25 for (int i = 0; i < count; ++i)
26 buf[i] = (uint8_t)(file * 17 + (i + ptr) * 29);
28 udata.u_base = (char *)buf;
29 udata.u_count = count;
32 if (writei(inode) < count || udata.u_error)
35 rassert((int)inode->c_node.i_size == limit);
39 void hash_verify(int file, struct cinode *inode, int base, int limit) {
41 for (int ptr = base; (count = limit - ptr) > 0; ptr += count) {
42 if (count > TRANSFER_SIZE)
43 count = TRANSFER_SIZE;
45 uint8_t buf[TRANSFER_SIZE];
46 udata.u_base = (char *)buf;
47 udata.u_count = count;
50 rassert(readi(inode) == count && udata.u_error == 0);
52 for (int i = 0; i < count; ++i)
53 rassert(buf[i] == (uint8_t)(file * 17 + (i + ptr) * 29));
57 int main(int argc, char **argv) {
59 printf("usage: %s fs_path n_files\n", argv[0]);
62 char *fs_path = argv[1];
63 int n_files = atoi(argv[2]);
67 printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
69 struct cinode **files = malloc(n_files * sizeof(struct cinode *));
71 memset(files, 0, n_files * sizeof(struct cinode *));
74 //printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
76 switch (scanf("%s", buf)) {
84 if (strcmp(buf, "alloc") == 0) {
86 rassert(scanf("%d %d %s", &file, &size, buf) == 3);
87 rassert(file >= 0 && file < n_files);
90 if (strcmp(buf, "false") == 0)
92 else if (strcmp(buf, "true") == 0)
100 success ? "true" : "false"
102 rassert(files[file] == NULL);
104 files[file] = i_open(0, 0);
105 if (files[file] == NULL)
108 /* This does not implement BSD style "sticky" groups */
109 files[file]->c_node.i_uid = udata.u_euid;
110 files[file]->c_node.i_gid = udata.u_egid;
112 files[file]->c_node.i_mode = F_REG; /* For the time being */
113 files[file]->c_node.i_nlink = 0;
114 files[file]->c_node.i_size = 0;
115 for (int i = 0; i < 20; ++i)
116 files[file]->c_node.i_addr[i] = 0;
117 wr_inode(files[file]);
119 if (!hash_init(file, files[file], 0, size)) {
121 i_deref(files[file]);
131 result ? "succeeded, should fail" : "failed, should succeed"
133 if (files[file] && !success) {
134 printf("... undo\n");
135 i_deref(files[file]);
139 else if (strcmp(buf, "realloc") == 0) {
140 int file, old_size, size;
141 rassert(scanf("%d %d %d %s", &file, &old_size, &size, buf) == 4);
142 rassert(file >= 0 && file < n_files);
143 rassert(old_size >= 0);
146 if (strcmp(buf, "false") == 0)
148 else if (strcmp(buf, "true") == 0)
153 "realloc %d %d %d %s\n",
157 success ? "true" : "false"
159 if (files[file] == NULL)
160 printf("... not allocated, ignore\n");
162 int actual_old_size = (int)files[file]->c_node.i_size;
163 if (actual_old_size != old_size) {
165 "... old size %d, should be %d\n",
169 rassert(actual_old_size <= old_size);
172 if (size < actual_old_size) {
173 hash_verify(file, files[file], size, actual_old_size);
174 udata.u_offset = size;
175 f_trunc(files[file]);
178 else if (!hash_init(file, files[file], actual_old_size, size)) {
179 udata.u_offset = actual_old_size;
180 f_trunc(files[file]);
189 result ? "succeeded, should fail" : "failed, should succeed"
191 if (result && !success) {
192 printf("... undo\n");
193 udata.u_offset = actual_old_size;
194 f_trunc(files[file]);
198 else if (strcmp(buf, "free") == 0) {
200 rassert(scanf("%d %d", &file, &old_size) == 2);
201 rassert(file >= 0 && file < n_files);
202 rassert(old_size >= 0);
208 if (files[file] == NULL)
209 printf("... not allocated, ignore\n");
211 int actual_old_size = (int)files[file]->c_node.i_size;
212 if (actual_old_size != old_size) {
214 "... old size %d, should be %d\n",
218 rassert(actual_old_size <= old_size);
220 hash_verify(file, files[file], 0, actual_old_size);
221 i_deref(files[file]);
231 printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
233 printf("final state:\n");
234 for (int i = 0; i < n_files; ++i) {
235 if (files[i] == NULL)
236 printf("file %d: not allocated\n", i);
238 int size = (int)files[i]->c_node.i_size;
239 printf("file %d: size %d\n", i, size);
240 hash_verify(i, files[i], 0, size);
245 printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);