1/* $NetBSD: inode.c,v 1.41 2010/02/04 23:55:43 christos 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 90extern SEGUSE *seg_table; 91extern ufs_daddr_t *din_table; 92 93static int iblock(struct inodesc *, long, u_int64_t); 94int blksreqd(struct lfs *, int); 95int lfs_maxino(void); 96 97/* 98 * Get a dinode of a given inum. 99 * XXX combine this function with vget. 100 */ 101struct ufs1_dinode * 102ginode(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 */ 124int 125ckinode(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 227static int 228iblock(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, idesc->id_numfrags)) 246 return (SKIP); 247 248 devvp = fs->lfs_devvp; 249 bread(devvp, fsbtodb(fs, idesc->id_blkno), fs->lfs_bsize, 250 NOCRED, 0, &bp); 251 ilevel--; 252 for (sizepb = fs->lfs_bsize, i = 0; i < ilevel; i++) 253 sizepb *= NINDIR(fs); 254 if (isize > sizepb * NINDIR(fs)) 255 nif = NINDIR(fs); 256 else 257 nif = howmany(isize, sizepb); 258 if (idesc->id_func == pass1check && nif < NINDIR(fs)) { 259 aplim = ((ufs_daddr_t *) bp->b_data) + NINDIR(fs); 260 for (ap = ((ufs_daddr_t *) bp->b_data) + nif; ap < aplim; ap++) { 261 if (*ap == 0) 262 continue; 263 (void) sprintf(buf, "PARTIALLY TRUNCATED INODE I=%llu", 264 (unsigned long long)idesc->id_number); 265 if (dofix(idesc, buf)) { 266 *ap = 0; 267 ++diddirty; 268 } 269 } 270 } 271 aplim = ((ufs_daddr_t *) bp->b_data) + nif; 272 for (ap = ((ufs_daddr_t *) bp->b_data); ap < aplim; ap++) { 273 if (*ap) { 274 idesc->id_blkno = *ap; 275 if (ilevel == 0) { 276 /* 277 * dirscan needs lblkno. 278 */ 279 idesc->id_lblkno++; 280 n = (*func) (idesc); 281 } else { 282 n = iblock(idesc, ilevel, isize); 283 } 284 if (n & STOP) { 285 if (diddirty) 286 VOP_BWRITE(bp); 287 else 288 brelse(bp, 0); 289 return (n); 290 } 291 } else { 292 if (idesc->id_type == DATA && isize > 0) { 293 /* An empty block in a directory XXX */ 294 getpathname(pathbuf, sizeof(pathbuf), 295 idesc->id_number, idesc->id_number); 296 pfatal("DIRECTORY %s INO %lld: CONTAINS EMPTY BLOCKS [3]", 297 pathbuf, (long long)idesc->id_number); 298 if (reply("ADJUST LENGTH") == 1) { 299 vp = vget(fs, idesc->id_number); 300 VTOI(vp)->i_ffs1_size -= isize; 301 isize = 0; 302 printf( 303 "YOU MUST RERUN FSCK AFTERWARDS\n"); 304 rerun = 1; 305 inodirty(VTOI(vp)); 306 if (diddirty) 307 VOP_BWRITE(bp); 308 else 309 brelse(bp, 0); 310 return (STOP); 311 } 312 } 313 } 314 isize -= sizepb; 315 } 316 if (diddirty) 317 VOP_BWRITE(bp); 318 else 319 brelse(bp, 0); 320 return (KEEPON); 321} 322 323/* 324 * Check that a block in a legal block number. 325 * Return 0 if in range, 1 if out of range. 326 */ 327int 328chkrange(daddr_t blk, int cnt) 329{ 330 if (blk < sntod(fs, 0)) { 331 return (1); 332 } 333 if (blk > maxfsblock) { 334 return (1); 335 } 336 if (blk + cnt < sntod(fs, 0)) { 337 return (1); 338 } 339 if (blk + cnt > maxfsblock) { 340 return (1); 341 } 342 return (0); 343} 344 345/* 346 * Routines to maintain information about directory inodes. 347 * This is built during the first pass and used during the 348 * second and third passes. 349 * 350 * Enter inodes into the cache. 351 */ 352void 353cacheino(struct ufs1_dinode * dp, ino_t inumber) 354{ 355 struct inoinfo *inp; 356 struct inoinfo **inpp, **ninpsort; 357 unsigned int blks; 358 359 blks = howmany(dp->di_size, fs->lfs_bsize); 360 if (blks > NDADDR) 361 blks = NDADDR + NIADDR; 362 inp = emalloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t)); 363 inpp = &inphead[inumber % numdirs]; 364 inp->i_nexthash = *inpp; 365 *inpp = inp; 366 inp->i_child = inp->i_sibling = inp->i_parentp = 0; 367 if (inumber == ROOTINO) 368 inp->i_parent = ROOTINO; 369 else 370 inp->i_parent = (ino_t) 0; 371 inp->i_dotdot = (ino_t) 0; 372 inp->i_number = inumber; 373 inp->i_isize = dp->di_size; 374 375 inp->i_numblks = blks * sizeof(ufs_daddr_t); 376 memcpy(&inp->i_blks[0], &dp->di_db[0], (size_t) inp->i_numblks); 377 if (inplast == listmax) { 378 ninpsort = erealloc(inpsort, 379 (listmax + 100) * sizeof(struct inoinfo *)); 380 inpsort = ninpsort; 381 listmax += 100; 382 } 383 inpsort[inplast++] = inp; 384} 385 386/* 387 * Look up an inode cache structure. 388 */ 389struct inoinfo * 390getinoinfo(ino_t inumber) 391{ 392 struct inoinfo *inp; 393 394 for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) { 395 if (inp->i_number != inumber) 396 continue; 397 return (inp); 398 } 399 err(EEXIT, "cannot find inode %llu\n", (unsigned long long)inumber); 400 return ((struct inoinfo *) 0); 401} 402 403/* 404 * Clean up all the inode cache structure. 405 */ 406void 407inocleanup(void) 408{ 409 struct inoinfo **inpp; 410 411 if (inphead == NULL) 412 return; 413 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 414 free((char *) (*inpp)); 415 free((char *) inphead); 416 free((char *) inpsort); 417 inphead = inpsort = NULL; 418} 419 420void 421inodirty(struct inode *ip) 422{ 423 ip->i_flag |= IN_MODIFIED; 424} 425 426void 427clri(struct inodesc * idesc, const char *type, int flag) 428{ 429 struct uvnode *vp; 430 431 vp = vget(fs, idesc->id_number); 432 if (flag & 0x1) { 433 pwarn("%s %s", type, 434 (VTOI(vp)->i_ffs1_mode & IFMT) == IFDIR ? "DIR" : "FILE"); 435 pinode(idesc->id_number); 436 } 437 if ((flag & 0x2) || preen || reply("CLEAR") == 1) { 438 if (preen && flag != 2) 439 printf(" (CLEARED)\n"); 440 n_files--; 441 (void) ckinode(VTOD(vp), idesc); 442 clearinode(idesc->id_number); 443 statemap[idesc->id_number] = USTATE; 444 vnode_destroy(vp); 445 return; 446 } 447 return; 448} 449 450void 451clearinode(ino_t inumber) 452{ 453 struct ubuf *bp; 454 IFILE *ifp; 455 daddr_t daddr; 456 457 /* Send cleared inode to the free list */ 458 459 LFS_IENTRY(ifp, fs, inumber, bp); 460 daddr = ifp->if_daddr; 461 if (daddr == LFS_UNUSED_DADDR) { 462 brelse(bp, 0); 463 return; 464 } 465 ifp->if_daddr = LFS_UNUSED_DADDR; 466 ifp->if_nextfree = fs->lfs_freehd; 467 fs->lfs_freehd = inumber; 468 sbdirty(); 469 VOP_BWRITE(bp); 470 471 /* 472 * update segment usage. 473 */ 474 if (daddr != LFS_UNUSED_DADDR) { 475 SEGUSE *sup; 476 u_int32_t oldsn = dtosn(fs, daddr); 477 478 seg_table[oldsn].su_nbytes -= DINODE1_SIZE; 479 LFS_SEGENTRY(sup, fs, oldsn, bp); 480 sup->su_nbytes -= DINODE1_SIZE; 481 LFS_WRITESEGENTRY(sup, fs, oldsn, bp); /* Ifile */ 482 } 483} 484 485int 486findname(struct inodesc * idesc) 487{ 488 struct direct *dirp = idesc->id_dirp; 489 size_t len; 490 char *buf; 491 492 if (dirp->d_ino != idesc->id_parent) 493 return (KEEPON); 494 if ((len = dirp->d_namlen + 1) > MAXPATHLEN) { 495 /* Truncate it but don't overflow the buffer */ 496 len = MAXPATHLEN; 497 } 498 /* this is namebuf with utils.h */ 499 buf = __UNCONST(idesc->id_name); 500 (void)memcpy(buf, dirp->d_name, len); 501 return (STOP | FOUND); 502} 503 504int 505findino(struct inodesc * idesc) 506{ 507 struct direct *dirp = idesc->id_dirp; 508 509 if (dirp->d_ino == 0) 510 return (KEEPON); 511 if (strcmp(dirp->d_name, idesc->id_name) == 0 && 512 dirp->d_ino >= ROOTINO && dirp->d_ino < maxino) { 513 idesc->id_parent = dirp->d_ino; 514 return (STOP | FOUND); 515 } 516 return (KEEPON); 517} 518 519void 520pinode(ino_t ino) 521{ 522 struct ufs1_dinode *dp; 523 struct passwd *pw; 524 525 printf(" I=%llu ", (unsigned long long)ino); 526 if (ino < ROOTINO || ino >= maxino) 527 return; 528 dp = ginode(ino); 529 if (dp) { 530 printf(" OWNER="); 531#ifndef SMALL 532 if (Uflag && (pw = getpwuid((int) dp->di_uid)) != 0) 533 printf("%s ", pw->pw_name); 534 else 535#endif 536 printf("%u ", (unsigned) dp->di_uid); 537 printf("MODE=%o\n", dp->di_mode); 538 if (preen) 539 printf("%s: ", cdevname()); 540 printf("SIZE=%llu ", (unsigned long long) dp->di_size); 541 printf("MTIME=%s ", print_mtime(dp->di_mtime)); 542 } 543} 544 545void 546blkerror(ino_t ino, const char *type, daddr_t blk) 547{ 548 549 pfatal("%lld %s I=%llu", (long long) blk, type, 550 (unsigned long long)ino); 551 printf("\n"); 552 if (exitonfail) 553 exit(1); 554 switch (statemap[ino]) { 555 556 case FSTATE: 557 statemap[ino] = FCLEAR; 558 return; 559 560 case DSTATE: 561 statemap[ino] = DCLEAR; 562 return; 563 564 case FCLEAR: 565 case DCLEAR: 566 return; 567 568 default: 569 err(EEXIT, "BAD STATE %d TO BLKERR\n", statemap[ino]); 570 /* NOTREACHED */ 571 } 572} 573 574/* 575 * allocate an unused inode 576 */ 577ino_t 578allocino(ino_t request, int type) 579{ 580 ino_t ino; 581 struct ufs1_dinode *dp; 582 time_t t; 583 struct uvnode *vp; 584 struct ubuf *bp; 585 586 if (request == 0) 587 request = ROOTINO; 588 else if (statemap[request] != USTATE) 589 return (0); 590 for (ino = request; ino < maxino; ino++) 591 if (statemap[ino] == USTATE) 592 break; 593 if (ino == maxino) 594 extend_ifile(fs); 595 596 switch (type & IFMT) { 597 case IFDIR: 598 statemap[ino] = DSTATE; 599 break; 600 case IFREG: 601 case IFLNK: 602 statemap[ino] = FSTATE; 603 break; 604 default: 605 return (0); 606 } 607 vp = lfs_valloc(fs, ino); 608 if (vp == NULL) 609 return (0); 610 dp = (VTOI(vp)->i_din.ffs1_din); 611 bp = getblk(vp, 0, fs->lfs_fsize); 612 VOP_BWRITE(bp); 613 dp->di_mode = type; 614 (void) time(&t); 615 dp->di_atime = t; 616 dp->di_mtime = dp->di_ctime = dp->di_atime; 617 dp->di_size = fs->lfs_fsize; 618 dp->di_blocks = btofsb(fs, fs->lfs_fsize); 619 n_files++; 620 inodirty(VTOI(vp)); 621 typemap[ino] = IFTODT(type); 622 return (ino); 623} 624 625/* 626 * deallocate an inode 627 */ 628void 629freeino(ino_t ino) 630{ 631 struct inodesc idesc; 632 struct uvnode *vp; 633 634 memset(&idesc, 0, sizeof(struct inodesc)); 635 idesc.id_type = ADDR; 636 idesc.id_func = pass4check; 637 idesc.id_number = ino; 638 vp = vget(fs, ino); 639 (void) ckinode(VTOD(vp), &idesc); 640 clearinode(ino); 641 statemap[ino] = USTATE; 642 vnode_destroy(vp); 643 644 n_files--; 645} 646