1 /* $NetBSD: inode.c,v 1.49 2004/10/08 17:33:52 dbj Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1986, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95"; 36 #else 37 __RCSID("$NetBSD: inode.c,v 1.49 2004/10/08 17:33:52 dbj Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include <sys/param.h> 42 #include <sys/time.h> 43 44 #include <ufs/ufs/dinode.h> 45 #include <ufs/ufs/dir.h> 46 #include <ufs/ffs/fs.h> 47 #include <ufs/ffs/ffs_extern.h> 48 #include <ufs/ufs/ufs_bswap.h> 49 50 #ifndef SMALL 51 #include <err.h> 52 #include <pwd.h> 53 #endif 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <string.h> 57 #include <time.h> 58 59 #include "fsck.h" 60 #include "fsutil.h" 61 #include "extern.h" 62 63 static ino_t startinum; 64 65 static int iblock __P((struct inodesc *, long, u_int64_t)); 66 static void swap_dinode1(union dinode *, int); 67 static void swap_dinode2(union dinode *, int); 68 69 int 70 ckinode(dp, idesc) 71 union dinode *dp; 72 struct inodesc *idesc; 73 { 74 int ret, offset, i; 75 union dinode dino; 76 u_int64_t sizepb; 77 int64_t remsize; 78 daddr_t ndb; 79 mode_t mode; 80 char pathbuf[MAXPATHLEN + 1]; 81 82 if (idesc->id_fix != IGNORE) 83 idesc->id_fix = DONTKNOW; 84 idesc->id_entryno = 0; 85 idesc->id_filesize = iswap64(DIP(dp, size)); 86 mode = iswap16(DIP(dp, mode)) & IFMT; 87 if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 88 (idesc->id_filesize < sblock->fs_maxsymlinklen || 89 (isappleufs && (idesc->id_filesize < APPLEUFS_MAXSYMLINKLEN)) || 90 (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0)))) 91 return (KEEPON); 92 if (is_ufs2) 93 dino.dp2 = dp->dp2; 94 else 95 dino.dp1 = dp->dp1; 96 ndb = howmany(iswap64(DIP(&dino, size)), sblock->fs_bsize); 97 for (i = 0; i < NDADDR; i++) { 98 if (--ndb == 0 && 99 (offset = blkoff(sblock, iswap64(DIP(&dino, size)))) != 0) 100 idesc->id_numfrags = 101 numfrags(sblock, fragroundup(sblock, offset)); 102 else 103 idesc->id_numfrags = sblock->fs_frag; 104 if (DIP(&dino, db[i]) == 0) { 105 if (idesc->id_type == DATA && ndb >= 0) { 106 /* An empty block in a directory XXX */ 107 markclean = 0; 108 getpathname(pathbuf, sizeof(pathbuf), 109 idesc->id_number, idesc->id_number); 110 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS I", 111 pathbuf); 112 abort(); 113 if (reply("ADJUST LENGTH") == 1) { 114 dp = ginode(idesc->id_number); 115 DIP(dp, size) = iswap64(i * 116 sblock->fs_bsize); 117 printf( 118 "YOU MUST RERUN FSCK AFTERWARDS\n"); 119 rerun = 1; 120 inodirty(); 121 } 122 } 123 continue; 124 } 125 if (is_ufs2) 126 idesc->id_blkno = iswap64(dino.dp2.di_db[i]); 127 else 128 idesc->id_blkno = iswap32(dino.dp1.di_db[i]); 129 if (idesc->id_type != DATA) 130 ret = (*idesc->id_func)(idesc); 131 else 132 ret = dirscan(idesc); 133 if (ret & STOP) 134 return (ret); 135 } 136 idesc->id_numfrags = sblock->fs_frag; 137 remsize = iswap64(DIP(&dino, size)) - sblock->fs_bsize * NDADDR; 138 sizepb = sblock->fs_bsize; 139 for (i = 0; i < NIADDR; i++) { 140 if (DIP(&dino, ib[i])) { 141 if (is_ufs2) 142 idesc->id_blkno = iswap64(dino.dp2.di_ib[i]); 143 else 144 idesc->id_blkno = iswap32(dino.dp1.di_ib[i]); 145 ret = iblock(idesc, i + 1, remsize); 146 if (ret & STOP) 147 return (ret); 148 } else { 149 if (idesc->id_type == DATA && remsize > 0) { 150 /* An empty block in a directory XXX */ 151 markclean = 0; 152 getpathname(pathbuf, sizeof(pathbuf), 153 idesc->id_number, idesc->id_number); 154 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 155 pathbuf); 156 if (reply("ADJUST LENGTH") == 1) { 157 dp = ginode(idesc->id_number); 158 DIP(dp, size) = 159 iswap64(iswap64(DIP(dp, size)) 160 - remsize); 161 remsize = 0; 162 printf( 163 "YOU MUST RERUN FSCK AFTERWARDS\n"); 164 rerun = 1; 165 inodirty(); 166 break; 167 } 168 } 169 } 170 sizepb *= NINDIR(sblock); 171 remsize -= sizepb; 172 } 173 return (KEEPON); 174 } 175 176 static int 177 iblock(idesc, ilevel, isize) 178 struct inodesc *idesc; 179 long ilevel; 180 u_int64_t isize; 181 { 182 struct bufarea *bp; 183 int i, n, (*func) __P((struct inodesc *)), nif; 184 u_int64_t sizepb; 185 char buf[BUFSIZ]; 186 char pathbuf[MAXPATHLEN + 1]; 187 union dinode *dp; 188 189 if (idesc->id_type != DATA) { 190 func = idesc->id_func; 191 if (((n = (*func)(idesc)) & KEEPON) == 0) 192 return (n); 193 } else 194 func = dirscan; 195 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 196 return (SKIP); 197 bp = getdatablk(idesc->id_blkno, sblock->fs_bsize); 198 ilevel--; 199 for (sizepb = sblock->fs_bsize, i = 0; i < ilevel; i++) 200 sizepb *= NINDIR(sblock); 201 if (howmany(isize, sizepb) > NINDIR(sblock)) 202 nif = NINDIR(sblock); 203 else 204 nif = howmany(isize, sizepb); 205 if (do_blkswap) { /* swap byte order of the whole blk */ 206 if (is_ufs2) { 207 for (i = 0; i < nif; i++) 208 bp->b_un.b_indir2[i] = 209 bswap64(bp->b_un.b_indir2[i]); 210 } else { 211 for (i = 0; i < nif; i++) 212 bp->b_un.b_indir1[i] = 213 bswap32(bp->b_un.b_indir1[i]); 214 } 215 dirty(bp); 216 flush(fswritefd, bp); 217 } 218 if (idesc->id_func == pass1check && nif < NINDIR(sblock)) { 219 for (i = nif; i < NINDIR(sblock); i++) { 220 if (IBLK(bp, i) == 0) 221 continue; 222 (void)snprintf(buf, sizeof(buf), 223 "PARTIALLY TRUNCATED INODE I=%u", idesc->id_number); 224 if (dofix(idesc, buf)) { 225 IBLK(bp, i) = 0; 226 dirty(bp); 227 } else 228 markclean= 0; 229 } 230 flush(fswritefd, bp); 231 } 232 for (i = 0; i < nif; i++) { 233 if (IBLK(bp, i)) { 234 if (is_ufs2) 235 idesc->id_blkno = iswap64(bp->b_un.b_indir2[i]); 236 else 237 idesc->id_blkno = iswap32(bp->b_un.b_indir1[i]); 238 if (ilevel == 0) 239 n = (*func)(idesc); 240 else 241 n = iblock(idesc, ilevel, isize); 242 if (n & STOP) { 243 bp->b_flags &= ~B_INUSE; 244 return (n); 245 } 246 } else { 247 if (idesc->id_type == DATA && isize > 0) { 248 /* An empty block in a directory XXX */ 249 markclean= 0; 250 getpathname(pathbuf, sizeof(pathbuf), 251 idesc->id_number, idesc->id_number); 252 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 253 pathbuf); 254 if (reply("ADJUST LENGTH") == 1) { 255 dp = ginode(idesc->id_number); 256 DIP(dp, size) = 257 iswap64(iswap64(DIP(dp, size)) 258 - isize); 259 isize = 0; 260 printf( 261 "YOU MUST RERUN FSCK AFTERWARDS\n"); 262 rerun = 1; 263 inodirty(); 264 bp->b_flags &= ~B_INUSE; 265 return(STOP); 266 } 267 } 268 } 269 isize -= sizepb; 270 } 271 bp->b_flags &= ~B_INUSE; 272 return (KEEPON); 273 } 274 275 /* 276 * Check that a block in a legal block number. 277 * Return 0 if in range, 1 if out of range. 278 */ 279 int 280 chkrange(blk, cnt) 281 daddr_t blk; 282 int cnt; 283 { 284 int c; 285 286 if (cnt <= 0 || blk <= 0 || blk > maxfsblock || 287 cnt - 1 > maxfsblock - blk) 288 return (1); 289 if (cnt > sblock->fs_frag || 290 fragnum(sblock, blk) + cnt > sblock->fs_frag) { 291 if (debug) 292 printf("bad size: blk %lld, offset %d, size %d\n", 293 (long long)blk, (int)fragnum(sblock, blk), cnt); 294 } 295 c = dtog(sblock, blk); 296 if (blk < cgdmin(sblock, c)) { 297 if ((blk + cnt) > cgsblock(sblock, c)) { 298 if (debug) { 299 printf("blk %lld < cgdmin %lld;", 300 (long long)blk, 301 (long long)cgdmin(sblock, c)); 302 printf(" blk + cnt %lld > cgsbase %lld\n", 303 (long long)(blk + cnt), 304 (long long)cgsblock(sblock, c)); 305 } 306 return (1); 307 } 308 } else { 309 if ((blk + cnt) > cgbase(sblock, c+1)) { 310 if (debug) { 311 printf("blk %lld >= cgdmin %lld;", 312 (long long)blk, 313 (long long)cgdmin(sblock, c)); 314 printf(" blk + cnt %lld > sblock->fs_fpg %d\n", 315 (long long)(blk+cnt), sblock->fs_fpg); 316 } 317 return (1); 318 } 319 } 320 return (0); 321 } 322 323 /* 324 * General purpose interface for reading inodes. 325 */ 326 union dinode * 327 ginode(inumber) 328 ino_t inumber; 329 { 330 daddr_t iblk; 331 int blkoff; 332 333 if (inumber < ROOTINO || inumber > maxino) 334 errx(EEXIT, "bad inode number %d to ginode", inumber); 335 if (startinum == 0 || 336 inumber < startinum || inumber >= startinum + INOPB(sblock)) { 337 iblk = ino_to_fsba(sblock, inumber); 338 if (pbp != 0) 339 pbp->b_flags &= ~B_INUSE; 340 pbp = getdatablk(iblk, sblock->fs_bsize); 341 startinum = (inumber / INOPB(sblock)) * INOPB(sblock); 342 } 343 if (is_ufs2) { 344 blkoff = (inumber % INOPB(sblock)) * DINODE2_SIZE; 345 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff)); 346 } 347 blkoff = (inumber % INOPB(sblock)) * DINODE1_SIZE; 348 return ((union dinode *)((caddr_t)pbp->b_un.b_buf + blkoff)); 349 } 350 351 static void 352 swap_dinode1(union dinode *dp, int n) 353 { 354 int i, j; 355 struct ufs1_dinode *dp1; 356 int32_t maxsymlinklen = sblock->fs_maxsymlinklen; 357 if (isappleufs) 358 maxsymlinklen = APPLEUFS_MAXSYMLINKLEN; 359 360 dp1 = (struct ufs1_dinode *)&dp->dp1; 361 for (i = 0; i < n; i++, dp1++) { 362 ffs_dinode1_swap(dp1, dp1); 363 if (((iswap16(dp1->di_mode) & IFMT) != IFLNK) || 364 doinglevel2 || 365 (maxsymlinklen < 0) || 366 (iswap64(dp1->di_size) > maxsymlinklen)) { 367 for (j = 0; j < (NDADDR + NIADDR); j++) 368 dp1->di_db[j] = bswap32(dp1->di_db[j]); 369 } 370 } 371 } 372 373 static void 374 swap_dinode2(union dinode *dp, int n) 375 { 376 int i, j; 377 struct ufs2_dinode *dp2; 378 379 dp2 = (struct ufs2_dinode *)&dp->dp2; 380 for (i = 0; i < n; i++, dp2++) { 381 ffs_dinode2_swap(dp2, dp2); 382 if ((iswap16(dp2->di_mode) & IFMT) != IFLNK) { 383 for (j = 0; j < (NDADDR + NIADDR + NXADDR); j++) 384 dp2->di_extb[j] = bswap64(dp2->di_extb[j]); 385 } 386 } 387 } 388 389 /* 390 * Special purpose version of ginode used to optimize first pass 391 * over all the inodes in numerical order. 392 */ 393 ino_t nextino, lastinum, lastvalidinum; 394 long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 395 union dinode *inodebuf; 396 397 union dinode * 398 getnextinode(inumber) 399 ino_t inumber; 400 { 401 long size; 402 daddr_t dblk; 403 static union dinode *dp; 404 union dinode *ret; 405 406 if (inumber != nextino++ || inumber > lastvalidinum) { 407 abort(); 408 errx(EEXIT, "bad inode number %d to nextinode", inumber); 409 } 410 411 if (inumber >= lastinum) { 412 readcnt++; 413 dblk = fsbtodb(sblock, ino_to_fsba(sblock, lastinum)); 414 if (readcnt % readpercg == 0) { 415 size = partialsize; 416 lastinum += partialcnt; 417 } else { 418 size = inobufsize; 419 lastinum += fullcnt; 420 } 421 (void)bread(fsreadfd, (caddr_t)inodebuf, dblk, size); 422 if (doswap) { 423 if (is_ufs2) 424 swap_dinode2(inodebuf, lastinum - inumber); 425 else 426 swap_dinode1(inodebuf, lastinum - inumber); 427 bwrite(fswritefd, (char *)inodebuf, dblk, size); 428 } 429 dp = (union dinode *)inodebuf; 430 } 431 ret = dp; 432 dp = (union dinode *) 433 ((char *)dp + (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE)); 434 return ret; 435 } 436 437 void 438 setinodebuf(inum) 439 ino_t inum; 440 { 441 442 if (inum % sblock->fs_ipg != 0) 443 errx(EEXIT, "bad inode number %d to setinodebuf", inum); 444 445 lastvalidinum = inum + sblock->fs_ipg - 1; 446 startinum = 0; 447 nextino = inum; 448 lastinum = inum; 449 readcnt = 0; 450 if (inodebuf != NULL) 451 return; 452 inobufsize = blkroundup(sblock, INOBUFSIZE); 453 fullcnt = inobufsize / (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE); 454 readpercg = sblock->fs_ipg / fullcnt; 455 partialcnt = sblock->fs_ipg % fullcnt; 456 partialsize = partialcnt * (is_ufs2 ? DINODE2_SIZE : DINODE1_SIZE); 457 if (partialcnt != 0) { 458 readpercg++; 459 } else { 460 partialcnt = fullcnt; 461 partialsize = inobufsize; 462 } 463 if (inodebuf == NULL && 464 (inodebuf = malloc((unsigned)inobufsize)) == NULL) 465 errx(EEXIT, "Cannot allocate space for inode buffer"); 466 } 467 468 void 469 freeinodebuf() 470 { 471 472 if (inodebuf != NULL) 473 free((char *)inodebuf); 474 inodebuf = NULL; 475 } 476 477 /* 478 * Routines to maintain information about directory inodes. 479 * This is built during the first pass and used during the 480 * second and third passes. 481 * 482 * Enter inodes into the cache. 483 */ 484 void 485 cacheino(dp, inumber) 486 union dinode *dp; 487 ino_t inumber; 488 { 489 struct inoinfo *inp; 490 struct inoinfo **inpp, **ninpsort; 491 unsigned int blks; 492 int i; 493 int64_t size; 494 495 size = iswap64(DIP(dp, size)); 496 blks = howmany(size, sblock->fs_bsize); 497 if (blks > NDADDR) 498 blks = NDADDR + NIADDR; 499 500 inp = (struct inoinfo *) malloc(sizeof(*inp) + (blks - 1) 501 * sizeof (int64_t)); 502 if (inp == NULL) 503 return; 504 inpp = &inphead[inumber % dirhash]; 505 inp->i_nexthash = *inpp; 506 *inpp = inp; 507 inp->i_child = inp->i_sibling = 0; 508 if (inumber == ROOTINO) 509 inp->i_parent = ROOTINO; 510 else 511 inp->i_parent = (ino_t)0; 512 inp->i_dotdot = (ino_t)0; 513 inp->i_number = inumber; 514 inp->i_isize = size; 515 inp->i_numblks = blks; 516 for (i = 0; i < (blks < NDADDR ? blks : NDADDR); i++) 517 inp->i_blks[i] = DIP(dp, db[i]); 518 if (blks > NDADDR) 519 for (i = 0; i < NIADDR; i++) 520 inp->i_blks[NDADDR + i] = DIP(dp, ib[i]); 521 if (inplast == listmax) { 522 ninpsort = (struct inoinfo **)realloc((char *)inpsort, 523 (unsigned)(listmax + 100) * sizeof(struct inoinfo *)); 524 if (inpsort == NULL) 525 errx(EEXIT, "cannot increase directory list"); 526 inpsort = ninpsort; 527 listmax += 100; 528 } 529 inpsort[inplast++] = inp; 530 } 531 532 /* 533 * Look up an inode cache structure. 534 */ 535 struct inoinfo * 536 getinoinfo(inumber) 537 ino_t inumber; 538 { 539 struct inoinfo *inp; 540 541 for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) { 542 if (inp->i_number != inumber) 543 continue; 544 return (inp); 545 } 546 errx(EEXIT, "cannot find inode %d", inumber); 547 return ((struct inoinfo *)0); 548 } 549 550 /* 551 * Clean up all the inode cache structure. 552 */ 553 void 554 inocleanup() 555 { 556 struct inoinfo **inpp; 557 558 if (inphead == NULL) 559 return; 560 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 561 free((char *)(*inpp)); 562 free((char *)inphead); 563 free((char *)inpsort); 564 inphead = inpsort = NULL; 565 } 566 567 void 568 inodirty() 569 { 570 571 dirty(pbp); 572 } 573 574 void 575 clri(idesc, type, flag) 576 struct inodesc *idesc; 577 char *type; 578 int flag; 579 { 580 union dinode *dp; 581 582 dp = ginode(idesc->id_number); 583 if (flag == 1) { 584 pwarn("%s %s", type, 585 (iswap16(DIP(dp, mode)) & IFMT) == IFDIR ? "DIR" : "FILE"); 586 pinode(idesc->id_number); 587 } 588 if (preen || reply("CLEAR") == 1) { 589 if (preen) 590 printf(" (CLEARED)\n"); 591 n_files--; 592 (void)ckinode(dp, idesc); 593 clearinode(dp); 594 inoinfo(idesc->id_number)->ino_state = USTATE; 595 inodirty(); 596 } else 597 markclean= 0; 598 } 599 600 int 601 findname(idesc) 602 struct inodesc *idesc; 603 { 604 struct direct *dirp = idesc->id_dirp; 605 606 if (iswap32(dirp->d_ino) != idesc->id_parent || idesc->id_entryno < 2) { 607 idesc->id_entryno++; 608 return (KEEPON); 609 } 610 memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1); 611 return (STOP|FOUND); 612 } 613 614 int 615 findino(idesc) 616 struct inodesc *idesc; 617 { 618 struct direct *dirp = idesc->id_dirp; 619 620 if (dirp->d_ino == 0) 621 return (KEEPON); 622 if (strcmp(dirp->d_name, idesc->id_name) == 0 && 623 iswap32(dirp->d_ino) >= ROOTINO && iswap32(dirp->d_ino) <= maxino) { 624 idesc->id_parent = iswap32(dirp->d_ino); 625 return (STOP|FOUND); 626 } 627 return (KEEPON); 628 } 629 630 int 631 clearentry(idesc) 632 struct inodesc *idesc; 633 { 634 struct direct *dirp = idesc->id_dirp; 635 636 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 637 idesc->id_entryno++; 638 return (KEEPON); 639 } 640 dirp->d_ino = 0; 641 return (STOP|FOUND|ALTERED); 642 } 643 644 void 645 pinode(ino) 646 ino_t ino; 647 { 648 union dinode *dp; 649 char *p; 650 struct passwd *pw; 651 time_t t; 652 653 printf(" I=%u ", ino); 654 if (ino < ROOTINO || ino > maxino) 655 return; 656 dp = ginode(ino); 657 printf(" OWNER="); 658 #ifndef SMALL 659 if ((pw = getpwuid((int)iswap32(DIP(dp, uid)))) != 0) 660 printf("%s ", pw->pw_name); 661 else 662 #endif 663 printf("%u ", (unsigned)iswap32(DIP(dp, uid))); 664 printf("MODE=%o\n", iswap16(DIP(dp, mode))); 665 if (preen) 666 printf("%s: ", cdevname()); 667 printf("SIZE=%llu ", (unsigned long long)iswap64(DIP(dp, size))); 668 t = iswap32(DIP(dp, mtime)); 669 p = ctime(&t); 670 printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); 671 } 672 673 void 674 blkerror(ino, type, blk) 675 ino_t ino; 676 char *type; 677 daddr_t blk; 678 { 679 struct inostat *info; 680 681 pfatal("%lld %s I=%u", (long long)blk, type, ino); 682 printf("\n"); 683 info = inoinfo(ino); 684 switch (info->ino_state) { 685 686 case FSTATE: 687 info->ino_state = FCLEAR; 688 return; 689 690 case DSTATE: 691 info->ino_state = DCLEAR; 692 return; 693 694 case FCLEAR: 695 case DCLEAR: 696 return; 697 698 default: 699 errx(EEXIT, "BAD STATE %d TO BLKERR", info->ino_state); 700 /* NOTREACHED */ 701 } 702 } 703 704 /* 705 * allocate an unused inode 706 */ 707 ino_t 708 allocino(request, type) 709 ino_t request; 710 int type; 711 { 712 ino_t ino; 713 union dinode *dp; 714 struct ufs1_dinode *dp1; 715 struct ufs2_dinode *dp2; 716 time_t t; 717 struct cg *cgp = cgrp; 718 int cg; 719 struct inostat *info; 720 721 if (request == 0) 722 request = ROOTINO; 723 else if (inoinfo(request)->ino_state != USTATE) 724 return (0); 725 for (ino = request; ino < maxino; ino++) { 726 info = inoinfo(ino); 727 if (info->ino_state == USTATE) 728 break; 729 } 730 if (ino == maxino) 731 return (0); 732 cg = ino_to_cg(sblock, ino); 733 /* If necessary, extend the inoinfo array. grow exponentially */ 734 if ((ino % sblock->fs_ipg) >= inostathead[cg].il_numalloced) { 735 unsigned long newalloced, i; 736 newalloced = MIN(sblock->fs_ipg, 737 MAX(2 * inostathead[cg].il_numalloced, 10)); 738 info = calloc(newalloced, sizeof(struct inostat)); 739 if (info == NULL) { 740 pwarn("cannot alloc %lu bytes to extend inoinfo\n", 741 sizeof(struct inostat) * newalloced); 742 return 0; 743 } 744 memmove(info, inostathead[cg].il_stat, 745 inostathead[cg].il_numalloced * sizeof(*info)); 746 for (i = inostathead[cg].il_numalloced; i < newalloced; i++) { 747 info[i].ino_state = USTATE; 748 } 749 if (inostathead[cg].il_numalloced) 750 free(inostathead[cg].il_stat); 751 inostathead[cg].il_stat = info; 752 inostathead[cg].il_numalloced = newalloced; 753 info = inoinfo(ino); 754 } 755 getblk(&cgblk, cgtod(sblock, cg), sblock->fs_cgsize); 756 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 757 if ((doswap && !needswap) || (!doswap && needswap)) 758 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 759 if (!cg_chkmagic(cgp, 0)) 760 pfatal("CG %d: ALLOCINO: BAD MAGIC NUMBER\n", cg); 761 if (doswap) 762 cgdirty(); 763 setbit(cg_inosused(cgp, 0), ino % sblock->fs_ipg); 764 cgp->cg_cs.cs_nifree--; 765 switch (type & IFMT) { 766 case IFDIR: 767 info->ino_state = DSTATE; 768 cgp->cg_cs.cs_ndir++; 769 break; 770 case IFREG: 771 case IFLNK: 772 info->ino_state = FSTATE; 773 break; 774 default: 775 return (0); 776 } 777 cgdirty(); 778 dp = ginode(ino); 779 if (is_ufs2) { 780 dp2 = &dp->dp2; 781 dp2->di_db[0] = iswap64(allocblk(1)); 782 if (dp2->di_db[0] == 0) { 783 info->ino_state = USTATE; 784 return (0); 785 } 786 dp2->di_mode = iswap16(type); 787 dp2->di_flags = 0; 788 (void)time(&t); 789 dp2->di_atime = iswap64(t); 790 dp2->di_mtime = dp2->di_ctime = dp2->di_atime; 791 dp2->di_size = iswap64(sblock->fs_fsize); 792 dp2->di_blocks = iswap64(btodb(sblock->fs_fsize)); 793 } else { 794 dp1 = &dp->dp1; 795 dp1->di_db[0] = iswap32(allocblk(1)); 796 if (dp1->di_db[0] == 0) { 797 info->ino_state = USTATE; 798 return (0); 799 } 800 dp1->di_mode = iswap16(type); 801 dp1->di_flags = 0; 802 (void)time(&t); 803 dp1->di_atime = iswap32(t); 804 dp1->di_mtime = dp1->di_ctime = dp1->di_atime; 805 dp1->di_size = iswap64(sblock->fs_fsize); 806 dp1->di_blocks = iswap32(btodb(sblock->fs_fsize)); 807 } 808 n_files++; 809 inodirty(); 810 if (newinofmt) 811 info->ino_type = IFTODT(type); 812 return (ino); 813 } 814 815 /* 816 * deallocate an inode 817 */ 818 void 819 freeino(ino) 820 ino_t ino; 821 { 822 struct inodesc idesc; 823 union dinode *dp; 824 825 memset(&idesc, 0, sizeof(struct inodesc)); 826 idesc.id_type = ADDR; 827 idesc.id_func = pass4check; 828 idesc.id_number = ino; 829 dp = ginode(ino); 830 (void)ckinode(dp, &idesc); 831 clearinode(dp); 832 inodirty(); 833 inoinfo(ino)->ino_state = USTATE; 834 n_files--; 835 } 836