fsck.h revision 98542
11558Srgrimes/* 298542Smckusick * Copyright (c) 2002 Networks Associates Technology, Inc. 398542Smckusick * All rights reserved. 498542Smckusick * 598542Smckusick * This software was developed for the FreeBSD Project by Marshall 698542Smckusick * Kirk McKusick and Network Associates Laboratories, the Security 798542Smckusick * Research Division of Network Associates, Inc. under DARPA/SPAWAR 898542Smckusick * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 998542Smckusick * research program 1098542Smckusick * 1198542Smckusick * Copyright (c) 1982, 1989, 1993 1298542Smckusick * The Regents of the University of California. All rights reserved. 1398542Smckusick * (c) UNIX System Laboratories, Inc. 141558Srgrimes * Copyright (c) 1980, 1986, 1993 151558Srgrimes * The Regents of the University of California. All rights reserved. 161558Srgrimes * 171558Srgrimes * Redistribution and use in source and binary forms, with or without 181558Srgrimes * modification, are permitted provided that the following conditions 191558Srgrimes * are met: 201558Srgrimes * 1. Redistributions of source code must retain the above copyright 211558Srgrimes * notice, this list of conditions and the following disclaimer. 221558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 231558Srgrimes * notice, this list of conditions and the following disclaimer in the 241558Srgrimes * documentation and/or other materials provided with the distribution. 251558Srgrimes * 3. All advertising materials mentioning features or use of this software 261558Srgrimes * must display the following acknowledgement: 271558Srgrimes * This product includes software developed by the University of 281558Srgrimes * California, Berkeley and its contributors. 291558Srgrimes * 4. Neither the name of the University nor the names of its contributors 301558Srgrimes * may be used to endorse or promote products derived from this software 311558Srgrimes * without specific prior written permission. 321558Srgrimes * 331558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 341558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 351558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 361558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 371558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 381558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 391558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 401558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 411558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 421558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 431558Srgrimes * SUCH DAMAGE. 441558Srgrimes * 4523675Speter * @(#)fsck.h 8.4 (Berkeley) 5/9/95 4655724Speter * $FreeBSD: head/sbin/fsck_ffs/fsck.h 98542 2002-06-21 06:18:05Z mckusick $ 471558Srgrimes */ 481558Srgrimes 4923675Speter#include <unistd.h> 5023675Speter#include <stdlib.h> 5123675Speter#include <stdio.h> 5223675Speter 531558Srgrimes#define MAXDUP 10 /* limit on dup blks (per inode) */ 541558Srgrimes#define MAXBAD 10 /* limit on bad blks (per inode) */ 551558Srgrimes#define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */ 561558Srgrimes#define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */ 571558Srgrimes 5898542Smckusickunion dinode { 5998542Smckusick struct ufs1_dinode dp1; 6098542Smckusick struct ufs2_dinode dp2; 6198542Smckusick}; 6298542Smckusick#define DIP(dp, field) \ 6398542Smckusick ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ 6498542Smckusick (dp)->dp1.field : (dp)->dp2.field) 6598542Smckusick 6641474Sjulian/* 6741474Sjulian * Each inode on the filesystem is described by the following structure. 6841474Sjulian * The linkcnt is initially set to the value in the inode. Each time it 6941474Sjulian * is found during the descent in passes 2, 3, and 4 the count is 7041474Sjulian * decremented. Any inodes whose count is non-zero after pass 4 needs to 7141474Sjulian * have its link count adjusted by the value remaining in ino_linkcnt. 7241474Sjulian */ 7341474Sjulianstruct inostat { 7441474Sjulian char ino_state; /* state of inode, see below */ 7541474Sjulian char ino_type; /* type of inode */ 7641474Sjulian short ino_linkcnt; /* number of links not found */ 7741474Sjulian}; 7841474Sjulian/* 7941474Sjulian * Inode states. 8041474Sjulian */ 811558Srgrimes#define USTATE 01 /* inode not allocated */ 821558Srgrimes#define FSTATE 02 /* inode is file */ 831558Srgrimes#define DSTATE 03 /* inode is directory */ 841558Srgrimes#define DFOUND 04 /* directory found during descent */ 851558Srgrimes#define DCLEAR 05 /* directory is to be cleared */ 861558Srgrimes#define FCLEAR 06 /* file is to be cleared */ 8741474Sjulian/* 8841474Sjulian * Inode state information is contained on per cylinder group lists 8941474Sjulian * which are described by the following structure. 9041474Sjulian */ 9141474Sjulianstruct inostatlist { 9241474Sjulian long il_numalloced; /* number of inodes allocated in this cg */ 9341474Sjulian struct inostat *il_stat;/* inostat info for this cylinder group */ 9441474Sjulian} *inostathead; 951558Srgrimes 961558Srgrimes/* 971558Srgrimes * buffer cache structure. 981558Srgrimes */ 991558Srgrimesstruct bufarea { 10023675Speter struct bufarea *b_next; /* free list queue */ 10123675Speter struct bufarea *b_prev; /* free list queue */ 10298542Smckusick ufs2_daddr_t b_bno; 10323675Speter int b_size; 10423675Speter int b_errs; 10523675Speter int b_flags; 1061558Srgrimes union { 10723675Speter char *b_buf; /* buffer space */ 10898542Smckusick ufs1_daddr_t *b_indir1; /* UFS1 indirect block */ 10998542Smckusick ufs2_daddr_t *b_indir2; /* UFS2 indirect block */ 11023675Speter struct fs *b_fs; /* super block */ 11123675Speter struct cg *b_cg; /* cylinder group */ 11298542Smckusick struct ufs1_dinode *b_dinode1; /* UFS1 inode block */ 11398542Smckusick struct ufs2_dinode *b_dinode2; /* UFS2 inode block */ 1141558Srgrimes } b_un; 11523675Speter char b_dirty; 1161558Srgrimes}; 11798542Smckusick#define IBLK(bp, i) \ 11898542Smckusick ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ 11998542Smckusick (bp)->b_un.b_indir1[i] : (bp)->b_un.b_indir2[i]) 1201558Srgrimes 1211558Srgrimes#define B_INUSE 1 1221558Srgrimes 1231558Srgrimes#define MINBUFS 5 /* minimum number of buffers required */ 1241558Srgrimesstruct bufarea bufhead; /* head of list of other blks in filesys */ 12596707Strhodesstruct bufarea sblk; /* filesystem superblock */ 1261558Srgrimesstruct bufarea cgblk; /* cylinder group blocks */ 1271558Srgrimesstruct bufarea *pdirbp; /* current directory contents */ 1281558Srgrimesstruct bufarea *pbp; /* current inode block */ 1291558Srgrimes 13086514Siedowse#define dirty(bp) do { \ 13174556Smckusick if (fswritefd < 0) \ 13274556Smckusick pfatal("SETTING DIRTY FLAG IN READ_ONLY MODE\n"); \ 13374556Smckusick else \ 13486514Siedowse (bp)->b_dirty = 1; \ 13586514Siedowse} while (0) 13686514Siedowse#define initbarea(bp) do { \ 1371558Srgrimes (bp)->b_dirty = 0; \ 13898542Smckusick (bp)->b_bno = (ufs2_daddr_t)-1; \ 13986514Siedowse (bp)->b_flags = 0; \ 14086514Siedowse} while (0) 1411558Srgrimes 14274556Smckusick#define sbdirty() dirty(&sblk) 14374556Smckusick#define cgdirty() dirty(&cgblk) 1441558Srgrimes#define sblock (*sblk.b_un.b_fs) 1451558Srgrimes#define cgrp (*cgblk.b_un.b_cg) 1461558Srgrimes 1471558Srgrimesenum fixstate {DONTKNOW, NOFIX, FIX, IGNORE}; 14862668Smckusickino_t cursnapshot; 1491558Srgrimes 1501558Srgrimesstruct inodesc { 1511558Srgrimes enum fixstate id_fix; /* policy on fixing errors */ 1521558Srgrimes int (*id_func)(); /* function to be applied to blocks of inode */ 1531558Srgrimes ino_t id_number; /* inode number described */ 1541558Srgrimes ino_t id_parent; /* for DATA nodes, their parent */ 15598542Smckusick ufs_lbn_t id_lbn; /* logical block number of current block */ 15698542Smckusick ufs2_daddr_t id_blkno; /* current block number being examined */ 1571558Srgrimes int id_numfrags; /* number of frags contained in block */ 15898542Smckusick off_t id_filesize; /* for DATA nodes, the size of the directory */ 15998542Smckusick ufs2_daddr_t id_entryno;/* for DATA nodes, current entry number */ 1601558Srgrimes int id_loc; /* for DATA nodes, current location in dir */ 1611558Srgrimes struct direct *id_dirp; /* for DATA nodes, ptr to current entry */ 1621558Srgrimes char *id_name; /* for DATA nodes, name to find or enter */ 1631558Srgrimes char id_type; /* type of descriptor, DATA or ADDR */ 1641558Srgrimes}; 1651558Srgrimes/* file types */ 16662668Smckusick#define DATA 1 /* a directory */ 16762668Smckusick#define SNAP 2 /* a snapshot */ 16862668Smckusick#define ADDR 3 /* anything but a directory or a snapshot */ 1691558Srgrimes 1701558Srgrimes/* 1711558Srgrimes * Linked list of duplicate blocks. 1728871Srgrimes * 1731558Srgrimes * The list is composed of two parts. The first part of the 1741558Srgrimes * list (from duplist through the node pointed to by muldup) 1758871Srgrimes * contains a single copy of each duplicate block that has been 1761558Srgrimes * found. The second part of the list (from muldup to the end) 1771558Srgrimes * contains duplicate blocks that have been found more than once. 1781558Srgrimes * To check if a block has been found as a duplicate it is only 1798871Srgrimes * necessary to search from duplist through muldup. To find the 1801558Srgrimes * total number of times that a block has been found as a duplicate 1811558Srgrimes * the entire list must be searched for occurences of the block 1821558Srgrimes * in question. The following diagram shows a sample list where 1831558Srgrimes * w (found twice), x (found once), y (found three times), and z 1841558Srgrimes * (found once) are duplicate block numbers: 1851558Srgrimes * 1861558Srgrimes * w -> y -> x -> z -> y -> w -> y 1871558Srgrimes * ^ ^ 1881558Srgrimes * | | 1891558Srgrimes * duplist muldup 1901558Srgrimes */ 1911558Srgrimesstruct dups { 1921558Srgrimes struct dups *next; 19398542Smckusick ufs2_daddr_t dup; 1941558Srgrimes}; 1951558Srgrimesstruct dups *duplist; /* head of dup list */ 1961558Srgrimesstruct dups *muldup; /* end of unique duplicate dup block numbers */ 1971558Srgrimes 1981558Srgrimes/* 1991558Srgrimes * Linked list of inodes with zero link counts. 2001558Srgrimes */ 2011558Srgrimesstruct zlncnt { 2021558Srgrimes struct zlncnt *next; 2031558Srgrimes ino_t zlncnt; 2041558Srgrimes}; 2051558Srgrimesstruct zlncnt *zlnhead; /* head of zero link count list */ 2061558Srgrimes 2071558Srgrimes/* 2081558Srgrimes * Inode cache data structures. 2091558Srgrimes */ 2101558Srgrimesstruct inoinfo { 2111558Srgrimes struct inoinfo *i_nexthash; /* next entry in hash chain */ 2121558Srgrimes ino_t i_number; /* inode number of this entry */ 2131558Srgrimes ino_t i_parent; /* inode number of parent */ 2141558Srgrimes ino_t i_dotdot; /* inode number of `..' */ 2151558Srgrimes size_t i_isize; /* size of inode */ 2161558Srgrimes u_int i_numblks; /* size of block array in bytes */ 21798542Smckusick ufs2_daddr_t i_blks[1]; /* actually longer */ 2181558Srgrimes} **inphead, **inpsort; 21957573Smckusicklong numdirs, dirhash, listmax, inplast; 22041474Sjulianlong countdirs; /* number of directories we actually found */ 2211558Srgrimes 22274556Smckusick#define MIBSIZE 3 /* size of fsck sysctl MIBs */ 22374556Smckusickint adjrefcnt[MIBSIZE]; /* MIB command to adjust inode reference cnt */ 22474556Smckusickint adjblkcnt[MIBSIZE]; /* MIB command to adjust inode block count */ 22574556Smckusickint freefiles[MIBSIZE]; /* MIB command to free a set of files */ 22674556Smckusickint freedirs[MIBSIZE]; /* MIB command to free a set of directories */ 22774556Smckusickint freeblks[MIBSIZE]; /* MIB command to free a set of data blocks */ 22874556Smckusickstruct fsck_cmd cmd; /* sysctl filesystem update commands */ 22974556Smckusickchar snapname[BUFSIZ]; /* when doing snapshots, the name of the file */ 2301558Srgrimeschar *cdevname; /* name of device being checked */ 2311558Srgrimeslong dev_bsize; /* computed value of DEV_BSIZE */ 2321558Srgrimeslong secsize; /* actual disk sector size */ 2331558Srgrimeschar nflag; /* assume a no response */ 2341558Srgrimeschar yflag; /* assume a yes response */ 23574556Smckusickint bkgrdflag; /* use a snapshot to run on an active system */ 2361558Srgrimesint bflag; /* location of alternate super block */ 2371558Srgrimesint debug; /* output debugging info */ 23896707Strhodesint cvtlevel; /* convert to newer filesystem format */ 23975927Smckusickint bkgrdcheck; /* determine if background check is possible */ 24034266Sjulianchar usedsoftdep; /* just fix soft dependency inconsistencies */ 24141474Sjulianchar preen; /* just fix normal inconsistencies */ 24241474Sjulianchar rerun; /* rerun fsck. Only used in non-preen mode */ 24341474Sjulianint returntosingle; /* 1 => return to single user mode on exit */ 24434266Sjulianchar resolved; /* cleared if unresolved changes => not clean */ 2451558Srgrimeschar havesb; /* superblock has been read */ 24696707Strhodeschar skipclean; /* skip clean filesystems if preening */ 24796707Strhodesint fsmodified; /* 1 => write done to filesystem */ 24896707Strhodesint fsreadfd; /* file descriptor for reading filesystem */ 24996707Strhodesint fswritefd; /* file descriptor for writing filesystem */ 2501558Srgrimes 25198542Smckusickufs2_daddr_t maxfsblock; /* number of blocks in the filesystem */ 2521558Srgrimeschar *blockmap; /* ptr to primary blk allocation map */ 25396707Strhodesino_t maxino; /* number of inodes in filesystem */ 2541558Srgrimes 2551558Srgrimesino_t lfdir; /* lost & found directory inode number */ 2561558Srgrimeschar *lfname; /* lost & found directory name */ 2571558Srgrimesint lfmode; /* lost & found directory creation mode */ 2581558Srgrimes 25998542Smckusickufs2_daddr_t n_blks; /* number of blocks in use */ 26098542Smckusickino_t n_files; /* number of files in use */ 2611558Srgrimes 26270050Siedowseint got_siginfo; /* received a SIGINFO */ 26370050Siedowse 26498542Smckusick#define clearinode(dp) \ 26598542Smckusick if (sblock.fs_magic == FS_UFS1_MAGIC) { \ 26698542Smckusick (dp)->dp1 = ufs1_zino; \ 26798542Smckusick } else { \ 26898542Smckusick (dp)->dp2 = ufs2_zino; \ 26998542Smckusick } 27098542Smckusickstruct ufs1_dinode ufs1_zino; 27198542Smckusickstruct ufs2_dinode ufs2_zino; 2721558Srgrimes 2731558Srgrimes#define setbmap(blkno) setbit(blockmap, blkno) 2741558Srgrimes#define testbmap(blkno) isset(blockmap, blkno) 2751558Srgrimes#define clrbmap(blkno) clrbit(blockmap, blkno) 2761558Srgrimes 2771558Srgrimes#define STOP 0x01 2781558Srgrimes#define SKIP 0x02 2791558Srgrimes#define KEEPON 0x04 2801558Srgrimes#define ALTERED 0x08 2811558Srgrimes#define FOUND 0x10 2821558Srgrimes 28323675Speter#define EEXIT 8 /* Standard error exit. */ 2847585Sbde 28523675Speterstruct fstab; 2867585Sbde 28741474Sjulian 28892839Simpvoid adjust(struct inodesc *, int lcnt); 28998542Smckusickufs2_daddr_t allocblk(long frags); 29092839Simpino_t allocdir(ino_t parent, ino_t request, int mode); 29192839Simpino_t allocino(ino_t request, int type); 29298542Smckusickvoid blkerror(ino_t ino, char *type, ufs2_daddr_t blk); 29392839Simpchar *blockcheck(char *name); 29498542Smckusickint bread(int fd, char *buf, ufs2_daddr_t blk, long size); 29592839Simpvoid bufinit(void); 29698542Smckusickvoid bwrite(int fd, char *buf, ufs2_daddr_t blk, long size); 29798542Smckusickvoid cacheino(union dinode *dp, ino_t inumber); 29892839Simpvoid catch(int); 29992839Simpvoid catchquit(int); 30092839Simpint changeino(ino_t dir, char *name, ino_t newnum); 30198542Smckusickint chkrange(ufs2_daddr_t blk, int cnt); 30292839Simpvoid ckfini(int markclean); 30398542Smckusickint ckinode(union dinode *dp, struct inodesc *); 30492839Simpvoid clri(struct inodesc *, char *type, int flag); 30592839Simpint clearentry(struct inodesc *); 30692839Simpvoid direrror(ino_t ino, char *errmesg); 30792839Simpint dirscan(struct inodesc *); 30892839Simpint dofix(struct inodesc *, char *msg); 30998542Smckusickvoid ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t); 31092839Simpvoid ffs_fragacct(struct fs *, int, int32_t [], int); 31198542Smckusickint ffs_isblock(struct fs *, u_char *, ufs1_daddr_t); 31298542Smckusickvoid ffs_setblock(struct fs *, u_char *, ufs1_daddr_t); 31392839Simpvoid fileerror(ino_t cwd, ino_t ino, char *errmesg); 31492839Simpint findino(struct inodesc *); 31592839Simpint findname(struct inodesc *); 31692839Simpvoid flush(int fd, struct bufarea *bp); 31798542Smckusickvoid freeblk(ufs2_daddr_t blkno, long frags); 31892839Simpvoid freeino(ino_t ino); 31992839Simpvoid freeinodebuf(void); 32098542Smckusickint ftypeok(union dinode *dp); 32198542Smckusickvoid getblk(struct bufarea *bp, ufs2_daddr_t blk, long size); 32298542Smckusickstruct bufarea *getdatablk(ufs2_daddr_t blkno, long size); 32392839Simpstruct inoinfo *getinoinfo(ino_t inumber); 32498542Smckusickunion dinode *getnextinode(ino_t inumber); 32592839Simpvoid getpathname(char *namebuf, ino_t curdir, ino_t ino); 32698542Smckusickunion dinode *ginode(ino_t inumber); 32792839Simpvoid infohandler(int sig); 32892839Simpvoid inocleanup(void); 32992839Simpvoid inodirty(void); 33092839Simpstruct inostat *inoinfo(ino_t inum); 33192839Simpint linkup(ino_t orphan, ino_t parentdir, char *name); 33292839Simpint makeentry(ino_t parent, ino_t ino, char *name); 33392839Simpvoid panic(const char *fmt, ...) __printflike(1, 2); 33492839Simpvoid pass1(void); 33592839Simpvoid pass1b(void); 33692839Simpint pass1check(struct inodesc *); 33792839Simpvoid pass2(void); 33892839Simpvoid pass3(void); 33992839Simpvoid pass4(void); 34092839Simpint pass4check(struct inodesc *); 34192839Simpvoid pass5(void); 34292839Simpvoid pfatal(const char *fmt, ...) __printflike(1, 2); 34392839Simpvoid pinode(ino_t ino); 34492839Simpvoid propagate(void); 34592839Simpvoid pwarn(const char *fmt, ...) __printflike(1, 2); 34692839Simpint readsb(int listerr); 34792839Simpint reply(char *question); 34898542Smckusickvoid rwerror(char *mesg, ufs2_daddr_t blk); 34992839Simpvoid sblock_init(void); 35092839Simpvoid setinodebuf(ino_t); 35192839Simpint setup(char *dev); 352