1 /* $NetBSD: inode.c,v 1.38 2008/04/28 20:23:08 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Konrad E. Schroder <perseant@hhhh.org>. 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 /* 33 * Copyright (c) 1980, 1986, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 */ 60 61 #include <sys/types.h> 62 #include <sys/param.h> 63 #include <sys/time.h> 64 #include <sys/buf.h> 65 #include <sys/mount.h> 66 67 #include <ufs/ufs/inode.h> 68 #include <ufs/ufs/dir.h> 69 #define vnode uvnode 70 #include <ufs/lfs/lfs.h> 71 #undef vnode 72 73 #include <err.h> 74 #ifndef SMALL 75 #include <pwd.h> 76 #endif 77 #include <stdio.h> 78 #include <stdlib.h> 79 #include <string.h> 80 #include <util.h> 81 82 #include "bufcache.h" 83 #include "vnode.h" 84 #include "lfs_user.h" 85 86 #include "fsck.h" 87 #include "fsutil.h" 88 #include "extern.h" 89 90 extern SEGUSE *seg_table; 91 extern ufs_daddr_t *din_table; 92 93 static int iblock(struct inodesc *, long, u_int64_t); 94 int blksreqd(struct lfs *, int); 95 int lfs_maxino(void); 96 97 /* 98 * Get a dinode of a given inum. 99 * XXX combine this function with vget. 100 */ 101 struct ufs1_dinode * 102 ginode(ino_t ino) 103 { 104 struct uvnode *vp; 105 struct ubuf *bp; 106 IFILE *ifp; 107 108 vp = vget(fs, ino); 109 if (vp == NULL) 110 return NULL; 111 112 if (din_table[ino] == 0x0) { 113 LFS_IENTRY(ifp, fs, ino, bp); 114 din_table[ino] = ifp->if_daddr; 115 seg_table[dtosn(fs, ifp->if_daddr)].su_nbytes += DINODE1_SIZE; 116 brelse(bp, 0); 117 } 118 return (VTOI(vp)->i_din.ffs1_din); 119 } 120 121 /* 122 * Check validity of held blocks in an inode, recursing through all blocks. 123 */ 124 int 125 ckinode(struct ufs1_dinode *dp, struct inodesc *idesc) 126 { 127 ufs_daddr_t *ap, lbn; 128 long ret, n, ndb, offset; 129 struct ufs1_dinode dino; 130 u_int64_t remsize, sizepb; 131 mode_t mode; 132 char pathbuf[MAXPATHLEN + 1]; 133 struct uvnode *vp, *thisvp; 134 135 if (idesc->id_fix != IGNORE) 136 idesc->id_fix = DONTKNOW; 137 idesc->id_entryno = 0; 138 idesc->id_filesize = dp->di_size; 139 mode = dp->di_mode & IFMT; 140 if (mode == IFBLK || mode == IFCHR || 141 (mode == IFLNK && (dp->di_size < fs->lfs_maxsymlinklen || 142 (fs->lfs_maxsymlinklen == 0 && 143 dp->di_blocks == 0)))) 144 return (KEEPON); 145 dino = *dp; 146 ndb = howmany(dino.di_size, fs->lfs_bsize); 147 148 thisvp = vget(fs, idesc->id_number); 149 for (lbn = 0; lbn < NDADDR; lbn++) { 150 ap = dino.di_db + lbn; 151 if (thisvp) 152 idesc->id_numfrags = 153 numfrags(fs, VTOI(thisvp)->i_lfs_fragsize[lbn]); 154 else { 155 if (--ndb == 0 && (offset = blkoff(fs, dino.di_size)) != 0) { 156 idesc->id_numfrags = 157 numfrags(fs, fragroundup(fs, offset)); 158 } else 159 idesc->id_numfrags = fs->lfs_frag; 160 } 161 if (*ap == 0) { 162 if (idesc->id_type == DATA && ndb >= 0) { 163 /* An empty block in a directory XXX */ 164 getpathname(pathbuf, sizeof(pathbuf), 165 idesc->id_number, idesc->id_number); 166 pfatal("DIRECTORY %s INO %lld: CONTAINS EMPTY BLOCKS [1]", 167 pathbuf, (long long)idesc->id_number); 168 if (reply("ADJUST LENGTH") == 1) { 169 vp = vget(fs, idesc->id_number); 170 dp = VTOD(vp); 171 dp->di_size = (ap - &dino.di_db[0]) * 172 fs->lfs_bsize; 173 printf( 174 "YOU MUST RERUN FSCK AFTERWARDS\n"); 175 rerun = 1; 176 inodirty(VTOI(vp)); 177 } else 178 break; 179 } 180 continue; 181 } 182 idesc->id_blkno = *ap; 183 idesc->id_lblkno = ap - &dino.di_db[0]; 184 if (idesc->id_type == ADDR) { 185 ret = (*idesc->id_func) (idesc); 186 } else 187 ret = dirscan(idesc); 188 if (ret & STOP) 189 return (ret); 190 } 191 idesc->id_numfrags = fs->lfs_frag; 192 remsize = dino.di_size - fs->lfs_bsize * NDADDR; 193 sizepb = fs->lfs_bsize; 194 for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { 195 if (*ap) { 196 idesc->id_blkno = *ap; 197 ret = iblock(idesc, n, remsize); 198 if (ret & STOP) 199 return (ret); 200 } else { 201 if (idesc->id_type == DATA && remsize > 0) { 202 /* An empty block in a directory XXX */ 203 getpathname(pathbuf, sizeof(pathbuf), 204 idesc->id_number, idesc->id_number); 205 pfatal("DIRECTORY %s INO %lld: CONTAINS EMPTY BLOCKS [2]", 206 pathbuf, (long long)idesc->id_number); 207 if (reply("ADJUST LENGTH") == 1) { 208 vp = vget(fs, idesc->id_number); 209 dp = VTOD(vp); 210 dp->di_size -= remsize; 211 remsize = 0; 212 printf( 213 "YOU MUST RERUN FSCK AFTERWARDS\n"); 214 rerun = 1; 215 inodirty(VTOI(vp)); 216 break; 217 } else 218 break; 219 } 220 } 221 sizepb *= NINDIR(fs); 222 remsize -= sizepb; 223 } 224 return (KEEPON); 225 } 226 227 static int 228 iblock(struct inodesc *idesc, long ilevel, u_int64_t isize) 229 { 230 ufs_daddr_t *ap, *aplim; 231 struct ubuf *bp; 232 int i, n, (*func) (struct inodesc *), nif; 233 u_int64_t sizepb; 234 char pathbuf[MAXPATHLEN + 1], buf[BUFSIZ]; 235 struct uvnode *devvp, *vp; 236 int diddirty = 0; 237 238 if (idesc->id_type == ADDR) { 239 func = idesc->id_func; 240 n = (*func) (idesc); 241 if ((n & KEEPON) == 0) 242 return (n); 243 } else 244 func = dirscan; 245 if (chkrange(idesc->id_blkno, fragstofsb(fs, idesc->id_numfrags))) 246 return (SKIP); 247 248 devvp = fs->lfs_devvp; 249 bread(devvp, fsbtodb(fs, idesc->id_blkno), fs->lfs_bsize, NOCRED, &bp); 250 ilevel--; 251 for (sizepb = fs->lfs_bsize, i = 0; i < ilevel; i++) 252 sizepb *= NINDIR(fs); 253 if (isize > sizepb * NINDIR(fs)) 254 nif = NINDIR(fs); 255 else 256 nif = howmany(isize, sizepb); 257 if (idesc->id_func == pass1check && nif < NINDIR(fs)) { 258 aplim = ((ufs_daddr_t *) bp->b_data) + NINDIR(fs); 259 for (ap = ((ufs_daddr_t *) bp->b_data) + nif; ap < aplim; ap++) { 260 if (*ap == 0) 261 continue; 262 (void) sprintf(buf, "PARTIALLY TRUNCATED INODE I=%llu", 263 (unsigned long long)idesc->id_number); 264 if (dofix(idesc, buf)) { 265 *ap = 0; 266 ++diddirty; 267 } 268 } 269 } 270 aplim = ((ufs_daddr_t *) bp->b_data) + nif; 271 for (ap = ((ufs_daddr_t *) bp->b_data); ap < aplim; ap++) { 272 if (*ap) { 273 idesc->id_blkno = *ap; 274 if (ilevel == 0) { 275 /* 276 * dirscan needs lblkno. 277 */ 278 idesc->id_lblkno++; 279 n = (*func) (idesc); 280 } else { 281 n = iblock(idesc, ilevel, isize); 282 } 283 if (n & STOP) { 284 if (diddirty) 285 VOP_BWRITE(bp); 286 else 287 brelse(bp, 0); 288 return (n); 289 } 290 } else { 291 if (idesc->id_type == DATA && isize > 0) { 292 /* An empty block in a directory XXX */ 293 getpathname(pathbuf, sizeof(pathbuf), 294 idesc->id_number, idesc->id_number); 295 pfatal("DIRECTORY %s INO %lld: CONTAINS EMPTY BLOCKS [3]", 296 pathbuf, (long long)idesc->id_number); 297 if (reply("ADJUST LENGTH") == 1) { 298 vp = vget(fs, idesc->id_number); 299 VTOI(vp)->i_ffs1_size -= isize; 300 isize = 0; 301 printf( 302 "YOU MUST RERUN FSCK AFTERWARDS\n"); 303 rerun = 1; 304 inodirty(VTOI(vp)); 305 if (diddirty) 306 VOP_BWRITE(bp); 307 else 308 brelse(bp, 0); 309 return (STOP); 310 } 311 } 312 } 313 isize -= sizepb; 314 } 315 if (diddirty) 316 VOP_BWRITE(bp); 317 else 318 brelse(bp, 0); 319 return (KEEPON); 320 } 321 322 /* 323 * Check that a block in a legal block number. 324 * Return 0 if in range, 1 if out of range. 325 */ 326 int 327 chkrange(daddr_t blk, int cnt) 328 { 329 if (blk < sntod(fs, 0)) { 330 return (1); 331 } 332 if (blk > maxfsblock) { 333 return (1); 334 } 335 if (blk + cnt < sntod(fs, 0)) { 336 return (1); 337 } 338 if (blk + cnt > maxfsblock) { 339 return (1); 340 } 341 return (0); 342 } 343 344 /* 345 * Routines to maintain information about directory inodes. 346 * This is built during the first pass and used during the 347 * second and third passes. 348 * 349 * Enter inodes into the cache. 350 */ 351 void 352 cacheino(struct ufs1_dinode * dp, ino_t inumber) 353 { 354 struct inoinfo *inp; 355 struct inoinfo **inpp, **ninpsort; 356 unsigned int blks; 357 358 blks = howmany(dp->di_size, fs->lfs_bsize); 359 if (blks > NDADDR) 360 blks = NDADDR + NIADDR; 361 inp = emalloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t)); 362 inpp = &inphead[inumber % numdirs]; 363 inp->i_nexthash = *inpp; 364 *inpp = inp; 365 inp->i_child = inp->i_sibling = inp->i_parentp = 0; 366 if (inumber == ROOTINO) 367 inp->i_parent = ROOTINO; 368 else 369 inp->i_parent = (ino_t) 0; 370 inp->i_dotdot = (ino_t) 0; 371 inp->i_number = inumber; 372 inp->i_isize = dp->di_size; 373 374 inp->i_numblks = blks * sizeof(ufs_daddr_t); 375 memcpy(&inp->i_blks[0], &dp->di_db[0], (size_t) inp->i_numblks); 376 if (inplast == listmax) { 377 ninpsort = erealloc(inpsort, 378 (listmax + 100) * sizeof(struct inoinfo *)); 379 inpsort = ninpsort; 380 listmax += 100; 381 } 382 inpsort[inplast++] = inp; 383 } 384 385 /* 386 * Look up an inode cache structure. 387 */ 388 struct inoinfo * 389 getinoinfo(ino_t inumber) 390 { 391 struct inoinfo *inp; 392 393 for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) { 394 if (inp->i_number != inumber) 395 continue; 396 return (inp); 397 } 398 err(EEXIT, "cannot find inode %llu\n", (unsigned long long)inumber); 399 return ((struct inoinfo *) 0); 400 } 401 402 /* 403 * Clean up all the inode cache structure. 404 */ 405 void 406 inocleanup(void) 407 { 408 struct inoinfo **inpp; 409 410 if (inphead == NULL) 411 return; 412 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 413 free((char *) (*inpp)); 414 free((char *) inphead); 415 free((char *) inpsort); 416 inphead = inpsort = NULL; 417 } 418 419 void 420 inodirty(struct inode *ip) 421 { 422 ip->i_flag |= IN_MODIFIED; 423 } 424 425 void 426 clri(struct inodesc * idesc, const char *type, int flag) 427 { 428 struct uvnode *vp; 429 430 vp = vget(fs, idesc->id_number); 431 if (flag & 0x1) { 432 pwarn("%s %s", type, 433 (VTOI(vp)->i_ffs1_mode & IFMT) == IFDIR ? "DIR" : "FILE"); 434 pinode(idesc->id_number); 435 } 436 if ((flag & 0x2) || preen || reply("CLEAR") == 1) { 437 if (preen && flag != 2) 438 printf(" (CLEARED)\n"); 439 n_files--; 440 (void) ckinode(VTOD(vp), idesc); 441 clearinode(idesc->id_number); 442 statemap[idesc->id_number] = USTATE; 443 vnode_destroy(vp); 444 return; 445 } 446 return; 447 } 448 449 void 450 clearinode(ino_t inumber) 451 { 452 struct ubuf *bp; 453 IFILE *ifp; 454 daddr_t daddr; 455 456 /* Send cleared inode to the free list */ 457 458 LFS_IENTRY(ifp, fs, inumber, bp); 459 daddr = ifp->if_daddr; 460 if (daddr == LFS_UNUSED_DADDR) { 461 brelse(bp, 0); 462 return; 463 } 464 ifp->if_daddr = LFS_UNUSED_DADDR; 465 ifp->if_nextfree = fs->lfs_freehd; 466 fs->lfs_freehd = inumber; 467 sbdirty(); 468 VOP_BWRITE(bp); 469 470 /* 471 * update segment usage. 472 */ 473 if (daddr != LFS_UNUSED_DADDR) { 474 SEGUSE *sup; 475 u_int32_t oldsn = dtosn(fs, daddr); 476 477 seg_table[oldsn].su_nbytes -= DINODE1_SIZE; 478 LFS_SEGENTRY(sup, fs, oldsn, bp); 479 sup->su_nbytes -= DINODE1_SIZE; 480 LFS_WRITESEGENTRY(sup, fs, oldsn, bp); /* Ifile */ 481 } 482 } 483 484 int 485 findname(struct inodesc * idesc) 486 { 487 struct direct *dirp = idesc->id_dirp; 488 size_t len; 489 char *buf; 490 491 if (dirp->d_ino != idesc->id_parent) 492 return (KEEPON); 493 if ((len = dirp->d_namlen + 1) > MAXPATHLEN) { 494 /* Truncate it but don't overflow the buffer */ 495 len = MAXPATHLEN; 496 } 497 /* this is namebuf with utils.h */ 498 buf = __UNCONST(idesc->id_name); 499 (void)memcpy(buf, dirp->d_name, len); 500 return (STOP | FOUND); 501 } 502 503 int 504 findino(struct inodesc * idesc) 505 { 506 struct direct *dirp = idesc->id_dirp; 507 508 if (dirp->d_ino == 0) 509 return (KEEPON); 510 if (strcmp(dirp->d_name, idesc->id_name) == 0 && 511 dirp->d_ino >= ROOTINO && dirp->d_ino < maxino) { 512 idesc->id_parent = dirp->d_ino; 513 return (STOP | FOUND); 514 } 515 return (KEEPON); 516 } 517 518 void 519 pinode(ino_t ino) 520 { 521 struct ufs1_dinode *dp; 522 char *p; 523 struct passwd *pw; 524 time_t t; 525 526 printf(" I=%llu ", (unsigned long long)ino); 527 if (ino < ROOTINO || ino >= maxino) 528 return; 529 dp = ginode(ino); 530 if (dp) { 531 printf(" OWNER="); 532 #ifndef SMALL 533 if ((pw = getpwuid((int) dp->di_uid)) != 0) 534 printf("%s ", pw->pw_name); 535 else 536 #endif 537 printf("%u ", (unsigned) dp->di_uid); 538 printf("MODE=%o\n", dp->di_mode); 539 if (preen) 540 printf("%s: ", cdevname()); 541 printf("SIZE=%llu ", (unsigned long long) dp->di_size); 542 t = dp->di_mtime; 543 p = ctime(&t); 544 printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); 545 } 546 } 547 548 void 549 blkerror(ino_t ino, const char *type, daddr_t blk) 550 { 551 552 pfatal("%lld %s I=%llu", (long long) blk, type, 553 (unsigned long long)ino); 554 printf("\n"); 555 if (exitonfail) 556 exit(1); 557 switch (statemap[ino]) { 558 559 case FSTATE: 560 statemap[ino] = FCLEAR; 561 return; 562 563 case DSTATE: 564 statemap[ino] = DCLEAR; 565 return; 566 567 case FCLEAR: 568 case DCLEAR: 569 return; 570 571 default: 572 err(EEXIT, "BAD STATE %d TO BLKERR\n", statemap[ino]); 573 /* NOTREACHED */ 574 } 575 } 576 577 /* 578 * allocate an unused inode 579 */ 580 ino_t 581 allocino(ino_t request, int type) 582 { 583 ino_t ino; 584 struct ufs1_dinode *dp; 585 time_t t; 586 struct uvnode *vp; 587 struct ubuf *bp; 588 589 if (request == 0) 590 request = ROOTINO; 591 else if (statemap[request] != USTATE) 592 return (0); 593 for (ino = request; ino < maxino; ino++) 594 if (statemap[ino] == USTATE) 595 break; 596 if (ino == maxino) 597 extend_ifile(fs); 598 599 switch (type & IFMT) { 600 case IFDIR: 601 statemap[ino] = DSTATE; 602 break; 603 case IFREG: 604 case IFLNK: 605 statemap[ino] = FSTATE; 606 break; 607 default: 608 return (0); 609 } 610 vp = lfs_valloc(fs, ino); 611 if (vp == NULL) 612 return (0); 613 dp = (VTOI(vp)->i_din.ffs1_din); 614 bp = getblk(vp, 0, fs->lfs_fsize); 615 VOP_BWRITE(bp); 616 dp->di_mode = type; 617 (void) time(&t); 618 dp->di_atime = t; 619 dp->di_mtime = dp->di_ctime = dp->di_atime; 620 dp->di_size = fs->lfs_fsize; 621 dp->di_blocks = btofsb(fs, fs->lfs_fsize); 622 n_files++; 623 inodirty(VTOI(vp)); 624 typemap[ino] = IFTODT(type); 625 return (ino); 626 } 627 628 /* 629 * deallocate an inode 630 */ 631 void 632 freeino(ino_t ino) 633 { 634 struct inodesc idesc; 635 struct uvnode *vp; 636 637 memset(&idesc, 0, sizeof(struct inodesc)); 638 idesc.id_type = ADDR; 639 idesc.id_func = pass4check; 640 idesc.id_number = ino; 641 vp = vget(fs, ino); 642 (void) ckinode(VTOD(vp), &idesc); 643 clearinode(ino); 644 statemap[ino] = USTATE; 645 vnode_destroy(vp); 646 647 n_files--; 648 } 649