17c478bd9Sstevel@tonic-gate /* 2*77a343abSabalfour * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 147c478bd9Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright 157c478bd9Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display 167c478bd9Sstevel@tonic-gate * the following acknowledgement: ``This product includes software 177c478bd9Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors'' 187c478bd9Sstevel@tonic-gate * in the documentation or other materials provided with the distribution 197c478bd9Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this 207c478bd9Sstevel@tonic-gate * software. Neither the name of the University nor the names of its 217c478bd9Sstevel@tonic-gate * contributors may be used to endorse or promote products derived 227c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 237c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 247c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 257c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 30355d6bb5Sswilcox #include <stdio.h> 31355d6bb5Sswilcox #include <stdlib.h> 32355d6bb5Sswilcox #include <unistd.h> 337c478bd9Sstevel@tonic-gate #include <sys/param.h> 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 367c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h> 377c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 387c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h> 397c478bd9Sstevel@tonic-gate #include "fsck.h" 407c478bd9Sstevel@tonic-gate 41355d6bb5Sswilcox void 42355d6bb5Sswilcox pass4(void) 437c478bd9Sstevel@tonic-gate { 44355d6bb5Sswilcox fsck_ino_t inumber; 457c478bd9Sstevel@tonic-gate struct dinode *dp; 467c478bd9Sstevel@tonic-gate struct inodesc idesc; 47355d6bb5Sswilcox int n, was_dir; 48355d6bb5Sswilcox int need_rescan; 49355d6bb5Sswilcox int scan_pass = 0; 507c478bd9Sstevel@tonic-gate 51355d6bb5Sswilcox /* 52355d6bb5Sswilcox * If we clear a directory, it may have produced orphans which 53355d6bb5Sswilcox * we need to go pick up. So, do this until done. It can be 54355d6bb5Sswilcox * proven that the loop terminates because at most there can 55355d6bb5Sswilcox * be lastino directories, and we only rescan if we clear a 56355d6bb5Sswilcox * directory. 57355d6bb5Sswilcox */ 58355d6bb5Sswilcox do { 59355d6bb5Sswilcox if (debug) 60355d6bb5Sswilcox (void) printf("pass4 scan %d\n", scan_pass++); 61355d6bb5Sswilcox 62355d6bb5Sswilcox need_rescan = 0; 63355d6bb5Sswilcox for (inumber = UFSROOTINO; inumber <= lastino; inumber++) { 64355d6bb5Sswilcox init_inodesc(&idesc); 657c478bd9Sstevel@tonic-gate idesc.id_type = ADDR; 667c478bd9Sstevel@tonic-gate idesc.id_func = pass4check; 677c478bd9Sstevel@tonic-gate idesc.id_number = inumber; 68355d6bb5Sswilcox 69355d6bb5Sswilcox was_dir = (statemap[inumber] & DSTATE) == DSTATE; 70355d6bb5Sswilcox 71355d6bb5Sswilcox switch (statemap[inumber] & ~(INORPHAN | INDELAYD 72355d6bb5Sswilcox | INZLINK)) { 73355d6bb5Sswilcox 74355d6bb5Sswilcox case FZLINK: 75355d6bb5Sswilcox case DZLINK: 76355d6bb5Sswilcox /* 77355d6bb5Sswilcox * INZLINK gets set if the inode claimed zero 78355d6bb5Sswilcox * links when we first looked at it in pass 1. 79355d6bb5Sswilcox * If lncntp[] also claims it has zero links, 80355d6bb5Sswilcox * it really is unreferenced. However, we 81355d6bb5Sswilcox * could have found a link to it during one of 82355d6bb5Sswilcox * the other passes, so we have to check the 83355d6bb5Sswilcox * final count in lncntp[]. 84355d6bb5Sswilcox */ 85355d6bb5Sswilcox if (lncntp[inumber] == 0) { 86355d6bb5Sswilcox clri(&idesc, "UNREF", CLRI_VERBOSE, 87355d6bb5Sswilcox CLRI_NOP_OK); 88355d6bb5Sswilcox if (was_dir && 89355d6bb5Sswilcox (statemap[inumber] == USTATE)) 90355d6bb5Sswilcox need_rescan = 1; 91355d6bb5Sswilcox break; 92355d6bb5Sswilcox } 93355d6bb5Sswilcox /* FALLTHROUGH */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate case FSTATE: 967c478bd9Sstevel@tonic-gate case DFOUND: 97355d6bb5Sswilcox case SSTATE: 987c478bd9Sstevel@tonic-gate n = lncntp[inumber]; 99355d6bb5Sswilcox if (n || (statemap[inumber] & 100355d6bb5Sswilcox (INDELAYD | INZLINK))) { 101355d6bb5Sswilcox /* 102355d6bb5Sswilcox * adjust() will clear the inode if 103355d6bb5Sswilcox * the link count goes to zero. If 104355d6bb5Sswilcox * it isn't cleared, we need to note 105355d6bb5Sswilcox * that we've adjusted the count 106355d6bb5Sswilcox * already, so we don't do it again 107355d6bb5Sswilcox * on a rescan. 108355d6bb5Sswilcox */ 109355d6bb5Sswilcox adjust(&idesc, n); 110355d6bb5Sswilcox if (was_dir && 111355d6bb5Sswilcox (statemap[inumber] == USTATE)) { 112355d6bb5Sswilcox need_rescan = 1; 113355d6bb5Sswilcox } else { 114355d6bb5Sswilcox TRACK_LNCNTP(inumber, 115355d6bb5Sswilcox lncntp[inumber] = 0); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate break; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate case DSTATE: 121355d6bb5Sswilcox clri(&idesc, "UNREF", CLRI_VERBOSE, 122355d6bb5Sswilcox CLRI_NOP_OK); 123355d6bb5Sswilcox if (was_dir && (statemap[inumber] == USTATE)) 124355d6bb5Sswilcox need_rescan = 1; 1257c478bd9Sstevel@tonic-gate break; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate case DCLEAR: 1287c478bd9Sstevel@tonic-gate dp = ginode(inumber); 1297c478bd9Sstevel@tonic-gate if (dp->di_size == 0) { 130355d6bb5Sswilcox clri(&idesc, "ZERO LENGTH", 131355d6bb5Sswilcox CLRI_VERBOSE, CLRI_NOP_CORRUPT); 1327c478bd9Sstevel@tonic-gate break; 1337c478bd9Sstevel@tonic-gate } 134355d6bb5Sswilcox /* FALLTHROUGH */ 135355d6bb5Sswilcox 1367c478bd9Sstevel@tonic-gate case FCLEAR: 137355d6bb5Sswilcox clri(&idesc, "BAD/DUP", CLRI_VERBOSE, 138355d6bb5Sswilcox CLRI_NOP_CORRUPT); 1397c478bd9Sstevel@tonic-gate break; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate case SCLEAR: 142355d6bb5Sswilcox clri(&idesc, "BAD", CLRI_VERBOSE, 143355d6bb5Sswilcox CLRI_NOP_CORRUPT); 1447c478bd9Sstevel@tonic-gate break; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate case USTATE: 1477c478bd9Sstevel@tonic-gate break; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate default: 150355d6bb5Sswilcox errexit("BAD STATE 0x%x FOR INODE I=%d", 151355d6bb5Sswilcox (int)statemap[inumber], inumber); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate } 154355d6bb5Sswilcox } while (need_rescan); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 157355d6bb5Sswilcox int 158355d6bb5Sswilcox pass4check(struct inodesc *idesc) 1597c478bd9Sstevel@tonic-gate { 160355d6bb5Sswilcox int fragnum, cg_frag; 1617c478bd9Sstevel@tonic-gate int res = KEEPON; 1627c478bd9Sstevel@tonic-gate daddr32_t blkno = idesc->id_blkno; 163355d6bb5Sswilcox int cylno; 164355d6bb5Sswilcox struct cg *cgp = &cgrp; 165355d6bb5Sswilcox caddr_t err; 1667c478bd9Sstevel@tonic-gate 167355d6bb5Sswilcox if ((idesc->id_truncto >= 0) && (idesc->id_lbn < idesc->id_truncto)) { 168355d6bb5Sswilcox if (debug) 169355d6bb5Sswilcox (void) printf( 170355d6bb5Sswilcox "pass4check: skipping inode %d lbn %d with truncto %d\n", 171355d6bb5Sswilcox idesc->id_number, idesc->id_lbn, 172355d6bb5Sswilcox idesc->id_truncto); 173355d6bb5Sswilcox return (KEEPON); 1747c478bd9Sstevel@tonic-gate } 175355d6bb5Sswilcox 176355d6bb5Sswilcox for (fragnum = 0; fragnum < idesc->id_numfrags; fragnum++) { 177355d6bb5Sswilcox if (chkrange(blkno + fragnum, 1)) { 178355d6bb5Sswilcox res = SKIP; 179355d6bb5Sswilcox } else if (testbmap(blkno + fragnum)) { 180355d6bb5Sswilcox /* 181355d6bb5Sswilcox * The block's in use. Remove our reference 182355d6bb5Sswilcox * from it. 183355d6bb5Sswilcox * 184355d6bb5Sswilcox * If it wasn't a dup, or everybody's done with 185355d6bb5Sswilcox * it, then this is the last reference and it's 186355d6bb5Sswilcox * safe to actually deallocate the on-disk block. 187355d6bb5Sswilcox * 188355d6bb5Sswilcox * We depend on pass 5 resolving the on-disk bitmap 189355d6bb5Sswilcox * effects. 190355d6bb5Sswilcox */ 191355d6bb5Sswilcox cg_frag = blkno + fragnum; 192355d6bb5Sswilcox if (!find_dup_ref(cg_frag, idesc->id_number, 193355d6bb5Sswilcox idesc->id_lbn * sblock.fs_frag + fragnum, 194355d6bb5Sswilcox DB_DECR)) { 195355d6bb5Sswilcox 196355d6bb5Sswilcox if (debug) 197355d6bb5Sswilcox (void) printf("p4c marking %d avail\n", 198355d6bb5Sswilcox cg_frag); 199355d6bb5Sswilcox clrbmap(cg_frag); 2007c478bd9Sstevel@tonic-gate n_blks--; 201355d6bb5Sswilcox 202355d6bb5Sswilcox /* 203355d6bb5Sswilcox * Do the same for the on-disk bitmap, so 204355d6bb5Sswilcox * that we don't need another pass to figure 205355d6bb5Sswilcox * out what's really being used. We'll let 206355d6bb5Sswilcox * pass5() work out the fragment/block 207355d6bb5Sswilcox * accounting. 208355d6bb5Sswilcox */ 209355d6bb5Sswilcox cylno = dtog(&sblock, cg_frag); 210355d6bb5Sswilcox (void) getblk(&cgblk, cgtod(&sblock, cylno), 211355d6bb5Sswilcox (size_t)sblock.fs_cgsize); 212*77a343abSabalfour err = cg_sanity(cgp, cylno); 213355d6bb5Sswilcox if (err != NULL) { 214355d6bb5Sswilcox pfatal("CG %d: %s\n", cylno, err); 215355d6bb5Sswilcox free((void *)err); 216355d6bb5Sswilcox if (reply("REPAIR") == 0) 217355d6bb5Sswilcox errexit("Program terminated."); 218355d6bb5Sswilcox fix_cg(cgp, cylno); 219355d6bb5Sswilcox } 220355d6bb5Sswilcox clrbit(cg_blksfree(cgp), 221355d6bb5Sswilcox dtogd(&sblock, cg_frag)); 222355d6bb5Sswilcox cgdirty(); 223355d6bb5Sswilcox 224355d6bb5Sswilcox res |= ALTERED; 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate return (res); 2297c478bd9Sstevel@tonic-gate } 230