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