bfs.c revision 1.3 1 /* $NetBSD: bfs.c,v 1.3 2006/07/01 08:42:39 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by UCHIYAMA Yasushi.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40
41 __KERNEL_RCSID(0, "$NetBSD: bfs.c,v 1.3 2006/07/01 08:42:39 martin Exp $");
42 #define BFS_DEBUG
43
44 #include <sys/param.h>
45 #include <sys/kernel.h>
46 #include <sys/types.h>
47 #include <sys/systm.h>
48 #include <sys/errno.h>
49 #include <sys/malloc.h>
50 #include <sys/time.h>
51
52 #ifdef _KERNEL
53 MALLOC_DEFINE(M_BFS, "sysvbfs core", "sysvbfs internal structures");
54 #define __MALLOC(s, t, f) malloc(s, t, f)
55 #define __FREE(a, s, t) free(a, t)
56 #elif defined _STANDALONE
57 #include <lib/libsa/stand.h>
58 #include <lib/libkern/libkern.h>
59 #define __MALLOC(s, t, f) alloc(s)
60 #define __FREE(a, s, t) dealloc(a, s)
61 #else
62 #include "local.h"
63 #define __MALLOC(s, t, f) malloc(s)
64 #define __FREE(a, s, t) free(a)
65 #endif
66 #include <fs/sysvbfs/bfs.h>
67
68 #ifdef BFS_DEBUG
69 #define DPRINTF(on, fmt, args...) if (on) printf(fmt, ##args)
70 #else
71 #define DPRINTF(arg...) ((void)0)
72 #endif
73
74 #define ROUND_SECTOR(x) (((x) + 511) & ~511)
75 #define TRUNC_SECTOR(x) ((x) & ~511)
76
77 #define STATIC
78
79 STATIC int bfs_init_superblock(struct bfs *, int, size_t *);
80 STATIC int bfs_init_inode(struct bfs *, uint8_t *, size_t *);
81 STATIC int bfs_init_dirent(struct bfs *, uint8_t *);
82
83 /* super block ops. */
84 STATIC boolean_t bfs_superblock_valid(const struct bfs_super_block *);
85 STATIC boolean_t bfs_writeback_dirent(const struct bfs *, struct bfs_dirent *,
86 boolean_t);
87 STATIC boolean_t bfs_writeback_inode(const struct bfs *, struct bfs_inode *);
88
89 int
90 bfs_init2(struct bfs **bfsp, int bfs_sector, struct sector_io_ops *io,
91 boolean_t debug)
92 {
93 struct bfs *bfs;
94 size_t memsize;
95 uint8_t *p;
96 int err;
97
98 /* 1. */
99 DPRINTF(debug, "bfs sector = %d\n", bfs_sector);
100 if ((bfs = (void *)__MALLOC(sizeof(struct bfs), M_BFS, M_NOWAIT)) == 0)
101 return ENOMEM;
102 memset(bfs, 0, sizeof *bfs);
103 bfs->io = io;
104 bfs->debug = debug;
105
106 /* 2. */
107 if ((err = bfs_init_superblock(bfs, bfs_sector, &memsize)) != 0) {
108 bfs_fini(bfs);
109 return err;
110 }
111 DPRINTF(debug, "bfs super block + inode area = %d\n", memsize);
112 bfs->super_block_size = memsize;
113 if ((p = (void *)__MALLOC(memsize, M_BFS, M_NOWAIT)) == 0) {
114 bfs_fini(bfs);
115 return ENOMEM;
116 }
117 /* 3. */
118 if ((err = bfs_init_inode(bfs, p, &memsize)) != 0) {
119 bfs_fini(bfs);
120 return err;
121 }
122 DPRINTF(debug, "bfs dirent area = %d\n", memsize);
123 bfs->dirent_size = memsize;
124 if ((p = (void *)__MALLOC(memsize, M_BFS, M_NOWAIT)) == 0) {
125 bfs_fini(bfs);
126 return ENOMEM;
127 }
128 /* 4. */
129 if ((err = bfs_init_dirent(bfs, p)) != 0) {
130 bfs_fini(bfs);
131 return err;
132 }
133
134 #ifdef BFS_DEBUG
135 bfs_dump(bfs);
136 #endif
137 *bfsp = bfs;
138
139 return 0;
140 }
141
142 void
143 bfs_fini(struct bfs *bfs)
144 {
145
146 if (bfs == 0)
147 return;
148 if (bfs->super_block)
149 __FREE(bfs->super_block, bfs->super_block_size, M_BFS);
150 if (bfs->dirent)
151 __FREE(bfs->dirent, bfs->dirent_size, M_BFS);
152 __FREE(bfs, sizeof(struct bfs), M_BFS);
153 }
154
155 STATIC int
156 bfs_init_superblock(struct bfs *bfs, int bfs_sector, size_t *required_memory)
157 {
158 struct bfs_super_block super;
159
160 bfs->start_sector = bfs_sector;
161
162 /* Read super block */
163 if (!bfs->io->read(bfs->io, (uint8_t *)&super, bfs_sector))
164 return EIO;
165
166 if (!bfs_superblock_valid(&super))
167 return EINVAL;
168
169 /* i-node table size */
170 bfs->data_start = super.header.data_start_byte;
171 bfs->data_end = super.header.data_end_byte;
172
173 bfs->max_inode = (bfs->data_start - sizeof(struct bfs_super_block)) /
174 sizeof(struct bfs_inode);
175
176 *required_memory = ROUND_SECTOR(bfs->data_start);
177
178 return 0;
179 }
180
181 STATIC int
182 bfs_init_inode(struct bfs *bfs, uint8_t *p, size_t *required_memory)
183 {
184 struct bfs_inode *inode, *root_inode;
185 int i;
186
187 if (!bfs->io->read_n(bfs->io, p, bfs->start_sector,
188 bfs->data_start >> DEV_BSHIFT))
189 return EIO;
190
191 bfs->super_block = (struct bfs_super_block *)p;
192 bfs->inode = (struct bfs_inode *)(p + sizeof(struct bfs_super_block));
193 p += bfs->data_start;
194
195 bfs->n_inode = 0;
196 inode = bfs->inode;
197 root_inode = 0;
198 for (i = 0; i < bfs->max_inode; i++, inode++) {
199 if (inode->number != 0) {
200 bfs->n_inode++;
201 if (inode->number == BFS_ROOT_INODE)
202 root_inode = inode;
203 }
204 }
205 DPRINTF(bfs->debug, "inode: %d/%d\n", bfs->n_inode, bfs->max_inode);
206
207 if (root_inode == 0) {
208 DPRINTF(bfs->debug, "no root directory.\n");
209 return ENOTDIR;
210 }
211 /* dirent table size */
212 DPRINTF(bfs->debug, "root inode: %d-%d\n", root_inode->start_sector,
213 root_inode->end_sector);
214 bfs->root_inode = root_inode;
215
216 *required_memory = (root_inode->end_sector -
217 root_inode->start_sector + 1) << DEV_BSHIFT;
218
219 return 0;
220 }
221
222 STATIC int
223 bfs_init_dirent(struct bfs *bfs, uint8_t *p)
224 {
225 struct bfs_dirent *file;
226 struct bfs_inode *inode = bfs->root_inode;
227 int i, n;
228
229 n = inode->end_sector - inode->start_sector + 1;
230
231 if (!bfs->io->read_n(bfs->io, p,
232 bfs->start_sector + inode->start_sector, n))
233 return EIO;
234
235 bfs->dirent = (struct bfs_dirent *)p;
236 bfs->max_dirent = (n << DEV_BSHIFT) / sizeof(struct bfs_dirent);
237
238 file = bfs->dirent;
239 bfs->n_dirent = 0;
240 for (i = 0; i < bfs->max_dirent; i++, file++)
241 if (file->inode != 0)
242 bfs->n_dirent++;
243
244 DPRINTF(bfs->debug, "dirent: %d/%d\n", bfs->n_dirent, bfs->max_dirent);
245
246 return 0;
247 }
248
249 int
250 bfs_file_read(const struct bfs *bfs, const char *fname, void *buf, size_t bufsz,
251 size_t *read_size)
252 {
253 int start, end, n;
254 size_t sz;
255 uint8_t tmpbuf[DEV_BSIZE];
256 uint8_t *p;
257
258 if (!bfs_file_lookup(bfs, fname, &start, &end, &sz))
259 return ENOENT;
260
261 if (sz > bufsz)
262 return ENOMEM;
263
264 p = buf;
265 n = end - start;
266 bfs->io->read_n(bfs->io, p, start, n);
267 /* last sector */
268 n *= DEV_BSIZE;
269 bfs->io->read(bfs->io, tmpbuf, end);
270 memcpy(p + n, tmpbuf, sz - n);
271
272 if (read_size)
273 *read_size = sz;
274
275 return 0;
276 }
277
278 int
279 bfs_file_write(struct bfs *bfs, const char *fname, void *buf,
280 size_t bufsz)
281 {
282 struct bfs_fileattr attr;
283 struct bfs_dirent *dirent;
284 int8_t name[BFS_FILENAME_MAXLEN];
285 int err;
286 #ifdef _KERNEL
287 struct timespec ts;
288 #endif
289
290 strncpy(name, fname, BFS_FILENAME_MAXLEN);
291
292 if (bfs_dirent_lookup_by_name(bfs, name, &dirent)) {
293 struct bfs_inode *inode;
294 if (!bfs_inode_lookup(bfs, dirent->inode, &inode)) {
295 DPRINTF(bfs->debug, "%s: dirent found, but inode "
296 "not found. inconsistent filesystem.\n",
297 __FUNCTION__);
298 return ENOENT;
299 }
300 attr = inode->attr; /* copy old attribute */
301 bfs_file_delete(bfs, name);
302 if ((err = bfs_file_create(bfs, name, buf, bufsz, &attr)) != 0)
303 return err;
304 } else {
305 memset(&attr, 0xff, sizeof attr); /* Set VNOVAL all */
306 #ifdef _KERNEL
307 getnanotime(&ts);
308 attr.atime = ts.tv_sec;
309 attr.ctime = ts.tv_sec;
310 attr.mtime = ts.tv_sec;
311 #endif
312 if ((err = bfs_file_create(bfs, name, buf, bufsz, &attr)) != 0)
313 return err;
314 }
315
316 return 0;
317 }
318
319 int
320 bfs_file_delete(struct bfs *bfs, const char *fname)
321 {
322 struct bfs_inode *inode;
323 struct bfs_dirent *dirent;
324
325 if (!bfs_dirent_lookup_by_name(bfs, fname, &dirent))
326 return ENOENT;
327
328 if (!bfs_inode_lookup(bfs, dirent->inode, &inode))
329 return ENOENT;
330
331 memset(dirent, 0, sizeof *dirent);
332 memset(inode, 0, sizeof *inode);
333 bfs->n_inode--;
334 bfs->n_dirent--;
335
336 bfs_writeback_dirent(bfs, dirent, FALSE);
337 bfs_writeback_inode(bfs, inode);
338 DPRINTF(bfs->debug, "%s: \"%s\" deleted.\n", __FUNCTION__, fname);
339
340 return 0;
341 }
342
343 int
344 bfs_file_rename(struct bfs *bfs, const char *from_name, const char *to_name)
345 {
346 struct bfs_dirent *dirent;
347 int err = 0;
348
349 if (strlen(to_name) > BFS_FILENAME_MAXLEN) {
350 err = ENAMETOOLONG;
351 goto out;
352 }
353 if (!bfs_dirent_lookup_by_name(bfs, from_name, &dirent)) {
354 err = ENOENT;
355 goto out;
356 }
357
358 bfs_file_delete(bfs, to_name);
359 strncpy(dirent->name, to_name, BFS_FILENAME_MAXLEN);
360 bfs_writeback_dirent(bfs, dirent, FALSE);
361
362 out:
363 DPRINTF(bfs->debug, "%s: \"%s\" -> \"%s\" error=%d.\n", __FUNCTION__,
364 from_name, to_name, err);
365
366 return err;
367 }
368
369 int
370 bfs_file_create(struct bfs *bfs, const char *fname, void *buf, size_t bufsz,
371 const struct bfs_fileattr *attr)
372 {
373 struct bfs_inode *inode;
374 struct bfs_dirent *file;
375 int i, j, n, start;
376 uint8_t *p, tmpbuf[DEV_BSIZE];
377 int err;
378
379 /* Find free i-node and data block */
380 if ((err = bfs_inode_alloc(bfs, &inode, &j, &start)) != 0)
381 return err;
382
383 /* File size (unit block) */
384 n = (ROUND_SECTOR(bufsz) >> DEV_BSHIFT) - 1;
385 if (n < 0) /* bufsz == 0 */
386 n = 0;
387
388 if ((start + n) * DEV_BSIZE >= bfs->data_end) {
389 DPRINTF(bfs->debug, "disk full.\n");
390 return ENOSPC;
391 }
392
393 /* Find free dirent */
394 for (file = bfs->dirent, i = 0; i < bfs->max_dirent; i++, file++)
395 if (file->inode == 0)
396 break;
397 if (i == bfs->max_dirent) {
398 DPRINTF(bfs->debug, "dirent full.\n");
399 return ENOSPC;
400 }
401
402 /* i-node */
403 memset(inode, 0, sizeof *inode);
404 inode->number = j;
405 inode->start_sector = start;
406 inode->end_sector = start + n;
407 inode->eof_offset_byte = start * DEV_BSIZE + bufsz - 1;
408 /* i-node attribute */
409 inode->attr.type = 1;
410 inode->attr.mode = 0;
411 inode->attr.nlink = 1;
412 bfs_inode_set_attr(bfs, inode, attr);
413
414 /* Dirent */
415 memset(file, 0, sizeof *file);
416 file->inode = inode->number;
417 strncpy(file->name, fname, BFS_FILENAME_MAXLEN);
418
419 DPRINTF(bfs->debug, "%s: start %d end %d\n", __FUNCTION__,
420 inode->start_sector, inode->end_sector);
421
422 if (buf != 0) {
423 p = (uint8_t *)buf;
424 /* Data block */
425 n = 0;
426 for (i = inode->start_sector; i < inode->end_sector; i++) {
427 if (!bfs->io->write(bfs->io, p, bfs->start_sector + i))
428 return EIO;
429 p += DEV_BSIZE;
430 n += DEV_BSIZE;
431 }
432 /* last sector */
433 memset(tmpbuf, 0, DEV_BSIZE);
434 memcpy(tmpbuf, p, bufsz - n);
435 if (!bfs->io->write(bfs->io, tmpbuf, bfs->start_sector + i))
436 return EIO;
437 }
438 /* Update */
439 bfs->n_inode++;
440 bfs->n_dirent++;
441 bfs_writeback_dirent(bfs, file, TRUE);
442 bfs_writeback_inode(bfs, inode);
443
444 return 0;
445 }
446
447 STATIC boolean_t
448 bfs_writeback_dirent(const struct bfs *bfs, struct bfs_dirent *dir,
449 boolean_t create)
450 {
451 struct bfs_dirent *dir_base = bfs->dirent;
452 struct bfs_inode *root_inode = bfs->root_inode;
453 uint32_t eof;
454 int i;
455
456 i = ((dir - dir_base) * sizeof *dir) >> DEV_BSHIFT;
457
458 eof = (uint32_t)(dir + 1) - 1;
459 eof = eof - (uint32_t)dir_base +
460 (root_inode->start_sector << DEV_BSHIFT);
461
462 /* update root directory inode */
463 #if 0
464 printf("eof new=%d old=%d\n", eof, root_inode->eof_offset_byte);
465 #endif
466 if (create) {
467 if (eof > root_inode->eof_offset_byte) {
468 root_inode->eof_offset_byte = eof;
469 }
470 } else {
471 /* delete the last entry */
472 if (eof == root_inode->eof_offset_byte) {
473 root_inode->eof_offset_byte = eof - sizeof *dir;
474 }
475 }
476 bfs_writeback_inode(bfs, root_inode);
477
478 /* update dirent */
479 return bfs->io->write(bfs->io, (uint8_t *)dir_base + (i << DEV_BSHIFT),
480 bfs->start_sector + bfs->root_inode->start_sector + i);
481 }
482
483 STATIC boolean_t
484 bfs_writeback_inode(const struct bfs *bfs, struct bfs_inode *inode)
485 {
486 struct bfs_inode *inode_base = bfs->inode;
487 int i;
488
489 i = ((inode - inode_base) * sizeof *inode) >> DEV_BSHIFT;
490
491 return bfs->io->write(bfs->io,
492 (uint8_t *)inode_base + (i << DEV_BSHIFT),
493 bfs->start_sector + 1/*super block*/ + i);
494 }
495
496 boolean_t
497 bfs_file_lookup(const struct bfs *bfs, const char *fname, int *start, int *end,
498 size_t *size)
499 {
500 struct bfs_inode *inode;
501 struct bfs_dirent *dirent;
502
503 if (!bfs_dirent_lookup_by_name(bfs, fname, &dirent))
504 return FALSE;
505 if (!bfs_inode_lookup(bfs, dirent->inode, &inode))
506 return FALSE;
507
508 if (start)
509 *start = inode->start_sector + bfs->start_sector;
510 if (end)
511 *end = inode->end_sector + bfs->start_sector;
512 if (size)
513 *size = bfs_file_size(inode);
514
515 DPRINTF(bfs->debug, "%s: %d + %d -> %d (%d)\n",
516 fname, bfs->start_sector, inode->start_sector,
517 inode->end_sector, *size);
518
519 return TRUE;
520 }
521
522 boolean_t
523 bfs_dirent_lookup_by_inode(const struct bfs *bfs, int inode,
524 struct bfs_dirent **dirent)
525 {
526 struct bfs_dirent *file;
527 int i;
528
529 for (file = bfs->dirent, i = 0; i < bfs->max_dirent; i++, file++)
530 if (file->inode == inode)
531 break;
532
533 if (i == bfs->max_dirent)
534 return FALSE;
535
536 *dirent = file;
537
538 return TRUE;
539 }
540
541 boolean_t
542 bfs_dirent_lookup_by_name(const struct bfs *bfs, const char *fname,
543 struct bfs_dirent **dirent)
544 {
545 struct bfs_dirent *file;
546 int i;
547
548 for (file = bfs->dirent, i = 0; i < bfs->max_dirent; i++, file++)
549 if ((file->inode != 0) &&
550 (strncmp(file->name, fname, BFS_FILENAME_MAXLEN) ==0))
551 break;
552
553 if (i == bfs->max_dirent)
554 return FALSE;
555
556 *dirent = file;
557
558 return TRUE;
559 }
560
561 boolean_t
562 bfs_inode_lookup(const struct bfs *bfs, ino_t n, struct bfs_inode **iinode)
563 {
564 struct bfs_inode *inode;
565 int i;
566
567 for (inode = bfs->inode, i = 0; i < bfs->max_inode; i++, inode++)
568 if (inode->number == n)
569 break;
570
571 if (i == bfs->max_inode)
572 return FALSE;
573
574 *iinode = inode;
575
576 return TRUE;
577 }
578
579 size_t
580 bfs_file_size(const struct bfs_inode *inode)
581 {
582
583 return inode->eof_offset_byte - inode->start_sector * DEV_BSIZE + 1;
584 }
585
586 STATIC int
587 bfs_inode_alloc(const struct bfs *bfs, struct bfs_inode **free_inode,
588 int *free_inode_number, int *free_block)
589 {
590 struct bfs_inode *jnode, *inode;
591 int i, j, start;
592
593 j = start = 0;
594 inode = bfs->inode;
595 jnode = 0;
596
597 for (i = BFS_ROOT_INODE; i < bfs->max_inode; i++, inode++) {
598 /* Steal i-node # */
599 if (j == 0)
600 j = i;
601
602 /* Get free i-node */
603 if (jnode == 0 && (inode->number == 0))
604 jnode = inode;
605
606 /* Get free i-node # and data block */
607 if (inode->number != 0) {
608 if (inode->end_sector > start)
609 start = inode->end_sector;
610 if (inode->number == j)
611 j = 0; /* conflict */
612 }
613 }
614 start++;
615
616 if (jnode == 0) {
617 DPRINTF(bfs->debug, "i-node full.\n");
618 return ENOSPC;
619 }
620
621 if (start * DEV_BSIZE >= bfs->data_end) {
622 DPRINTF(bfs->debug, "data block full.\n");
623 /* compaction here ? */
624 return ENOSPC;
625 }
626 if (free_inode)
627 *free_inode = jnode;
628 if (free_inode_number)
629 *free_inode_number = j;
630 if (free_block)
631 *free_block = start;
632
633 return 0;
634 }
635
636 void
637 bfs_inode_set_attr(const struct bfs *bfs, struct bfs_inode *inode,
638 const struct bfs_fileattr *from)
639 {
640 struct bfs_fileattr *to = &inode->attr;
641
642 if (from != NULL) {
643 if (from->uid != (uid_t)-1)
644 to->uid = from->uid;
645 if (from->gid != (uid_t)-1)
646 to->gid = from->gid;
647 if (from->mode != (mode_t)-1)
648 to->mode = from->mode;
649 if (from->atime != -1)
650 to->atime = from->atime;
651 if (from->ctime != -1)
652 to->ctime = from->ctime;
653 if (from->mtime != -1)
654 to->mtime = from->mtime;
655 }
656 bfs_writeback_inode(bfs, inode);
657 }
658
659 STATIC boolean_t
660 bfs_superblock_valid(const struct bfs_super_block *super)
661 {
662
663 return super->header.magic == BFS_MAGIC;
664 }
665
666 boolean_t
667 bfs_dump(const struct bfs *bfs)
668 {
669 const struct bfs_super_block_header *h;
670 const struct bfs_compaction *compaction;
671 const struct bfs_inode *inode;
672 struct bfs_dirent *file;
673 int i, j, s, e, bytes;
674
675 if (!bfs_superblock_valid(bfs->super_block)) {
676 DPRINTF(bfs->debug, "invalid bfs super block.\n");
677 return FALSE;
678 }
679 h = &bfs->super_block->header;
680 compaction = &bfs->super_block->compaction;
681
682 DPRINTF(bfs->debug, "super block %dbyte, inode %dbyte, dirent %dbyte\n",
683 sizeof *bfs->super_block, sizeof *inode, sizeof *file);
684
685 DPRINTF(bfs->debug, "magic=%x\n", h->magic);
686 DPRINTF(bfs->debug, "data_start_byte=0x%x\n", h->data_start_byte);
687 DPRINTF(bfs->debug, "data_end_byte=0x%x\n", h->data_end_byte);
688 DPRINTF(bfs->debug, "from=%#x\n", compaction->from);
689 DPRINTF(bfs->debug, "to=%#x\n", compaction->to);
690 DPRINTF(bfs->debug, "from_backup=%#x\n", compaction->from_backup);
691 DPRINTF(bfs->debug, "to_backup=%#x\n", compaction->to_backup);
692 DPRINTF(bfs->debug, "fsname=%s\n", bfs->super_block->fsname);
693 DPRINTF(bfs->debug, "volume=%s\n", bfs->super_block->volume);
694
695 /* inode list */
696 DPRINTF(bfs->debug, "[inode index list]\n");
697 for (inode = bfs->inode, i = j = 0; i < bfs->max_inode; inode++, i++) {
698 if (inode->number != 0) {
699 const struct bfs_fileattr *attr = &inode->attr;
700 DPRINTF(bfs->debug, "%3d %8d %8d %8d (%d) ",
701 inode->number,
702 inode->eof_offset_byte -
703 (inode->start_sector * DEV_BSIZE) + 1,/* file size*/
704 inode->start_sector,
705 inode->end_sector, i);
706
707 DPRINTF(bfs->debug, "%d %d %d %d %d %08x %08x %08x\n",
708 attr->type, attr->mode, attr->uid, attr->gid,
709 attr->nlink, attr->atime, attr->mtime, attr->ctime);
710 j++;
711 }
712 }
713 if (j != bfs->n_inode) {
714 DPRINTF(bfs->debug, "inconsistent cached data. (i-node)\n");
715 return FALSE;
716 }
717 DPRINTF(bfs->debug, "total %d i-node.\n", j);
718
719 /* file list */
720 DPRINTF(bfs->debug, "[dirent index list]\n");
721 DPRINTF(bfs->debug, "%d file entries.\n", bfs->max_dirent);
722 file = bfs->dirent;
723 for (i = j = 0; i < bfs->max_dirent; i++, file++) {
724 if (file->inode != 0) {
725 if (bfs_file_lookup(bfs, file->name, &s, &e, &bytes))
726 DPRINTF(bfs->debug, "%3d %14s %8d %8d %8d\n",
727 file->inode, file->name, s, e, bytes);
728 j++;
729 }
730 }
731 if (j != bfs->n_dirent) {
732 DPRINTF(bfs->debug, "inconsistent cached data. (dirent)\n");
733 return FALSE;
734 }
735 DPRINTF(bfs->debug, "%d files.\n", j);
736
737 return TRUE;
738 }
739