diff options
Diffstat (limited to 'sbin/fsck_ffs')
-rw-r--r-- | sbin/fsck_ffs/dir.c | 86 | ||||
-rw-r--r-- | sbin/fsck_ffs/fsck.h | 95 | ||||
-rw-r--r-- | sbin/fsck_ffs/fsutil.c | 28 | ||||
-rw-r--r-- | sbin/fsck_ffs/inode.c | 189 | ||||
-rw-r--r-- | sbin/fsck_ffs/main.c | 20 | ||||
-rw-r--r-- | sbin/fsck_ffs/pass1.c | 125 | ||||
-rw-r--r-- | sbin/fsck_ffs/pass1b.c | 4 | ||||
-rw-r--r-- | sbin/fsck_ffs/pass2.c | 38 | ||||
-rw-r--r-- | sbin/fsck_ffs/pass4.c | 6 | ||||
-rw-r--r-- | sbin/fsck_ffs/pass5.c | 149 | ||||
-rw-r--r-- | sbin/fsck_ffs/setup.c | 111 |
11 files changed, 477 insertions, 374 deletions
diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c index 9a3eee4..7ab051d 100644 --- a/sbin/fsck_ffs/dir.c +++ b/sbin/fsck_ffs/dir.c @@ -69,10 +69,10 @@ struct odirtemplate odirhead = { static int chgino(struct inodesc *); static int dircheck(struct inodesc *, struct direct *); -static int expanddir(struct dinode *dp, char *name); +static int expanddir(union dinode *dp, char *name); static void freedir(ino_t ino, ino_t parent); static struct direct *fsck_readdir(struct inodesc *); -static struct bufarea *getdirblk(ufs_daddr_t blkno, long size); +static struct bufarea *getdirblk(ufs2_daddr_t blkno, long size); static int lftempname(char *bufp, ino_t ino); static int mkentry(struct inodesc *); @@ -255,7 +255,7 @@ direrror(ino_t ino, char *errmesg) void fileerror(ino_t cwd, ino_t ino, char *errmesg) { - struct dinode *dp; + union dinode *dp; char pathbuf[MAXPATHLEN + 1]; pwarn("%s ", errmesg); @@ -269,7 +269,8 @@ fileerror(ino_t cwd, ino_t ino, char *errmesg) dp = ginode(ino); if (ftypeok(dp)) pfatal("%s=%s\n", - (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf); + (DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE", + pathbuf); else pfatal("NAME=%s\n", pathbuf); } @@ -277,11 +278,11 @@ fileerror(ino_t cwd, ino_t ino, char *errmesg) void adjust(struct inodesc *idesc, int lcnt) { - struct dinode *dp; + union dinode *dp; int saveresolved; dp = ginode(idesc->id_number); - if (dp->di_nlink == lcnt) { + if (DIP(dp, di_nlink) == lcnt) { /* * If we have not hit any unresolved problems, are running * in preen mode, and are on a filesystem using soft updates, @@ -312,10 +313,10 @@ adjust(struct inodesc *idesc, int lcnt) } if (lcnt != 0) { pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : - ((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE")); + ((DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE")); pinode(idesc->id_number); printf(" COUNT %d SHOULD BE %d", - dp->di_nlink, dp->di_nlink - lcnt); + DIP(dp, di_nlink), DIP(dp, di_nlink) - lcnt); if (preen || usedsoftdep) { if (lcnt < 0) { printf("\n"); @@ -326,7 +327,7 @@ adjust(struct inodesc *idesc, int lcnt) } if (preen || reply("ADJUST") == 1) { if (bkgrdflag == 0) { - dp->di_nlink -= lcnt; + DIP(dp, di_nlink) -= lcnt; inodirty(); } else { cmd.value = idesc->id_number; @@ -383,7 +384,7 @@ chgino(struct inodesc *idesc) int linkup(ino_t orphan, ino_t parentdir, char *name) { - struct dinode *dp; + union dinode *dp; int lostdir; ino_t oldlfdir; struct inodesc idesc; @@ -391,10 +392,10 @@ linkup(ino_t orphan, ino_t parentdir, char *name) memset(&idesc, 0, sizeof(struct inodesc)); dp = ginode(orphan); - lostdir = (dp->di_mode & IFMT) == IFDIR; + lostdir = (DIP(dp, di_mode) & IFMT) == IFDIR; pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); pinode(orphan); - if (preen && dp->di_size == 0) + if (preen && DIP(dp, di_size) == 0) return (0); if (cursnapshot != 0) { pfatal("FILE LINKUP IN SNAPSHOT"); @@ -438,7 +439,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name) } } dp = ginode(lfdir); - if ((dp->di_mode & IFMT) != IFDIR) { + if ((DIP(dp, di_mode) & IFMT) != IFDIR) { pfatal("lost+found IS NOT A DIRECTORY"); if (reply("REALLOCATE") == 0) return (0); @@ -475,7 +476,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name) parentdir != (ino_t)-1) (void)makeentry(orphan, lfdir, ".."); dp = ginode(lfdir); - dp->di_nlink++; + DIP(dp, di_nlink)++; inodirty(); inoinfo(lfdir)->ino_linkcnt++; pwarn("DIR I=%lu CONNECTED. ", (u_long)orphan); @@ -520,7 +521,7 @@ changeino(ino_t dir, char *name, ino_t newnum) int makeentry(ino_t parent, ino_t ino, char *name) { - struct dinode *dp; + union dinode *dp; struct inodesc idesc; char pathbuf[MAXPATHLEN + 1]; @@ -535,8 +536,8 @@ makeentry(ino_t parent, ino_t ino, char *name) idesc.id_fix = DONTKNOW; idesc.id_name = name; dp = ginode(parent); - if (dp->di_size % DIRBLKSIZ) { - dp->di_size = roundup(dp->di_size, DIRBLKSIZ); + if (DIP(dp, di_size) % DIRBLKSIZ) { + DIP(dp, di_size) = roundup(DIP(dp, di_size), DIRBLKSIZ); inodirty(); } if ((ckinode(dp, &idesc) & ALTERED) != 0) @@ -552,23 +553,24 @@ makeentry(ino_t parent, ino_t ino, char *name) * Attempt to expand the size of a directory */ static int -expanddir(struct dinode *dp, char *name) +expanddir(union dinode *dp, char *name) { - ufs_daddr_t lastbn, newblk; + ufs2_daddr_t lastbn, newblk; struct bufarea *bp; char *cp, firstblk[DIRBLKSIZ]; - lastbn = lblkno(&sblock, dp->di_size); - if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0) + lastbn = lblkno(&sblock, DIP(dp, di_size)); + if (lastbn >= NDADDR - 1 || DIP(dp, di_db[lastbn]) == 0 || + DIP(dp, di_size) == 0) return (0); if ((newblk = allocblk(sblock.fs_frag)) == 0) return (0); - dp->di_db[lastbn + 1] = dp->di_db[lastbn]; - dp->di_db[lastbn] = newblk; - dp->di_size += sblock.fs_bsize; - dp->di_blocks += btodb(sblock.fs_bsize); - bp = getdirblk(dp->di_db[lastbn + 1], - (long)dblksize(&sblock, dp, lastbn + 1)); + DIP(dp, di_db[lastbn + 1]) = DIP(dp, di_db[lastbn]); + DIP(dp, di_db[lastbn]) = newblk; + DIP(dp, di_size) += sblock.fs_bsize; + DIP(dp, di_blocks) += btodb(sblock.fs_bsize); + bp = getdirblk(DIP(dp, di_db[lastbn + 1]), + sblksize(&sblock, DIP(dp, di_size), lastbn + 1)); if (bp->b_errs) goto bad; memmove(firstblk, bp->b_un.b_buf, DIRBLKSIZ); @@ -581,8 +583,8 @@ expanddir(struct dinode *dp, char *name) cp += DIRBLKSIZ) memmove(cp, &emptydir, sizeof emptydir); dirty(bp); - bp = getdirblk(dp->di_db[lastbn + 1], - (long)dblksize(&sblock, dp, lastbn + 1)); + bp = getdirblk(DIP(dp, di_db[lastbn + 1]), + sblksize(&sblock, DIP(dp, di_size), lastbn + 1)); if (bp->b_errs) goto bad; memmove(bp->b_un.b_buf, &emptydir, sizeof emptydir); @@ -595,10 +597,10 @@ expanddir(struct dinode *dp, char *name) inodirty(); return (1); bad: - dp->di_db[lastbn] = dp->di_db[lastbn + 1]; - dp->di_db[lastbn + 1] = 0; - dp->di_size -= sblock.fs_bsize; - dp->di_blocks -= btodb(sblock.fs_bsize); + DIP(dp, di_db[lastbn]) = DIP(dp, di_db[lastbn + 1]); + DIP(dp, di_db[lastbn + 1]) = 0; + DIP(dp, di_size) -= sblock.fs_bsize; + DIP(dp, di_blocks) -= btodb(sblock.fs_bsize); freeblk(newblk, sblock.fs_frag); return (0); } @@ -611,7 +613,7 @@ allocdir(ino_t parent, ino_t request, int mode) { ino_t ino; char *cp; - struct dinode *dp; + union dinode *dp; struct bufarea *bp; struct inoinfo *inp; struct dirtemplate *dirp; @@ -621,7 +623,7 @@ allocdir(ino_t parent, ino_t request, int mode) dirp->dot_ino = ino; dirp->dotdot_ino = parent; dp = ginode(ino); - bp = getdirblk(dp->di_db[0], sblock.fs_fsize); + bp = getdirblk(DIP(dp, di_db[0]), sblock.fs_fsize); if (bp->b_errs) { freeino(ino); return (0); @@ -632,10 +634,10 @@ allocdir(ino_t parent, ino_t request, int mode) cp += DIRBLKSIZ) memmove(cp, &emptydir, sizeof emptydir); dirty(bp); - dp->di_nlink = 2; + DIP(dp, di_nlink) = 2; inodirty(); if (ino == ROOTINO) { - inoinfo(ino)->ino_linkcnt = dp->di_nlink; + inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink); cacheino(dp, ino); return(ino); } @@ -650,11 +652,11 @@ allocdir(ino_t parent, ino_t request, int mode) inp->i_dotdot = parent; inoinfo(ino)->ino_state = inoinfo(parent)->ino_state; if (inoinfo(ino)->ino_state == DSTATE) { - inoinfo(ino)->ino_linkcnt = dp->di_nlink; + inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink); inoinfo(parent)->ino_linkcnt++; } dp = ginode(parent); - dp->di_nlink++; + DIP(dp, di_nlink)++; inodirty(); return (ino); } @@ -665,11 +667,11 @@ allocdir(ino_t parent, ino_t request, int mode) static void freedir(ino_t ino, ino_t parent) { - struct dinode *dp; + union dinode *dp; if (ino != parent) { dp = ginode(parent); - dp->di_nlink--; + DIP(dp, di_nlink)--; inodirty(); } freeino(ino); @@ -704,7 +706,7 @@ lftempname(char *bufp, ino_t ino) * Insure that it is held until another is requested. */ static struct bufarea * -getdirblk(ufs_daddr_t blkno, long size) +getdirblk(ufs2_daddr_t blkno, long size) { if (pdirbp != 0) diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 2df0cd8..efe7fb5 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -1,4 +1,16 @@ /* + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by Marshall + * Kirk McKusick and Network Associates Laboratories, the Security + * Research Division of Network Associates, Inc. under DARPA/SPAWAR + * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS + * research program + * + * Copyright (c) 1982, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. * Copyright (c) 1980, 1986, 1993 * The Regents of the University of California. All rights reserved. * @@ -43,6 +55,14 @@ #define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */ #define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */ +union dinode { + struct ufs1_dinode dp1; + struct ufs2_dinode dp2; +}; +#define DIP(dp, field) \ + ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ + (dp)->dp1.field : (dp)->dp2.field) + /* * Each inode on the filesystem is described by the following structure. * The linkcnt is initially set to the value in the inode. Each time it @@ -79,19 +99,24 @@ struct inostatlist { struct bufarea { struct bufarea *b_next; /* free list queue */ struct bufarea *b_prev; /* free list queue */ - ufs_daddr_t b_bno; + ufs2_daddr_t b_bno; int b_size; int b_errs; int b_flags; union { char *b_buf; /* buffer space */ - ufs_daddr_t *b_indir; /* indirect block */ + ufs1_daddr_t *b_indir1; /* UFS1 indirect block */ + ufs2_daddr_t *b_indir2; /* UFS2 indirect block */ struct fs *b_fs; /* super block */ struct cg *b_cg; /* cylinder group */ - struct dinode *b_dinode; /* inode block */ + struct ufs1_dinode *b_dinode1; /* UFS1 inode block */ + struct ufs2_dinode *b_dinode2; /* UFS2 inode block */ } b_un; char b_dirty; }; +#define IBLK(bp, i) \ + ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ + (bp)->b_un.b_indir1[i] : (bp)->b_un.b_indir2[i]) #define B_INUSE 1 @@ -110,7 +135,7 @@ struct bufarea *pbp; /* current inode block */ } while (0) #define initbarea(bp) do { \ (bp)->b_dirty = 0; \ - (bp)->b_bno = (ufs_daddr_t)-1; \ + (bp)->b_bno = (ufs2_daddr_t)-1; \ (bp)->b_flags = 0; \ } while (0) @@ -127,12 +152,12 @@ struct inodesc { int (*id_func)(); /* function to be applied to blocks of inode */ ino_t id_number; /* inode number described */ ino_t id_parent; /* for DATA nodes, their parent */ - int id_lbn; /* logical block number of current block */ - ufs_daddr_t id_blkno; /* current block number being examined */ + ufs_lbn_t id_lbn; /* logical block number of current block */ + ufs2_daddr_t id_blkno; /* current block number being examined */ int id_numfrags; /* number of frags contained in block */ - quad_t id_filesize; /* for DATA nodes, the size of the directory */ + off_t id_filesize; /* for DATA nodes, the size of the directory */ + ufs2_daddr_t id_entryno;/* for DATA nodes, current entry number */ int id_loc; /* for DATA nodes, current location in dir */ - int id_entryno; /* for DATA nodes, current entry number */ struct direct *id_dirp; /* for DATA nodes, ptr to current entry */ char *id_name; /* for DATA nodes, name to find or enter */ char id_type; /* type of descriptor, DATA or ADDR */ @@ -165,7 +190,7 @@ struct inodesc { */ struct dups { struct dups *next; - ufs_daddr_t dup; + ufs2_daddr_t dup; }; struct dups *duplist; /* head of dup list */ struct dups *muldup; /* end of unique duplicate dup block numbers */ @@ -189,7 +214,7 @@ struct inoinfo { ino_t i_dotdot; /* inode number of `..' */ size_t i_isize; /* size of inode */ u_int i_numblks; /* size of block array in bytes */ - ufs_daddr_t i_blks[1]; /* actually longer */ + ufs2_daddr_t i_blks[1]; /* actually longer */ } **inphead, **inpsort; long numdirs, dirhash, listmax, inplast; long countdirs; /* number of directories we actually found */ @@ -223,7 +248,7 @@ int fsmodified; /* 1 => write done to filesystem */ int fsreadfd; /* file descriptor for reading filesystem */ int fswritefd; /* file descriptor for writing filesystem */ -ufs_daddr_t maxfsblock; /* number of blocks in the filesystem */ +ufs2_daddr_t maxfsblock; /* number of blocks in the filesystem */ char *blockmap; /* ptr to primary blk allocation map */ ino_t maxino; /* number of inodes in filesystem */ @@ -231,13 +256,19 @@ ino_t lfdir; /* lost & found directory inode number */ char *lfname; /* lost & found directory name */ int lfmode; /* lost & found directory creation mode */ -ufs_daddr_t n_blks; /* number of blocks in use */ -ufs_daddr_t n_files; /* number of files in use */ +ufs2_daddr_t n_blks; /* number of blocks in use */ +ino_t n_files; /* number of files in use */ int got_siginfo; /* received a SIGINFO */ -#define clearinode(dp) (*(dp) = zino) -struct dinode zino; +#define clearinode(dp) \ + if (sblock.fs_magic == FS_UFS1_MAGIC) { \ + (dp)->dp1 = ufs1_zino; \ + } else { \ + (dp)->dp2 = ufs2_zino; \ + } +struct ufs1_dinode ufs1_zino; +struct ufs2_dinode ufs2_zino; #define setbmap(blkno) setbit(blockmap, blkno) #define testbmap(blkno) isset(blockmap, blkno) @@ -255,44 +286,44 @@ struct fstab; void adjust(struct inodesc *, int lcnt); -ufs_daddr_t allocblk(long frags); +ufs2_daddr_t allocblk(long frags); ino_t allocdir(ino_t parent, ino_t request, int mode); ino_t allocino(ino_t request, int type); -void blkerror(ino_t ino, char *type, ufs_daddr_t blk); +void blkerror(ino_t ino, char *type, ufs2_daddr_t blk); char *blockcheck(char *name); -int bread(int fd, char *buf, ufs_daddr_t blk, long size); +int bread(int fd, char *buf, ufs2_daddr_t blk, long size); void bufinit(void); -void bwrite(int fd, char *buf, ufs_daddr_t blk, long size); -void cacheino(struct dinode *dp, ino_t inumber); +void bwrite(int fd, char *buf, ufs2_daddr_t blk, long size); +void cacheino(union dinode *dp, ino_t inumber); void catch(int); void catchquit(int); int changeino(ino_t dir, char *name, ino_t newnum); -int chkrange(ufs_daddr_t blk, int cnt); +int chkrange(ufs2_daddr_t blk, int cnt); void ckfini(int markclean); -int ckinode(struct dinode *dp, struct inodesc *); +int ckinode(union dinode *dp, struct inodesc *); void clri(struct inodesc *, char *type, int flag); int clearentry(struct inodesc *); void direrror(ino_t ino, char *errmesg); int dirscan(struct inodesc *); int dofix(struct inodesc *, char *msg); -void ffs_clrblock(struct fs *, u_char *, ufs_daddr_t); +void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t); void ffs_fragacct(struct fs *, int, int32_t [], int); -int ffs_isblock(struct fs *, u_char *, ufs_daddr_t); -void ffs_setblock(struct fs *, u_char *, ufs_daddr_t); +int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t); +void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t); void fileerror(ino_t cwd, ino_t ino, char *errmesg); int findino(struct inodesc *); int findname(struct inodesc *); void flush(int fd, struct bufarea *bp); -void freeblk(ufs_daddr_t blkno, long frags); +void freeblk(ufs2_daddr_t blkno, long frags); void freeino(ino_t ino); void freeinodebuf(void); -int ftypeok(struct dinode *dp); -void getblk(struct bufarea *bp, ufs_daddr_t blk, long size); -struct bufarea *getdatablk(ufs_daddr_t blkno, long size); +int ftypeok(union dinode *dp); +void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size); +struct bufarea *getdatablk(ufs2_daddr_t blkno, long size); struct inoinfo *getinoinfo(ino_t inumber); -struct dinode *getnextinode(ino_t inumber); +union dinode *getnextinode(ino_t inumber); void getpathname(char *namebuf, ino_t curdir, ino_t ino); -struct dinode *ginode(ino_t inumber); +union dinode *ginode(ino_t inumber); void infohandler(int sig); void inocleanup(void); void inodirty(void); @@ -314,7 +345,7 @@ void propagate(void); void pwarn(const char *fmt, ...) __printflike(1, 2); int readsb(int listerr); int reply(char *question); -void rwerror(char *mesg, ufs_daddr_t blk); +void rwerror(char *mesg, ufs2_daddr_t blk); void sblock_init(void); void setinodebuf(ino_t); int setup(char *dev); diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index bf6c7fe..18e5eed 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -42,6 +42,7 @@ static const char rcsid[] = #include <sys/param.h> #include <sys/types.h> #include <sys/sysctl.h> +#include <sys/disklabel.h> #include <sys/stat.h> #include <sys/disklabel.h> @@ -63,9 +64,9 @@ static const char rcsid[] = long diskreads, totalreads; /* Disk cache statistics */ int -ftypeok(struct dinode *dp) +ftypeok(union dinode *dp) { - switch (dp->di_mode & IFMT) { + switch (DIP(dp, di_mode) & IFMT) { case IFDIR: case IFREG: @@ -78,7 +79,7 @@ ftypeok(struct dinode *dp) default: if (debug) - printf("bad file type 0%o\n", dp->di_mode); + printf("bad file type 0%o\n", DIP(dp, di_mode)); return (0); } } @@ -181,7 +182,7 @@ bufinit(void) * Manage a cache of directory blocks. */ struct bufarea * -getdatablk(ufs_daddr_t blkno, long size) +getdatablk(ufs2_daddr_t blkno, long size) { struct bufarea *bp; @@ -207,9 +208,9 @@ foundit: } void -getblk(struct bufarea *bp, ufs_daddr_t blk, long size) +getblk(struct bufarea *bp, ufs2_daddr_t blk, long size) { - ufs_daddr_t dblk; + ufs2_daddr_t dblk; totalreads++; dblk = fsbtodb(&sblock, blk); @@ -251,7 +252,7 @@ flush(int fd, struct bufarea *bp) } void -rwerror(char *mesg, ufs_daddr_t blk) +rwerror(char *mesg, ufs2_daddr_t blk) { if (bkgrdcheck) @@ -293,9 +294,10 @@ ckfini(int markclean) return; } flush(fswritefd, &sblk); - if (havesb && sblk.b_bno != SBOFF / dev_bsize && cursnapshot == 0 && + if (havesb && cursnapshot == 0 && sblock.fs_magic == FS_UFS2_MAGIC && + sblk.b_bno != fsbtodb(&sblock, sblock.fs_sblockloc) && !preen && reply("UPDATE STANDARD SUPERBLOCK")) { - sblk.b_bno = SBOFF / dev_bsize; + sblk.b_bno = fsbtodb(&sblock, sblock.fs_sblockloc); sbdirty(); flush(fswritefd, &sblk); } @@ -336,7 +338,7 @@ ckfini(int markclean) } int -bread(int fd, char *buf, ufs_daddr_t blk, long size) +bread(int fd, char *buf, ufs2_daddr_t blk, long size) { char *cp; int i, errs; @@ -373,7 +375,7 @@ bread(int fd, char *buf, ufs_daddr_t blk, long size) } void -bwrite(int fd, char *buf, ufs_daddr_t blk, long size) +bwrite(int fd, char *buf, ufs2_daddr_t blk, long size) { int i; char *cp; @@ -406,7 +408,7 @@ bwrite(int fd, char *buf, ufs_daddr_t blk, long size) /* * allocate a data block with the specified number of fragments */ -ufs_daddr_t +ufs2_daddr_t allocblk(long frags) { int i, j, k, cg, baseblk; @@ -450,7 +452,7 @@ allocblk(long frags) * Free a previously allocated block */ void -freeblk(ufs_daddr_t blkno, long frags) +freeblk(ufs2_daddr_t blkno, long frags) { struct inodesc idesc; diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c index 0050ae1..636daa6 100644 --- a/sbin/fsck_ffs/inode.c +++ b/sbin/fsck_ffs/inode.c @@ -40,6 +40,7 @@ static const char rcsid[] = #endif /* not lint */ #include <sys/param.h> +#include <sys/stdint.h> #include <sys/time.h> #include <sys/sysctl.h> @@ -55,16 +56,15 @@ static const char rcsid[] = static ino_t startinum; -static int iblock(struct inodesc *, long ilevel, quad_t isize); +static int iblock(struct inodesc *, long ilevel, off_t isize); int -ckinode(struct dinode *dp, struct inodesc *idesc) +ckinode(union dinode *dp, struct inodesc *idesc) { - ufs_daddr_t *ap; - int ret; - long n, ndb, offset; - struct dinode dino; - quad_t remsize, sizepb; + off_t remsize, sizepb; + int i, offset, ret; + union dinode dino; + ufs2_daddr_t ndb; mode_t mode; char pathbuf[MAXPATHLEN + 1]; @@ -72,21 +72,25 @@ ckinode(struct dinode *dp, struct inodesc *idesc) idesc->id_fix = DONTKNOW; idesc->id_lbn = -1; idesc->id_entryno = 0; - idesc->id_filesize = dp->di_size; - mode = dp->di_mode & IFMT; + idesc->id_filesize = DIP(dp, di_size); + mode = DIP(dp, di_mode) & IFMT; if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && - dp->di_size < (unsigned)sblock.fs_maxsymlinklen)) + DIP(dp, di_size) < (unsigned)sblock.fs_maxsymlinklen)) return (KEEPON); - dino = *dp; - ndb = howmany(dino.di_size, sblock.fs_bsize); - for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { + if (sblock.fs_magic == FS_UFS1_MAGIC) + dino.dp1 = dp->dp1; + else + dino.dp2 = dp->dp2; + ndb = howmany(DIP(&dino, di_size), sblock.fs_bsize); + for (i = 0; i < NDADDR; i++) { idesc->id_lbn++; - if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) + if (--ndb == 0 && + (offset = blkoff(&sblock, DIP(&dino, di_size))) != 0) idesc->id_numfrags = numfrags(&sblock, fragroundup(&sblock, offset)); else idesc->id_numfrags = sblock.fs_frag; - if (*ap == 0) { + if (DIP(&dino, di_db[i]) == 0) { if (idesc->id_type == DATA && ndb >= 0) { /* An empty block in a directory XXX */ getpathname(pathbuf, idesc->id_number, @@ -95,8 +99,7 @@ ckinode(struct dinode *dp, struct inodesc *idesc) pathbuf); if (reply("ADJUST LENGTH") == 1) { dp = ginode(idesc->id_number); - dp->di_size = (ap - &dino.di_db[0]) * - sblock.fs_bsize; + DIP(dp, di_size) = i * sblock.fs_bsize; printf( "YOU MUST RERUN FSCK AFTERWARDS\n"); rerun = 1; @@ -106,7 +109,7 @@ ckinode(struct dinode *dp, struct inodesc *idesc) } continue; } - idesc->id_blkno = *ap; + idesc->id_blkno = DIP(&dino, di_db[i]); if (idesc->id_type != DATA) ret = (*idesc->id_func)(idesc); else @@ -115,13 +118,13 @@ ckinode(struct dinode *dp, struct inodesc *idesc) return (ret); } idesc->id_numfrags = sblock.fs_frag; - remsize = dino.di_size - sblock.fs_bsize * NDADDR; + remsize = DIP(&dino, di_size) - sblock.fs_bsize * NDADDR; sizepb = sblock.fs_bsize; - for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) { + for (i = 0; i < NIADDR; i++) { sizepb *= NINDIR(&sblock); - if (*ap) { - idesc->id_blkno = *ap; - ret = iblock(idesc, n, remsize); + if (DIP(&dino, di_ib[i])) { + idesc->id_blkno = DIP(&dino, di_ib[i]); + ret = iblock(idesc, i + 1, remsize); if (ret & STOP) return (ret); } else { @@ -134,7 +137,7 @@ ckinode(struct dinode *dp, struct inodesc *idesc) pathbuf); if (reply("ADJUST LENGTH") == 1) { dp = ginode(idesc->id_number); - dp->di_size -= remsize; + DIP(dp, di_size) -= remsize; remsize = 0; printf( "YOU MUST RERUN FSCK AFTERWARDS\n"); @@ -150,16 +153,14 @@ ckinode(struct dinode *dp, struct inodesc *idesc) } static int -iblock(struct inodesc *idesc, long ilevel, quad_t isize) +iblock(struct inodesc *idesc, long ilevel, off_t isize) { - ufs_daddr_t *ap; - ufs_daddr_t *aplim; struct bufarea *bp; int i, n, (*func)(), nif; - quad_t sizepb; + off_t sizepb; char buf[BUFSIZ]; char pathbuf[MAXPATHLEN + 1]; - struct dinode *dp; + union dinode *dp; if (idesc->id_type != DATA) { func = idesc->id_func; @@ -173,31 +174,30 @@ iblock(struct inodesc *idesc, long ilevel, quad_t isize) ilevel--; for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) sizepb *= NINDIR(&sblock); - nif = howmany(isize , sizepb); - if (nif > NINDIR(&sblock)) + if (howmany(isize, sizepb) > NINDIR(&sblock)) nif = NINDIR(&sblock); + else + nif = howmany(isize, sizepb); if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { - aplim = &bp->b_un.b_indir[NINDIR(&sblock)]; - for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { - if (*ap == 0) + for (i = nif; i < NINDIR(&sblock); i++) { + if (IBLK(bp, i) == 0) continue; (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", (u_long)idesc->id_number); if (preen) { pfatal("%s", buf); } else if (dofix(idesc, buf)) { - *ap = 0; + IBLK(bp, i) = 0; dirty(bp); } } flush(fswritefd, bp); } - aplim = &bp->b_un.b_indir[nif]; - for (ap = bp->b_un.b_indir; ap < aplim; ap++) { + for (i = 0; i < nif; i++) { if (ilevel == 0) idesc->id_lbn++; - if (*ap) { - idesc->id_blkno = *ap; + if (IBLK(bp, i)) { + idesc->id_blkno = IBLK(bp, i); if (ilevel == 0) n = (*func)(idesc); else @@ -215,7 +215,7 @@ iblock(struct inodesc *idesc, long ilevel, quad_t isize) pathbuf); if (reply("ADJUST LENGTH") == 1) { dp = ginode(idesc->id_number); - dp->di_size -= isize; + DIP(dp, di_size) -= isize; isize = 0; printf( "YOU MUST RERUN FSCK AFTERWARDS\n"); @@ -237,7 +237,7 @@ iblock(struct inodesc *idesc, long ilevel, quad_t isize) * Return 0 if in range, 1 if out of range. */ int -chkrange(ufs_daddr_t blk, int cnt) +chkrange(ufs2_daddr_t blk, int cnt) { int c; @@ -280,10 +280,10 @@ chkrange(ufs_daddr_t blk, int cnt) /* * General purpose interface for reading inodes. */ -struct dinode * +union dinode * ginode(ino_t inumber) { - ufs_daddr_t iblk; + ufs2_daddr_t iblk; if (inumber < ROOTINO || inumber > maxino) errx(EEXIT, "bad inode number %d to ginode", inumber); @@ -295,7 +295,10 @@ ginode(ino_t inumber) pbp = getdatablk(iblk, sblock.fs_bsize); startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); } - return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]); + if (sblock.fs_magic == FS_UFS1_MAGIC) + return ((union dinode *) + &pbp->b_un.b_dinode1[inumber % INOPB(&sblock)]); + return ((union dinode *)&pbp->b_un.b_dinode2[inumber % INOPB(&sblock)]); } /* @@ -304,14 +307,15 @@ ginode(ino_t inumber) */ static ino_t nextino, lastinum, lastvalidinum; static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; -static struct dinode *inodebuf; +static caddr_t inodebuf; -struct dinode * +union dinode * getnextinode(ino_t inumber) { long size; - ufs_daddr_t dblk; - static struct dinode *dp; + ufs2_daddr_t dblk; + union dinode *dp; + static caddr_t nextinop; if (inumber != nextino++ || inumber > lastvalidinum) errx(EEXIT, "bad inode number %d to nextinode", inumber); @@ -329,10 +333,15 @@ getnextinode(ino_t inumber) * If bread returns an error, it will already have zeroed * out the buffer, so we do not need to do so here. */ - (void)bread(fsreadfd, (char *)inodebuf, dblk, size); - dp = inodebuf; + (void)bread(fsreadfd, inodebuf, dblk, size); + nextinop = inodebuf; } - return (dp++); + dp = (union dinode *)nextinop; + if (sblock.fs_magic == FS_UFS1_MAGIC) + nextinop += sizeof(struct ufs1_dinode); + else + nextinop += sizeof(struct ufs2_dinode); + return (dp); } void @@ -349,17 +358,19 @@ setinodebuf(ino_t inum) if (inodebuf != NULL) return; inobufsize = blkroundup(&sblock, INOBUFSIZE); - fullcnt = inobufsize / sizeof(struct dinode); + fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ? + sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode)); readpercg = sblock.fs_ipg / fullcnt; partialcnt = sblock.fs_ipg % fullcnt; - partialsize = partialcnt * sizeof(struct dinode); + partialsize = partialcnt * ((sblock.fs_magic == FS_UFS1_MAGIC) ? + sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode)); if (partialcnt != 0) { readpercg++; } else { partialcnt = fullcnt; partialsize = inobufsize; } - if ((inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) + if ((inodebuf = malloc((unsigned)inobufsize)) == NULL) errx(EEXIT, "cannot allocate space for inode buffer"); } @@ -380,17 +391,17 @@ freeinodebuf(void) * Enter inodes into the cache. */ void -cacheino(struct dinode *dp, ino_t inumber) +cacheino(union dinode *dp, ino_t inumber) { - struct inoinfo *inp; - struct inoinfo **inpp; - int blks; + struct inoinfo *inp, **inpp; + int i, blks; - blks = howmany(dp->di_size, sblock.fs_bsize); - if (blks > NDADDR) + if (howmany(DIP(dp, di_size), sblock.fs_bsize) > NDADDR) blks = NDADDR + NIADDR; + else + blks = howmany(DIP(dp, di_size), sblock.fs_bsize); inp = (struct inoinfo *) - malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs_daddr_t)); + malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs2_daddr_t)); if (inp == NULL) errx(EEXIT, "cannot increase directory list"); inpp = &inphead[inumber % dirhash]; @@ -399,9 +410,13 @@ cacheino(struct dinode *dp, ino_t inumber) inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0; inp->i_dotdot = (ino_t)0; inp->i_number = inumber; - inp->i_isize = dp->di_size; - inp->i_numblks = blks * sizeof(ufs_daddr_t); - memmove(&inp->i_blks[0], &dp->di_db[0], (size_t)inp->i_numblks); + inp->i_isize = DIP(dp, di_size); + inp->i_numblks = blks; + for (i = 0; i < (blks < NDADDR ? blks : NDADDR); i++) + inp->i_blks[i] = DIP(dp, di_db[i]); + if (blks > NDADDR) + for (i = 0; i < NIADDR; i++) + inp->i_blks[NDADDR + i] = DIP(dp, di_ib[i]); if (inplast == listmax) { listmax += 100; inpsort = (struct inoinfo **)realloc((char *)inpsort, @@ -456,12 +471,12 @@ inodirty(void) void clri(struct inodesc *idesc, char *type, int flag) { - struct dinode *dp; + union dinode *dp; dp = ginode(idesc->id_number); if (flag == 1) { pwarn("%s %s", type, - (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"); + (DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE"); pinode(idesc->id_number); } if (preen || reply("CLEAR") == 1) { @@ -475,7 +490,7 @@ clri(struct inodesc *idesc, char *type, int flag) inodirty(); } else { cmd.value = idesc->id_number; - cmd.size = -dp->di_nlink; + cmd.size = -DIP(dp, di_nlink); if (debug) printf("adjrefcnt ino %ld amt %ld\n", (long)cmd.value, cmd.size); @@ -530,7 +545,7 @@ clearentry(struct inodesc *idesc) void pinode(ino_t ino) { - struct dinode *dp; + union dinode *dp; char *p; struct passwd *pw; time_t t; @@ -540,24 +555,24 @@ pinode(ino_t ino) return; dp = ginode(ino); printf(" OWNER="); - if ((pw = getpwuid((int)dp->di_uid)) != 0) + if ((pw = getpwuid((int)DIP(dp, di_uid))) != 0) printf("%s ", pw->pw_name); else - printf("%u ", (unsigned)dp->di_uid); - printf("MODE=%o\n", dp->di_mode); + printf("%u ", (unsigned)DIP(dp, di_uid)); + printf("MODE=%o\n", DIP(dp, di_mode)); if (preen) printf("%s: ", cdevname); - printf("SIZE=%qu ", dp->di_size); - t = dp->di_mtime; + printf("SIZE=%qu ", DIP(dp, di_size)); + t = DIP(dp, di_mtime); p = ctime(&t); printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); } void -blkerror(ino_t ino, char *type, ufs_daddr_t blk) +blkerror(ino_t ino, char *type, ufs2_daddr_t blk) { - pfatal("%ld %s I=%lu", (long)blk, type, (u_long)ino); + pfatal("%lld %s I=%lu", (intmax_t)blk, type, (u_long)ino); printf("\n"); switch (inoinfo(ino)->ino_state) { @@ -586,7 +601,7 @@ ino_t allocino(ino_t request, int type) { ino_t ino; - struct dinode *dp; + union dinode *dp; struct cg *cgp = &cgrp; int cg; @@ -619,18 +634,20 @@ allocino(ino_t request, int type) } cgdirty(); dp = ginode(ino); - dp->di_db[0] = allocblk((long)1); - if (dp->di_db[0] == 0) { + DIP(dp, di_db[0]) = allocblk((long)1); + if (DIP(dp, di_db[0]) == 0) { inoinfo(ino)->ino_state = USTATE; return (0); } - dp->di_mode = type; - dp->di_flags = 0; - dp->di_atime = time(NULL); - dp->di_mtime = dp->di_ctime = dp->di_atime; - dp->di_mtimensec = dp->di_ctimensec = dp->di_atimensec = 0; - dp->di_size = sblock.fs_fsize; - dp->di_blocks = btodb(sblock.fs_fsize); + DIP(dp, di_mode) = type; + DIP(dp, di_flags) = 0; + DIP(dp, di_atime) = time(NULL); + DIP(dp, di_mtime) = DIP(dp, di_ctime) = DIP(dp, di_atime); + DIP(dp, di_mtimensec) = 0; + DIP(dp, di_ctimensec) = 0; + DIP(dp, di_atimensec) = 0; + DIP(dp, di_size) = sblock.fs_fsize; + DIP(dp, di_blocks) = btodb(sblock.fs_fsize); n_files++; inodirty(); inoinfo(ino)->ino_type = IFTODT(type); @@ -644,7 +661,7 @@ void freeino(ino_t ino) { struct inodesc idesc; - struct dinode *dp; + union dinode *dp; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = ADDR; diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index 73364a7..c69e9d3 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mount.h> #include <sys/resource.h> #include <sys/sysctl.h> +#include <sys/disklabel.h> #include <ufs/ufs/dinode.h> #include <ufs/ufs/ufsmount.h> @@ -95,6 +96,9 @@ main(int argc, char *argv[]) case 'c': skipclean = 0; cvtlevel = argtoi('c', "conversion level", optarg, 10); + if (cvtlevel < 3) + errx(EEXIT, "cannot do level %d conversion", + cvtlevel); break; case 'd': @@ -180,14 +184,14 @@ argtoi(int flag, char *req, char *str, int base) static int checkfilesys(char *filesys) { - ufs_daddr_t n_ffree, n_bfree; + ufs2_daddr_t n_ffree, n_bfree; struct ufs_args args; struct dups *dp; struct statfs *mntp; struct zlncnt *zlnp; - ufs_daddr_t blks; - ufs_daddr_t files; + ufs2_daddr_t blks; int cylno, size; + ino_t files; cdevname = filesys; if (debug && preen) @@ -367,10 +371,9 @@ checkfilesys(char *filesys) pwarn("Reclaimed: %ld directories, %ld files, %d fragments\n", countdirs, (long)files - countdirs, blks); } - pwarn("%ld files, %ld used, %ld free ", - (long)n_files, (long)n_blks, (long)(n_ffree + - sblock.fs_frag * n_bfree)); - printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", + pwarn("%ld files, %ld used, %qu free ", + (long)n_files, (long)n_blks, n_ffree + sblock.fs_frag * n_bfree); + printf("(%qu frags, %qu blocks, %.1f%% fragmentation)\n", n_ffree, n_bfree, n_ffree * 100.0 / sblock.fs_dsize); if (debug) { if (files < 0) @@ -404,7 +407,8 @@ checkfilesys(char *filesys) */ for (cylno = 0; cylno < sblock.fs_ncg; cylno++) bwrite(fswritefd, (char *)&sblock, - fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); + fsbtodb(&sblock, cgsblock(&sblock, cylno)), + SBLOCKSIZE); } if (rerun) resolved = 0; diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c index cfb8af8..10f03eb 100644 --- a/sbin/fsck_ffs/pass1.c +++ b/sbin/fsck_ffs/pass1.c @@ -52,8 +52,8 @@ static const char rcsid[] = #include "fsck.h" -static ufs_daddr_t badblk; -static ufs_daddr_t dupblk; +static ufs2_daddr_t badblk; +static ufs2_daddr_t dupblk; static ino_t lastino; /* last inode in use */ static void checkinode(ino_t inumber, struct inodesc *); @@ -61,11 +61,12 @@ static void checkinode(ino_t inumber, struct inodesc *); void pass1(void) { - u_int8_t *cp; - ino_t inumber; - int c, i, cgd, inosused; struct inostat *info; struct inodesc idesc; + ino_t inumber, inosused; + ufs2_daddr_t i, cgd; + u_int8_t *cp; + int c; /* * Set filesystem reserved blocks in used block map. @@ -93,7 +94,11 @@ pass1(void) for (c = 0; c < sblock.fs_ncg; c++) { inumber = c * sblock.fs_ipg; setinodebuf(inumber); - inosused = sblock.fs_ipg; + getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize); + if (sblock.fs_magic == FS_UFS2_MAGIC) + inosused = cgrp.cg_initediblk; + else + inosused = sblock.fs_ipg; if (got_siginfo) { printf("%s: phase 1: cyl group %d of %d (%d%%)\n", cdevname, c, sblock.fs_ncg, @@ -108,10 +113,9 @@ pass1(void) * read only those inodes in from disk. */ if (preen && usedsoftdep) { - getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize); if (!cg_chkmagic(&cgrp)) pfatal("CG %d: BAD MAGIC NUMBER\n", c); - cp = &cg_inosused(&cgrp)[(sblock.fs_ipg - 1) / NBBY]; + cp = &cg_inosused(&cgrp)[(inosused - 1) / NBBY]; for ( ; inosused > 0; inosused -= NBBY, cp--) { if (*cp == 0) continue; @@ -157,9 +161,10 @@ pass1(void) * to the size necessary to describe the inodes that we * really found. */ - inosused = lastino - (c * sblock.fs_ipg); - if (inosused < 0) + if (lastino < (c * sblock.fs_ipg)) inosused = 0; + else + inosused = lastino - (c * sblock.fs_ipg); inostathead[c].il_numalloced = inosused; if (inosused == 0) { free(inostathead[c].il_stat); @@ -180,21 +185,29 @@ pass1(void) static void checkinode(ino_t inumber, struct inodesc *idesc) { - struct dinode *dp; + union dinode *dp; struct zlncnt *zlnp; - u_int64_t kernmaxfilesize; - ufs_daddr_t ndb, j; + off_t kernmaxfilesize; + ufs2_daddr_t ndb; mode_t mode; char *symbuf; + int j; dp = getnextinode(inumber); - mode = dp->di_mode & IFMT; + mode = DIP(dp, di_mode) & IFMT; if (mode == 0) { - if (memcmp(dp->di_db, zino.di_db, - NDADDR * sizeof(ufs_daddr_t)) || - memcmp(dp->di_ib, zino.di_ib, - NIADDR * sizeof(ufs_daddr_t)) || - dp->di_mode || dp->di_size) { + if ((sblock.fs_magic == FS_UFS1_MAGIC && + (memcmp(dp->dp1.di_db, ufs1_zino.di_db, + NDADDR * sizeof(ufs1_daddr_t)) || + memcmp(dp->dp1.di_ib, ufs1_zino.di_ib, + NIADDR * sizeof(ufs1_daddr_t)) || + dp->dp1.di_mode || dp->dp1.di_size)) || + (sblock.fs_magic == FS_UFS2_MAGIC && + (memcmp(dp->dp2.di_db, ufs2_zino.di_db, + NDADDR * sizeof(ufs2_daddr_t)) || + memcmp(dp->dp2.di_ib, ufs2_zino.di_ib, + NIADDR * sizeof(ufs2_daddr_t)) || + dp->dp2.di_mode || dp->dp2.di_size))) { pfatal("PARTIALLY ALLOCATED INODE I=%lu", (u_long)inumber); if (reply("CLEAR") == 1) { @@ -208,36 +221,37 @@ checkinode(ino_t inumber, struct inodesc *idesc) } lastino = inumber; /* This should match the file size limit in ffs_mountfs(). */ - kernmaxfilesize = (u_int64_t)0x40000000 * sblock.fs_bsize - 1; - if (dp->di_size > kernmaxfilesize || - dp->di_size > sblock.fs_maxfilesize || - (mode == IFDIR && dp->di_size > MAXDIRSIZE)) { + kernmaxfilesize = (off_t)0x40000000 * sblock.fs_bsize - 1; + if (DIP(dp, di_size) > kernmaxfilesize || + DIP(dp, di_size) > sblock.fs_maxfilesize || + (mode == IFDIR && DIP(dp, di_size) > MAXDIRSIZE)) { if (debug) - printf("bad size %qu:", dp->di_size); + printf("bad size %qu:", DIP(dp, di_size)); goto unknown; } if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { dp = ginode(inumber); - dp->di_size = sblock.fs_fsize; - dp->di_mode = IFREG|0600; + DIP(dp, di_size) = sblock.fs_fsize; + DIP(dp, di_mode) = IFREG|0600; inodirty(); } if ((mode == IFBLK || mode == IFCHR || mode == IFIFO || - mode == IFSOCK) && dp->di_size != 0) { + mode == IFSOCK) && DIP(dp, di_size) != 0) { if (debug) - printf("bad special-file size %qu:", dp->di_size); + printf("bad special-file size %qu:", DIP(dp, di_size)); goto unknown; } - if ((mode == IFBLK || mode == IFCHR) && (dev_t)dp->di_rdev == NODEV) { + if ((mode == IFBLK || mode == IFCHR) && + (dev_t)DIP(dp, di_rdev) == NODEV) { if (debug) printf("bad special-file rdev NODEV:"); goto unknown; } - ndb = howmany(dp->di_size, sblock.fs_bsize); + ndb = howmany(DIP(dp, di_size), sblock.fs_bsize); if (ndb < 0) { if (debug) - printf("bad size %qu ndb %d:", - dp->di_size, ndb); + printf("bad size %qu ndb %qu:", + DIP(dp, di_size), ndb); goto unknown; } if (mode == IFBLK || mode == IFCHR) @@ -247,8 +261,13 @@ checkinode(ino_t inumber, struct inodesc *idesc) * Fake ndb value so direct/indirect block checks below * will detect any garbage after symlink string. */ - if (dp->di_size < (u_int64_t)sblock.fs_maxsymlinklen) { - ndb = howmany(dp->di_size, sizeof(ufs_daddr_t)); + if (DIP(dp, di_size) < (off_t)sblock.fs_maxsymlinklen) { + if (sblock.fs_magic == FS_UFS1_MAGIC) + ndb = howmany(DIP(dp, di_size), + sizeof(ufs1_daddr_t)); + else + ndb = howmany(DIP(dp, di_size), + sizeof(ufs2_daddr_t)); if (ndb > NDADDR) { j = ndb - NDADDR; for (ndb = 1; j > 1; j--) @@ -258,26 +277,26 @@ checkinode(ino_t inumber, struct inodesc *idesc) } } for (j = ndb; j < NDADDR; j++) - if (dp->di_db[j] != 0) { + if (DIP(dp, di_db[j]) != 0) { if (debug) - printf("bad direct addr: %ld\n", - (long)dp->di_db[j]); + printf("bad direct addr[%d]: %qu\n", j, + (ufs2_daddr_t)DIP(dp, di_db[j])); goto unknown; } for (j = 0, ndb -= NDADDR; ndb > 0; j++) ndb /= NINDIR(&sblock); for (; j < NIADDR; j++) - if (dp->di_ib[j] != 0) { + if (DIP(dp, di_ib[j]) != 0) { if (debug) - printf("bad indirect addr: %ld\n", - (long)dp->di_ib[j]); + printf("bad indirect addr: %qu\n", + DIP(dp, di_ib[j])); goto unknown; } if (ftypeok(dp) == 0) goto unknown; n_files++; - inoinfo(inumber)->ino_linkcnt = dp->di_nlink; - if (dp->di_nlink <= 0) { + inoinfo(inumber)->ino_linkcnt = DIP(dp, di_nlink); + if (DIP(dp, di_nlink) <= 0) { zlnp = (struct zlncnt *)malloc(sizeof *zlnp); if (zlnp == NULL) { pfatal("LINK COUNT TABLE OVERFLOW"); @@ -292,7 +311,7 @@ checkinode(ino_t inumber, struct inodesc *idesc) } } if (mode == IFDIR) { - if (dp->di_size == 0) + if (DIP(dp, di_size) == 0) inoinfo(inumber)->ino_state = DCLEAR; else inoinfo(inumber)->ino_state = DSTATE; @@ -303,30 +322,30 @@ checkinode(ino_t inumber, struct inodesc *idesc) inoinfo(inumber)->ino_type = IFTODT(mode); badblk = dupblk = 0; idesc->id_number = inumber; - if (dp->di_flags & SF_SNAPSHOT) + if (DIP(dp, di_flags) & SF_SNAPSHOT) idesc->id_type = SNAP; else idesc->id_type = ADDR; (void)ckinode(dp, idesc); idesc->id_entryno *= btodb(sblock.fs_fsize); - if (dp->di_blocks != idesc->id_entryno) { - pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)", - (u_long)inumber, (long)dp->di_blocks, - (long)idesc->id_entryno); + if (DIP(dp, di_blocks) != idesc->id_entryno) { + pwarn("INCORRECT BLOCK COUNT I=%lu (%qu should be %qu)", + (u_long)inumber, DIP(dp, di_blocks), + idesc->id_entryno); if (preen) printf(" (CORRECTED)\n"); else if (reply("CORRECT") == 0) return; if (bkgrdflag == 0) { dp = ginode(inumber); - dp->di_blocks = idesc->id_entryno; + DIP(dp, di_blocks) = idesc->id_entryno; inodirty(); } else { cmd.value = idesc->id_number; - cmd.size = idesc->id_entryno - dp->di_blocks; + cmd.size = idesc->id_entryno - DIP(dp, di_blocks); if (debug) - printf("adjblkcnt ino %ld amount %ld\n", - (long)cmd.value, cmd.size); + printf("adjblkcnt ino %qu amount %ld\n", + cmd.value, cmd.size); if (sysctl(adjblkcnt, MIBSIZE, 0, 0, &cmd, sizeof cmd) == -1) rwerror("ADJUST INODE BLOCK COUNT", cmd.value); @@ -349,7 +368,7 @@ pass1check(struct inodesc *idesc) { int res = KEEPON; int anyout, nfrags; - ufs_daddr_t blkno = idesc->id_blkno; + ufs2_daddr_t blkno = idesc->id_blkno; struct dups *dlp; struct dups *new; diff --git a/sbin/fsck_ffs/pass1b.c b/sbin/fsck_ffs/pass1b.c index dbb401b..b30a2b1 100644 --- a/sbin/fsck_ffs/pass1b.c +++ b/sbin/fsck_ffs/pass1b.c @@ -55,7 +55,7 @@ void pass1b(void) { int c, i; - struct dinode *dp; + union dinode *dp; struct inodesc idesc; ino_t inumber; @@ -90,7 +90,7 @@ pass1bcheck(struct inodesc *idesc) { struct dups *dlp; int nfrags, res = KEEPON; - ufs_daddr_t blkno = idesc->id_blkno; + ufs2_daddr_t blkno = idesc->id_blkno; for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { if (chkrange(blkno, 1)) diff --git a/sbin/fsck_ffs/pass2.c b/sbin/fsck_ffs/pass2.c index 2347f76..34fda76 100644 --- a/sbin/fsck_ffs/pass2.c +++ b/sbin/fsck_ffs/pass2.c @@ -58,11 +58,12 @@ static int pass2check(struct inodesc *); void pass2(void) { - struct dinode *dp; + union dinode *dp; struct inoinfo **inpp, *inp; struct inoinfo **inpend; struct inodesc curino; - struct dinode dino; + union dinode dino; + int i; char pathbuf[MAXPATHLEN + 1]; switch (inoinfo(ROOTINO)->ino_state) { @@ -105,8 +106,8 @@ pass2(void) exit(EEXIT); } dp = ginode(ROOTINO); - dp->di_mode &= ~IFMT; - dp->di_mode |= IFDIR; + DIP(dp, di_mode) &= ~IFMT; + DIP(dp, di_mode) |= IFDIR; inodirty(); break; @@ -130,7 +131,6 @@ pass2(void) memset(&curino, 0, sizeof(struct inodesc)); curino.id_type = DATA; curino.id_func = pass2check; - dp = &dino; inpend = &inpsort[inplast]; for (inpp = inpsort; inpp < inpend; inpp++) { if (got_siginfo) { @@ -147,9 +147,8 @@ pass2(void) inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); if (reply("FIX") == 1) { dp = ginode(inp->i_number); - dp->di_size = inp->i_isize; + DIP(dp, di_size) = inp->i_isize; inodirty(); - dp = &dino; } } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { getpathname(pathbuf, inp->i_number, inp->i_number); @@ -166,15 +165,22 @@ pass2(void) inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); if (preen || reply("ADJUST") == 1) { dp = ginode(inp->i_number); - dp->di_size = roundup(inp->i_isize, DIRBLKSIZ); + DIP(dp, di_size) = + roundup(inp->i_isize, DIRBLKSIZ); inodirty(); - dp = &dino; } } - memset(&dino, 0, sizeof(struct dinode)); - dino.di_mode = IFDIR; - dp->di_size = inp->i_isize; - memmove(&dp->di_db[0], &inp->i_blks[0], (size_t)inp->i_numblks); + dp = &dino; + memset(dp, 0, sizeof(struct ufs2_dinode)); + DIP(dp, di_mode) = IFDIR; + DIP(dp, di_size) = inp->i_isize; + for (i = 0; + i < (inp->i_numblks<NDADDR ? inp->i_numblks : NDADDR); + i++) + DIP(dp, di_db[i]) = inp->i_blks[i]; + if (inp->i_numblks > NDADDR) + for (i = 0; i < NIADDR; i++) + DIP(dp, di_ib[i]) = inp->i_blks[NDADDR + i]; curino.id_number = inp->i_number; curino.id_parent = inp->i_parent; (void)ckinode(dp, &curino); @@ -223,7 +229,7 @@ pass2check(struct inodesc *idesc) struct direct *dirp = idesc->id_dirp; struct inoinfo *inp; int n, entrysize, ret = 0; - struct dinode *dp; + union dinode *dp; char *errmsg; struct direct proto; char namebuf[MAXPATHLEN + 1]; @@ -392,8 +398,8 @@ again: break; dp = ginode(dirp->d_ino); inoinfo(dirp->d_ino)->ino_state = - (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE; - inoinfo(dirp->d_ino)->ino_linkcnt = dp->di_nlink; + (DIP(dp, di_mode) & IFMT) == IFDIR ? DSTATE : FSTATE; + inoinfo(dirp->d_ino)->ino_linkcnt = DIP(dp, di_nlink); goto again; case DSTATE: diff --git a/sbin/fsck_ffs/pass4.c b/sbin/fsck_ffs/pass4.c index 6683ae4..da29804 100644 --- a/sbin/fsck_ffs/pass4.c +++ b/sbin/fsck_ffs/pass4.c @@ -54,7 +54,7 @@ pass4(void) { ino_t inumber; struct zlncnt *zlnp; - struct dinode *dp; + union dinode *dp; struct inodesc idesc; int i, n, cg; @@ -100,7 +100,7 @@ pass4(void) case DCLEAR: dp = ginode(inumber); - if (dp->di_size == 0) { + if (DIP(dp, di_size) == 0) { clri(&idesc, "ZERO LENGTH", 1); break; } @@ -125,7 +125,7 @@ pass4check(struct inodesc *idesc) { struct dups *dlp; int nfrags, res = KEEPON; - ufs_daddr_t blkno = idesc->id_blkno; + ufs2_daddr_t blkno = idesc->id_blkno; for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { if (chkrange(blkno, 1)) { diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c index f2ab2a8..707872b 100644 --- a/sbin/fsck_ffs/pass5.c +++ b/sbin/fsck_ffs/pass5.c @@ -55,18 +55,17 @@ static void check_maps(u_char *, u_char *, int, int, char *, int *, int, int); void pass5(void) { - int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0; + int c, i, j, blk, frags, basesize, mapsize; int inomapsize, blkmapsize; struct fs *fs = &sblock; struct cg *cg = &cgrp; - ufs_daddr_t dbase, dmax, d; - int i, j, excessdirs, rewritecg = 0; + ufs2_daddr_t d, dbase, dmax; + int excessdirs, rewritecg = 0; struct csum *cs; - struct csum cstotal; + struct csum_total cstotal; struct inodesc idesc[3]; char buf[MAXBSIZE]; struct cg *newcg = (struct cg *)buf; - struct ocg *ocg = (struct ocg *)buf; inoinfo(WINO)->ino_state = USTATE; memset(newcg, 0, (size_t)fs->fs_cgsize); @@ -110,63 +109,46 @@ pass5(void) } } } - switch ((int)fs->fs_postblformat) { - - case FS_42POSTBLFMT: - basesize = (char *)(&ocg->cg_btot[0]) - - (char *)(&ocg->cg_firstfield); - sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]); - mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] - - (u_char *)&ocg->cg_iused[0]; - blkmapsize = howmany(fs->fs_fpg, NBBY); - inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0]; - ocg->cg_magic = CG_MAGIC; - savednrpos = fs->fs_nrpos; - fs->fs_nrpos = 8; - break; - - case FS_DYNAMICPOSTBLFMT: - newcg->cg_btotoff = - &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield); - newcg->cg_boff = - newcg->cg_btotoff + fs->fs_cpg * sizeof(int32_t); - newcg->cg_iusedoff = newcg->cg_boff + - fs->fs_cpg * fs->fs_nrpos * sizeof(u_int16_t); - newcg->cg_freeoff = - newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY); - inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff; - newcg->cg_nextfreeoff = newcg->cg_freeoff + - howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY); - blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff; - if (fs->fs_contigsumsize > 0) { - newcg->cg_clustersumoff = newcg->cg_nextfreeoff - - sizeof(u_int32_t); - newcg->cg_clustersumoff = - roundup(newcg->cg_clustersumoff, sizeof(u_int32_t)); - newcg->cg_clusteroff = newcg->cg_clustersumoff + - (fs->fs_contigsumsize + 1) * sizeof(u_int32_t); - newcg->cg_nextfreeoff = newcg->cg_clusteroff + - howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY); - } - newcg->cg_magic = CG_MAGIC; - basesize = &newcg->cg_space[0] - - (u_char *)(&newcg->cg_firstfield); - sumsize = newcg->cg_iusedoff - newcg->cg_btotoff; - mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; - break; - - default: - inomapsize = blkmapsize = sumsize = 0; /* keep lint happy */ - errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d", - fs->fs_postblformat); + basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield); + if (sblock.fs_magic == FS_UFS2_MAGIC) { + newcg->cg_iusedoff = basesize; + } else { + /* + * We reserve the space for the old rotation summary + * tables for the benefit of old kernels, but do not + * maintain them in modern kernels. In time, they can + * go away. + */ + newcg->cg_old_btotoff = basesize; + newcg->cg_old_boff = newcg->cg_old_btotoff + + fs->fs_old_cpg * sizeof(int32_t); + newcg->cg_iusedoff = newcg->cg_old_boff + + fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t); + memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize); + } + inomapsize = howmany(fs->fs_ipg, NBBY); + newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize; + blkmapsize = howmany(fs->fs_fpg, NBBY); + newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize; + if (fs->fs_contigsumsize > 0) { + newcg->cg_clustersumoff = newcg->cg_nextfreeoff - + sizeof(u_int32_t); + newcg->cg_clustersumoff = + roundup(newcg->cg_clustersumoff, sizeof(u_int32_t)); + newcg->cg_clusteroff = newcg->cg_clustersumoff + + (fs->fs_contigsumsize + 1) * sizeof(u_int32_t); + newcg->cg_nextfreeoff = newcg->cg_clusteroff + + howmany(fragstoblks(fs, fs->fs_fpg), NBBY); } + newcg->cg_magic = CG_MAGIC; + mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; memset(&idesc[0], 0, sizeof idesc); for (i = 0; i < 3; i++) idesc[i].id_type = ADDR; - memset(&cstotal, 0, sizeof(struct csum)); - j = blknum(fs, fs->fs_size + fs->fs_frag - 1); - for (i = fs->fs_size; i < j; i++) - setbmap(i); + memset(&cstotal, 0, sizeof(struct csum_total)); + dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1); + for (d = fs->fs_size; d < dmax; d++) + setbmap(d); for (c = 0; c < fs->fs_ncg; c++) { if (got_siginfo) { printf("%s: phase 5: cyl group %d of %d (%d%%)\n", @@ -177,17 +159,23 @@ pass5(void) getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize); if (!cg_chkmagic(cg)) pfatal("CG %d: BAD MAGIC NUMBER\n", c); + newcg->cg_time = cg->cg_time; + newcg->cg_old_time = cg->cg_old_time; + newcg->cg_cgx = c; dbase = cgbase(fs, c); dmax = dbase + fs->fs_fpg; if (dmax > fs->fs_size) dmax = fs->fs_size; - newcg->cg_time = cg->cg_time; - newcg->cg_cgx = c; - if (c == fs->fs_ncg - 1 && fs->fs_ncyl % fs->fs_cpg > 0) - newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg; - else - newcg->cg_ncyl = fs->fs_cpg; newcg->cg_ndblk = dmax - dbase; + if (fs->fs_magic == FS_UFS1_MAGIC) { + if (c == fs->fs_ncg - 1) + newcg->cg_old_ncyl = howmany(newcg->cg_ndblk, + fs->fs_fpg / fs->fs_old_cpg); + else + newcg->cg_old_ncyl = fs->fs_old_cpg; + newcg->cg_old_niblk = fs->fs_ipg; + newcg->cg_niblk = 0; + } if (fs->fs_contigsumsize > 0) newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag; newcg->cg_cs.cs_ndir = 0; @@ -206,11 +194,16 @@ pass5(void) newcg->cg_irotor = cg->cg_irotor; else newcg->cg_irotor = 0; + if (fs->fs_magic == FS_UFS1_MAGIC) { + newcg->cg_initediblk = 0; + } else { + if ((unsigned)cg->cg_initediblk > fs->fs_ipg) + newcg->cg_initediblk = fs->fs_ipg; + else + newcg->cg_initediblk = cg->cg_initediblk; + } memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum); - memset(&cg_blktot(newcg)[0], 0, - (size_t)(sumsize + mapsize)); - if (fs->fs_postblformat == FS_42POSTBLFMT) - ocg->cg_magic = CG_MAGIC; + memset(cg_inosused(newcg), 0, (size_t)(mapsize)); j = fs->fs_ipg * c; for (i = 0; i < inostathead[c].il_numalloced; j++, i++) { switch (inoinfo(j)->ino_state) { @@ -254,9 +247,6 @@ pass5(void) } if (frags == fs->fs_frag) { newcg->cg_cs.cs_nbfree++; - j = cbtocylno(fs, i); - cg_blktot(newcg)[j]++; - cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++; if (fs->fs_contigsumsize > 0) setbit(cg_clustersfree(newcg), i / fs->fs_frag); @@ -312,13 +302,9 @@ pass5(void) continue; } if (cursnapshot == 0 && - (memcmp(newcg, cg, basesize) != 0 || - memcmp(&cg_blktot(newcg)[0], - &cg_blktot(cg)[0], sumsize) != 0) && + memcmp(newcg, cg, basesize) != 0 && dofix(&idesc[2], "SUMMARY INFORMATION BAD")) { memmove(cg, newcg, (size_t)basesize); - memmove(&cg_blktot(cg)[0], - &cg_blktot(newcg)[0], (size_t)sumsize); cgdirty(); } if (bkgrdflag != 0 || usedsoftdep || debug) { @@ -346,12 +332,10 @@ pass5(void) cgdirty(); } } - if (fs->fs_postblformat == FS_42POSTBLFMT) - fs->fs_nrpos = savednrpos; if (cursnapshot == 0 && - memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0 - && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { - memmove(&fs->fs_cstotal, &cstotal, sizeof *cs); + memcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal) != 0 + && dofix(&idesc[0], "SUMMARY BLK COUNT(S) WRONG IN SUPERBLK")) { + memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal); fs->fs_ronly = 0; fs->fs_fmod = 0; sbdirty(); @@ -398,6 +382,7 @@ check_maps( aend = n; continue; } + returntosingle = 1; if (astart == aend) (*msg)("ALLOCATED %s %d MARKED FREE\n", name, astart); @@ -434,6 +419,7 @@ check_maps( pwarn("%s %sS %d-%ld MARKED USED\n", "UNALLOCATED", name, ustart, ustart + size - 1); + returntosingle = 1; if (bkgrdflag != 0) { cmd.value = ustart; cmd.size = size; @@ -476,6 +462,7 @@ check_maps( pwarn("UNALLOCATED %sS %d-%ld MARKED USED\n", name, ustart, ustart + size - 1); } + returntosingle = 1; if (bkgrdflag != 0) { cmd.value = ustart; cmd.size = size; diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c index 107ded2..243edbe 100644 --- a/sbin/fsck_ffs/setup.c +++ b/sbin/fsck_ffs/setup.c @@ -210,7 +210,8 @@ setup(char *dev) sbdirty(); } } - if (sblock.fs_inodefmt < FS_44INODEFMT) { + if (sblock.fs_magic == FS_UFS1_MAGIC && + sblock.fs_old_inodefmt < FS_44INODEFMT) { pwarn("Format of filesystem is too old.\n"); pwarn("Must update to modern format using a version of fsck\n"); pfatal("from before 2002 with the command ``fsck -c 2''\n"); @@ -286,28 +287,43 @@ badsb: } /* + * Possible superblock locations ordered from most to least likely. + */ +static int sblock_try[] = SBLOCKSEARCH; + +/* * Read in the super block and its summary info. */ int readsb(int listerr) { - ufs_daddr_t super = bflag ? bflag : SBOFF / dev_bsize; + ufs2_daddr_t super; + int i; - if (bread(fsreadfd, (char *)&sblock, super, (long)SBSIZE) != 0) - return (0); - sblk.b_bno = super; - sblk.b_size = SBSIZE; - /* - * run a few consistency checks of the super block - */ - if (sblock.fs_magic != FS_MAGIC) - { badsb(listerr, "MAGIC NUMBER WRONG"); return (0); } - if (sblock.fs_ncg < 1) - { badsb(listerr, "NCG OUT OF RANGE"); return (0); } - if (sblock.fs_cpg < 1) - { badsb(listerr, "CPG OUT OF RANGE"); return (0); } - if (sblock.fs_sbsize > SBSIZE) - { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); } + if (bflag) { + super = bflag; + if ((bread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE))) + return (0); + } else { + for (i = 0; sblock_try[i] != -1; i++) { + super = sblock_try[i] / dev_bsize; + if ((bread(fsreadfd, (char *)&sblock, super, + (long)SBLOCKSIZE))) + return (0); + if ((sblock.fs_magic == FS_UFS1_MAGIC || + (sblock.fs_magic == FS_UFS2_MAGIC && + sblock.fs_sblockloc == + numfrags(&sblock, sblock_try[i]))) && + sblock.fs_ncg >= 1 && + sblock.fs_bsize >= SBLOCKSIZE && + sblock.fs_bsize >= sizeof(struct fs)) + break; + } + if (sblock_try[i] == -1) { + fprintf(stderr, "Cannot find filesystem superblock\n"); + return (0); + } + } /* * Compute block size that the filesystem is based on, * according to fsbtodb, and adjust superblock block number @@ -316,6 +332,7 @@ readsb(int listerr) super *= dev_bsize; dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); sblk.b_bno = super / dev_bsize; + sblk.b_size = SBLOCKSIZE; if (bflag) { havesb = 1; return (1); @@ -331,8 +348,6 @@ readsb(int listerr) altsblock.fs_cblkno != sblock.fs_cblkno || altsblock.fs_iblkno != sblock.fs_iblkno || altsblock.fs_dblkno != sblock.fs_dblkno || - altsblock.fs_cgoffset != sblock.fs_cgoffset || - altsblock.fs_cgmask != sblock.fs_cgmask || altsblock.fs_ncg != sblock.fs_ncg || altsblock.fs_bsize != sblock.fs_bsize || altsblock.fs_fsize != sblock.fs_fsize || @@ -347,7 +362,6 @@ readsb(int listerr) altsblock.fs_nindir != sblock.fs_nindir || altsblock.fs_inopb != sblock.fs_inopb || altsblock.fs_cssize != sblock.fs_cssize || - altsblock.fs_cpg != sblock.fs_cpg || altsblock.fs_ipg != sblock.fs_ipg || altsblock.fs_fpg != sblock.fs_fpg || altsblock.fs_magic != sblock.fs_magic) { @@ -355,6 +369,21 @@ readsb(int listerr) "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); return (0); } + /* + * If not yet done, update UFS1 superblock with new wider fields. + */ + if (sblock.fs_magic == FS_UFS1_MAGIC && + sblock.fs_maxbsize != sblock.fs_bsize) { + sblock.fs_maxbsize = sblock.fs_bsize; + sblock.fs_time = sblock.fs_old_time; + sblock.fs_size = sblock.fs_old_size; + sblock.fs_dsize = sblock.fs_old_dsize; + sblock.fs_csaddr = sblock.fs_old_csaddr; + sblock.fs_cstotal.cs_ndir = sblock.fs_old_cstotal.cs_ndir; + sblock.fs_cstotal.cs_nbfree = sblock.fs_old_cstotal.cs_nbfree; + sblock.fs_cstotal.cs_nifree = sblock.fs_old_cstotal.cs_nifree; + sblock.fs_cstotal.cs_nffree = sblock.fs_old_cstotal.cs_nffree; + } havesb = 1; return (1); } @@ -380,8 +409,8 @@ sblock_init(void) lfdir = 0; initbarea(&sblk); initbarea(&asblk); - sblk.b_un.b_buf = malloc(SBSIZE); - asblk.b_un.b_buf = malloc(SBSIZE); + sblk.b_un.b_buf = malloc(SBLOCKSIZE); + asblk.b_un.b_buf = malloc(SBLOCKSIZE); if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) errx(EEXIT, "cannot allocate space for superblock"); if ((lp = getdisklabel(NULL, fsreadfd))) @@ -402,7 +431,7 @@ calcsb(char *dev, int devfd, struct fs *fs) struct disklabel *lp; struct partition *pp; char *cp; - int i; + int i, nspf; cp = strchr(dev, '\0') - 1; if (cp == (char *)-1 || ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))) { @@ -430,24 +459,30 @@ calcsb(char *dev, int devfd, struct fs *fs) memset(fs, 0, sizeof(struct fs)); fs->fs_fsize = pp->p_fsize; fs->fs_frag = pp->p_frag; - fs->fs_cpg = pp->p_cpg; fs->fs_size = pp->p_size; - fs->fs_ntrak = lp->d_ntracks; - fs->fs_nsect = lp->d_nsectors; - fs->fs_spc = lp->d_secpercyl; - fs->fs_nspf = fs->fs_fsize / lp->d_secsize; - fs->fs_cgmask = 0xffffffff; - for (i = fs->fs_ntrak; i > 1; i >>= 1) - fs->fs_cgmask <<= 1; - if (!POWEROF2(fs->fs_ntrak)) - fs->fs_cgmask <<= 1; - fs->fs_cgoffset = roundup( - howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag); - fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs); - fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg); - for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1) + fs->fs_sblkno = roundup( + howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize), + fs->fs_frag); + nspf = fs->fs_fsize / lp->d_secsize; + for (fs->fs_fsbtodb = 0, i = nspf; i > 1; i >>= 1) fs->fs_fsbtodb++; dev_bsize = lp->d_secsize; + if (fs->fs_magic == FS_UFS2_MAGIC) { + fs->fs_fpg = pp->p_cpg; + fs->fs_ncg = howmany(fs->fs_size, fs->fs_fpg); + } else /* if (fs->fs_magic == FS_UFS1_MAGIC) */ { + fs->fs_old_cpg = pp->p_cpg; + fs->fs_old_cgmask = 0xffffffff; + for (i = lp->d_ntracks; i > 1; i >>= 1) + fs->fs_old_cgmask <<= 1; + if (!POWEROF2(lp->d_ntracks)) + fs->fs_old_cgmask <<= 1; + fs->fs_old_cgoffset = roundup(howmany(lp->d_nsectors, nspf), + fs->fs_frag); + fs->fs_fpg = (fs->fs_old_cpg * lp->d_secpercyl) / nspf; + fs->fs_ncg = howmany(fs->fs_size / lp->d_secpercyl, + fs->fs_old_cpg); + } return (1); } |