diff options
author | mckusick <mckusick@FreeBSD.org> | 2002-06-21 06:18:05 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2002-06-21 06:18:05 +0000 |
commit | 88d85c15ef183c06524d6ca695f62c0c0672b00c (patch) | |
tree | f1364dbfb9835934a3879b5904f7ff9a1495744c /sbin | |
parent | eacb69b0197a8553d5004aa99532cabad8778e36 (diff) | |
download | FreeBSD-src-88d85c15ef183c06524d6ca695f62c0c0672b00c.zip FreeBSD-src-88d85c15ef183c06524d6ca695f62c0c0672b00c.tar.gz |
This commit adds basic support for the UFS2 filesystem. The UFS2
filesystem expands the inode to 256 bytes to make space for 64-bit
block pointers. It also adds a file-creation time field, an ability
to use jumbo blocks per inode to allow extent like pointer density,
and space for extended attributes (up to twice the filesystem block
size worth of attributes, e.g., on a 16K filesystem, there is space
for 32K of attributes). UFS2 fully supports and runs existing UFS1
filesystems. New filesystems built using newfs can be built in either
UFS1 or UFS2 format using the -O option. In this commit UFS1 is
the default format, so if you want to build UFS2 format filesystems,
you must specify -O 2. This default will be changed to UFS2 when
UFS2 proves itself to be stable. In this commit the boot code for
reading UFS2 filesystems is not compiled (see /sys/boot/common/ufsread.c)
as there is insufficient space in the boot block. Once the size of the
boot block is increased, this code can be defined.
Things to note: the definition of SBSIZE has changed to SBLOCKSIZE.
The header file <ufs/ufs/dinode.h> must be included before
<ufs/ffs/fs.h> so as to get the definitions of ufs2_daddr_t and
ufs_lbn_t.
Still TODO:
Verify that the first level bootstraps work for all the architectures.
Convert the utility ffsinfo to understand UFS2 and test growfs.
Add support for the extended attribute storage. Update soft updates
to ensure integrity of extended attribute storage. Switch the
current extended attribute interfaces to use the extended attribute
storage. Add the extent like functionality (framework is there,
but is currently never used).
Sponsored by: DARPA & NAI Labs.
Reviewed by: Poul-Henning Kamp <phk@freebsd.org>
Diffstat (limited to 'sbin')
38 files changed, 2160 insertions, 1966 deletions
diff --git a/sbin/Makefile b/sbin/Makefile index bbd2f6b..dd04507 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -18,7 +18,6 @@ SUBDIR= adjkerntz \ dump \ dumpfs \ dumpon \ - ffsinfo \ fsck \ fsck_ffs \ fsck_msdosfs \ diff --git a/sbin/badsect/badsect.c b/sbin/badsect/badsect.c index 6094db2..94f9023 100644 --- a/sbin/badsect/badsect.c +++ b/sbin/badsect/badsect.c @@ -59,8 +59,8 @@ static const char rcsid[] = #include <sys/stat.h> #include <sys/disklabel.h> -#include <ufs/ffs/fs.h> #include <ufs/ufs/dinode.h> +#include <ufs/ffs/fs.h> #include <err.h> #include <dirent.h> @@ -73,7 +73,7 @@ static const char rcsid[] = union { struct fs fs; - char fsx[SBSIZE]; + char fsx[SBLOCKSIZE]; } ufs; #define sblock ufs.fs union { @@ -91,6 +91,11 @@ char buf[MAXBSIZE]; void rdfs(daddr_t, int, char *); int chkuse(daddr_t, int); +/* + * Possible superblock locations ordered from most to least likely. + */ +static int sblock_try[] = SBLOCKSEARCH; + static void usage(void) { @@ -108,6 +113,7 @@ main(int argc, char *argv[]) DIR *dirp; char name[2 * MAXPATHLEN]; char *name_dir_end; + int i; if (argc < 3) usage(); @@ -134,7 +140,19 @@ main(int argc, char *argv[]) if ((fsi = open(name, O_RDONLY)) < 0) err(6, "%s", name); fs = &sblock; - rdfs(SBOFF, SBSIZE, (char *)fs); + for (i = 0; sblock_try[i] != -1; i++) { + rdfs(sblock_try[i] / dev_bsize, SBLOCKSIZE, (char *)fs); + if ((fs->fs_magic == FS_UFS1_MAGIC || + (fs->fs_magic == FS_UFS2_MAGIC && + fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) && + fs->fs_bsize <= MAXBSIZE && + fs->fs_bsize >= sizeof(struct fs)) + break; + } + if (sblock_try[i] == -1) { + printf("Cannot find filesystem\n"); + exit(7); + } dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); for (argc -= 2, argv += 2; argc > 0; argc--, argv++) { number = atol(*argv); diff --git a/sbin/clri/clri.c b/sbin/clri/clri.c index 2dd6b2d..3a42177 100644 --- a/sbin/clri/clri.c +++ b/sbin/clri/clri.c @@ -61,6 +61,11 @@ static const char rcsid[] = #include <stdio.h> #include <unistd.h> +/* + * Possible superblock locations ordered from most to least likely. + */ +static int sblock_try[] = SBLOCKSEARCH; + static void usage(void) { @@ -74,13 +79,13 @@ main(argc, argv) char *argv[]; { struct fs *sbp; - struct dinode *ip; - int fd; - struct dinode ibuf[MAXBSIZE / sizeof (struct dinode)]; + struct ufs1_dinode *dp1; + struct ufs2_dinode *dp2; + char *ibuf[MAXBSIZE]; long generation, bsize; off_t offset; - int inonum; - char *fs, sblock[SBSIZE]; + int i, fd, inonum; + char *fs, sblock[SBLOCKSIZE]; if (argc < 3) usage(); @@ -90,15 +95,23 @@ main(argc, argv) /* get the superblock. */ if ((fd = open(fs, O_RDWR, 0)) < 0) err(1, "%s", fs); - if (lseek(fd, (off_t)(SBLOCK * DEV_BSIZE), SEEK_SET) < 0) - err(1, "%s", fs); - if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock)) - errx(1, "%s: can't read superblock", fs); - - sbp = (struct fs *)sblock; - if (sbp->fs_magic != FS_MAGIC) - errx(1, "%s: superblock magic number 0x%x, not 0x%x", - fs, sbp->fs_magic, FS_MAGIC); + for (i = 0; sblock_try[i] != -1; i++) { + if (lseek(fd, (off_t)(sblock_try[i]), SEEK_SET) < 0) + err(1, "%s", fs); + if (read(fd, sblock, sizeof(sblock)) != sizeof(sblock)) + errx(1, "%s: can't read superblock", fs); + sbp = (struct fs *)sblock; + if ((sbp->fs_magic == FS_UFS1_MAGIC || + (sbp->fs_magic == FS_UFS2_MAGIC && + sbp->fs_sblockloc == numfrags(sbp, sblock_try[i]))) && + sbp->fs_bsize <= MAXBSIZE && + sbp->fs_bsize >= sizeof(struct fs)) + break; + } + if (sblock_try[i] == -1) { + fprintf(stderr, "Cannot find filesystem\n"); + exit(2); + } bsize = sbp->fs_bsize; /* remaining arguments are inode numbers. */ @@ -119,13 +132,25 @@ main(argc, argv) if (read(fd, ibuf, bsize) != bsize) err(1, "%s", fs); - /* get the inode within the block. */ - ip = &ibuf[ino_to_fsbo(sbp, inonum)]; - - /* clear the inode, and bump the generation count. */ - generation = ip->di_gen + 1; - memset(ip, 0, sizeof(*ip)); - ip->di_gen = generation; + if (sbp->fs_magic == FS_UFS2_MAGIC) { + /* get the inode within the block. */ + dp2 = &(((struct ufs2_dinode *)ibuf) + [ino_to_fsbo(sbp, inonum)]); + + /* clear the inode, and bump the generation count. */ + generation = dp2->di_gen + 1; + memset(dp2, 0, sizeof(*dp2)); + dp2->di_gen = generation; + } else { + /* get the inode within the block. */ + dp1 = &(((struct ufs1_dinode *)ibuf) + [ino_to_fsbo(sbp, inonum)]); + + /* clear the inode, and bump the generation count. */ + generation = dp1->di_gen + 1; + memset(dp1, 0, sizeof(*dp1)); + dp1->di_gen = generation; + } /* backup and write the block */ if (lseek(fd, (off_t)-bsize, SEEK_CUR) < 0) diff --git a/sbin/dump/dump.h b/sbin/dump/dump.h index 4b42755..cd84596 100644 --- a/sbin/dump/dump.h +++ b/sbin/dump/dump.h @@ -35,9 +35,6 @@ * $FreeBSD$ */ -#define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) -#define MAXNINDIR (MAXBSIZE / sizeof(ufs_daddr_t)) - /* * Dump maps used to describe what is to be dumped. */ @@ -102,22 +99,23 @@ void timeest(void); time_t unctime(char *str); /* mapping rouintes */ -struct dinode; -long blockest(struct dinode *dp); +union dinode; +long blockest(union dinode *dp); int mapfiles(ino_t maxino, long *tapesize); int mapdirs(ino_t maxino, long *tapesize); /* file dumping routines */ -void blksout(ufs_daddr_t *blkp, int frags, ino_t ino); -void bread(ufs_daddr_t blkno, char *buf, int size); -void dumpino(struct dinode *dp, ino_t ino); +void ufs1_blksout(ufs1_daddr_t *blkp, int frags, ino_t ino); +void ufs2_blksout(ufs2_daddr_t *blkp, int frags, ino_t ino); +void bread(ufs2_daddr_t blkno, char *buf, int size); +void dumpino(union dinode *dp, ino_t ino); void dumpmap(char *map, int type, ino_t ino); void writeheader(ino_t ino); /* tape writing routines */ int alloctape(void); void close_rewind(void); -void dumpblock(ufs_daddr_t blkno, int size); +void dumpblock(ufs2_daddr_t blkno, int size); void startnewtape(int top); void trewind(void); void writerec(char *dp, int isspcl); @@ -127,7 +125,7 @@ void dumpabort(int signo); void getfstab(void); char *rawname(char *cp); -struct dinode *getino(ino_t inum); +union dinode *getino(ino_t inum, int *mode); /* rdump routines */ #ifdef RDUMP diff --git a/sbin/dump/itime.c b/sbin/dump/itime.c index b4c8f98..c875013 100644 --- a/sbin/dump/itime.c +++ b/sbin/dump/itime.c @@ -152,9 +152,9 @@ getdumptime(void) continue; if (ddp->dd_level >= level) continue; - if (ddp->dd_ddate <= _time32_to_time(spcl.c_ddate)) + if (ddp->dd_ddate <= _time64_to_time(spcl.c_ddate)) continue; - spcl.c_ddate = _time_to_time32(ddp->dd_ddate); + spcl.c_ddate = _time_to_time64(ddp->dd_ddate); lastlevel = ddp->dd_level; } } @@ -202,7 +202,7 @@ putdumptime(void) found: (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name)); dtwalk->dd_level = level; - dtwalk->dd_ddate = _time32_to_time(spcl.c_date); + dtwalk->dd_ddate = _time64_to_time(spcl.c_date); ITITERATE(i, dtwalk) { dumprecout(df, dtwalk); @@ -215,7 +215,7 @@ putdumptime(void) if (spcl.c_date == 0) { tmsg = "the epoch\n"; } else { - time_t t = _time32_to_time(spcl.c_date); + time_t t = _time64_to_time(spcl.c_date); tmsg = ctime(&t); } msg("level %c dump on %s", level, tmsg); diff --git a/sbin/dump/main.c b/sbin/dump/main.c index 860457b..270ea81 100644 --- a/sbin/dump/main.c +++ b/sbin/dump/main.c @@ -68,10 +68,6 @@ static const char rcsid[] = #include "dump.h" #include "pathnames.h" -#ifndef SBOFF -#define SBOFF (SBLOCK * DEV_BSIZE) -#endif - int notify = 0; /* notify operator flag */ int blockswritten = 0; /* number of blocks written on current tape */ int tapeno = 0; /* current tape number */ @@ -83,6 +79,11 @@ long dev_bsize = 1; /* recalculated below */ long blocksperfile; /* output blocks per file */ char *host = NULL; /* remote host (if any) */ +/* + * Possible superblock locations ordered from most to least likely. + */ +static int sblock_try[] = SBLOCKSEARCH; + static long numarg(const char *, long, long); static void obsolete(int *, char **[]); static void usage(void) __dead2; @@ -93,17 +94,17 @@ main(int argc, char *argv[]) struct stat sb; ino_t ino; int dirty; - struct dinode *dp; + union dinode *dp; struct fstab *dt; char *map; - int ch; + int ch, mode; int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1; int just_estimate = 0; ino_t maxino; char *tmsg; time_t t; - spcl.c_date = _time_to_time32(time(NULL)); + spcl.c_date = _time_to_time64(time(NULL)); tsize = 0; /* Default later, based on 'c' option for cart tapes */ if ((tape = getenv("TAPE")) == NULL) @@ -316,14 +317,14 @@ main(int argc, char *argv[]) if (spcl.c_date == 0) { tmsg = "the epoch\n"; } else { - time_t t = _time32_to_time(spcl.c_date); + time_t t = _time64_to_time(spcl.c_date); tmsg = ctime(&t); } msg("Date of this level %c dump: %s", level, tmsg); if (spcl.c_ddate == 0) { tmsg = "the epoch\n"; } else { - time_t t = _time32_to_time(spcl.c_ddate); + time_t t = _time64_to_time(spcl.c_ddate); tmsg = ctime(&t); } msg("Date of last level %c dump: %s", lastlevel, tmsg); @@ -343,9 +344,18 @@ main(int argc, char *argv[]) errx(X_STARTUP, "%s: unknown filesystem", disk); sync(); sblock = (struct fs *)sblock_buf; - bread(SBOFF, (char *) sblock, SBSIZE); - if (sblock->fs_magic != FS_MAGIC) - quit("bad sblock magic number\n"); + for (i = 0; sblock_try[i] != -1; i++) { + bread(sblock_try[i] >> dev_bshift, (char *) sblock, SBLOCKSIZE); + if ((sblock->fs_magic == FS_UFS1_MAGIC || + (sblock->fs_magic == FS_UFS2_MAGIC && + sblock->fs_sblockloc == + numfrags(sblock, sblock_try[i]))) && + sblock->fs_bsize <= MAXBSIZE && + sblock->fs_bsize >= sizeof(struct fs)) + break; + } + if (sblock_try[i] == -1) + quit("Cannot find filesystem superblock\n"); dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1); dev_bshift = ffs(dev_bsize) - 1; if (dev_bsize != (1 << dev_bshift)) @@ -353,10 +363,6 @@ main(int argc, char *argv[]) tp_bshift = ffs(TP_BSIZE) - 1; if (TP_BSIZE != (1 << tp_bshift)) quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE); -#ifdef FS_44INODEFMT - if (sblock->fs_inodefmt >= FS_44INODEFMT) - spcl.c_flags |= DR_NEWINODEFMT; -#endif maxino = sblock->fs_ipg * sblock->fs_ncg; mapsize = roundup(howmany(maxino, NBBY), TP_BSIZE); usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char)); @@ -456,8 +462,8 @@ main(int argc, char *argv[]) /* * Skip directory inodes deleted and maybe reallocated */ - dp = getino(ino); - if ((dp->di_mode & IFMT) != IFDIR) + dp = getino(ino, &mode); + if (mode != IFDIR) continue; (void)dumpino(dp, ino); } @@ -466,8 +472,6 @@ main(int argc, char *argv[]) setproctitle("%s: pass 4: regular files", disk); msg("dumping (Pass IV) [regular files]\n"); for (map = dumpinomap, ino = 1; ino < maxino; ino++) { - int mode; - if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */ dirty = *map++; else @@ -477,8 +481,7 @@ main(int argc, char *argv[]) /* * Skip inodes deleted and reallocated as directories. */ - dp = getino(ino); - mode = dp->di_mode & IFMT; + dp = getino(ino, &mode); if (mode == IFDIR) continue; (void)dumpino(dp, ino); @@ -489,9 +492,9 @@ main(int argc, char *argv[]) for (i = 0; i < ntrec; i++) writeheader(maxino - 1); if (pipeout) - msg("DUMP: %ld tape blocks\n", spcl.c_tapea); + msg("DUMP: %qd tape blocks\n", spcl.c_tapea); else - msg("DUMP: %ld tape blocks on %d volume%s\n", + msg("DUMP: %qd tape blocks on %d volume%s\n", spcl.c_tapea, spcl.c_volume, (spcl.c_volume == 1) ? "" : "s"); @@ -499,7 +502,7 @@ main(int argc, char *argv[]) if (tend_writing - tstart_writing == 0) msg("finished in less than a second\n"); else - msg("finished in %d seconds, throughput %d KBytes/sec\n", + msg("finished in %d seconds, throughput %qd KBytes/sec\n", tend_writing - tstart_writing, spcl.c_tapea / (tend_writing - tstart_writing)); diff --git a/sbin/dump/optr.c b/sbin/dump/optr.c index b0ff473..5fa1a02 100644 --- a/sbin/dump/optr.c +++ b/sbin/dump/optr.c @@ -44,6 +44,8 @@ static const char rcsid[] = #include <sys/wait.h> #include <sys/time.h> +#include <ufs/ufs/dinode.h> + #include <errno.h> #include <fstab.h> #include <grp.h> diff --git a/sbin/dump/tape.c b/sbin/dump/tape.c index 215d73b2..d13142e 100644 --- a/sbin/dump/tape.c +++ b/sbin/dump/tape.c @@ -62,7 +62,7 @@ static const char rcsid[] = #include "dump.h" int writesize; /* size of malloc()ed buffer for tape */ -long lastspclrec = -1; /* tape block number of last written header */ +int64_t lastspclrec = -1; /* tape block number of last written header */ int trecno = 0; /* next record to write in current block */ extern long blocksperfile; /* number of blocks per output file */ long blocksthisvol; /* number of blocks on current output file */ @@ -87,21 +87,21 @@ static void rollforward(void); * The following structure defines the instruction packets sent to slaves. */ struct req { - ufs_daddr_t dblk; + ufs2_daddr_t dblk; int count; }; int reqsiz; #define SLAVES 3 /* 1 slave writing, 1 reading, 1 for slack */ struct slave { - int tapea; /* header number at start of this chunk */ + int64_t tapea; /* header number at start of this chunk */ + int64_t firstrec; /* record number of this block */ int count; /* count to next header (used for TS_TAPE */ /* after EOT) */ int inode; /* inode that we are currently dealing with */ int fd; /* FD for this slave */ int pid; /* PID for this slave */ int sent; /* 1 == we've sent this slave requests */ - int firstrec; /* record number of this block */ char (*tblock)[TP_BSIZE]; /* buffer for data blocks */ struct req *req; /* buffer for requests */ } slaves[SLAVES+1]; @@ -161,7 +161,7 @@ void writerec(char *dp, int isspcl) { - slp->req[trecno].dblk = (ufs_daddr_t)0; + slp->req[trecno].dblk = (ufs2_daddr_t)0; slp->req[trecno].count = 1; /* Can't do a structure assignment due to alignment problems */ bcopy(dp, *(nextblock)++, sizeof (union u_spcl)); @@ -174,9 +174,10 @@ writerec(char *dp, int isspcl) } void -dumpblock(ufs_daddr_t blkno, int size) +dumpblock(ufs2_daddr_t blkno, int size) { - int avail, tpblks, dblkno; + int avail, tpblks; + ufs2_daddr_t dblkno; dblkno = fsbtodb(sblock, blkno); tpblks = size >> tp_bshift; @@ -226,7 +227,7 @@ static void flushtape(void) { int i, blks, got; - long lastfirstrec; + int64_t lastfirstrec; int siz = (char *)nextblock - (char *)slp->req; @@ -385,7 +386,8 @@ rollforward(void) { struct req *p, *q, *prev; struct slave *tslp; - int i, size, savedtapea, got; + int i, size, got; + int64_t savedtapea; union u_spcl *ntb, *otb; tslp = &slaves[SLAVES]; ntb = (union u_spcl *)tslp->tblock[1]; @@ -618,9 +620,7 @@ restore_check_point: spcl.c_firstrec = slp->firstrec; spcl.c_volume++; spcl.c_type = TS_TAPE; - spcl.c_flags |= DR_NEWHEADER; writeheader((ino_t)slp->inode); - spcl.c_flags &=~ DR_NEWHEADER; if (tapeno > 1) msg("Volume %d begins with blocks from inode %d\n", tapeno, slp->inode); diff --git a/sbin/dump/traverse.c b/sbin/dump/traverse.c index 622e32e..e5842b8 100644 --- a/sbin/dump/traverse.c +++ b/sbin/dump/traverse.c @@ -53,22 +53,25 @@ static const char rcsid[] = #include <errno.h> #include <string.h> #include <unistd.h> +#include <stdlib.h> #include "dump.h" +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) + #define HASDUMPEDFILE 0x1 #define HASSUBDIRS 0x2 -#ifdef FS_44INODEFMT -typedef quad_t fsizeT; -#else -typedef long fsizeT; -#endif - -static int dirindir(ino_t ino, ufs_daddr_t blkno, int level, long *size, +static int dirindir(ino_t ino, ufs2_daddr_t blkno, int level, long *size, long *tapesize, int nodump); -static void dmpindir(ino_t ino, ufs_daddr_t blk, int level, fsizeT *size); -static int searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize, +static void dmpindir(ino_t ino, ufs2_daddr_t blk, int level, off_t *size); +static int searchdir(ino_t ino, ufs2_daddr_t blkno, long size, long filesize, long *tapesize, int nodump); /* @@ -79,7 +82,7 @@ static int searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize, * hence the estimate may be high. */ long -blockest(struct dinode *dp) +blockest(union dinode *dp) { long blkest, sizeest; @@ -97,11 +100,11 @@ blockest(struct dinode *dp) * dump blocks (sizeest vs. blkest in the indirect block * calculation). */ - blkest = howmany(dbtob(dp->di_blocks), TP_BSIZE); - sizeest = howmany(dp->di_size, TP_BSIZE); + blkest = howmany(dbtob(DIP(dp, di_blocks)), TP_BSIZE); + sizeest = howmany(DIP(dp, di_size), TP_BSIZE); if (blkest > sizeest) blkest = sizeest; - if (dp->di_size > sblock->fs_bsize * NDADDR) { + if (DIP(dp, di_size) > sblock->fs_bsize * NDADDR) { /* calculate the number of indirect blocks on the dump tape */ blkest += howmany(sizeest - NDADDR * sblock->fs_bsize / TP_BSIZE, @@ -112,13 +115,13 @@ blockest(struct dinode *dp) /* Auxiliary macro to pick up files changed since previous dump. */ #define CHANGEDSINCE(dp, t) \ - ((dp)->di_mtime >= (t) || (dp)->di_ctime >= (t)) + (DIP(dp, di_mtime) >= (t) || DIP(dp, di_ctime) >= (t)) /* The WANTTODUMP macro decides whether a file should be dumped. */ #ifdef UF_NODUMP #define WANTTODUMP(dp) \ (CHANGEDSINCE(dp, spcl.c_ddate) && \ - (nonodump || ((dp)->di_flags & UF_NODUMP) != UF_NODUMP)) + (nonodump || (DIP(dp, di_flags) & UF_NODUMP) != UF_NODUMP)) #else #define WANTTODUMP(dp) CHANGEDSINCE(dp, spcl.c_ddate) #endif @@ -135,12 +138,12 @@ mapfiles(ino_t maxino, long *tapesize) { int mode; ino_t ino; - struct dinode *dp; + union dinode *dp; int anydirskipped = 0; for (ino = ROOTINO; ino < maxino; ino++) { - dp = getino(ino); - if ((mode = (dp->di_mode & IFMT)) == 0) + dp = getino(ino, &mode); + if (mode == 0) continue; /* * Everything must go in usedinomap so that a check @@ -160,7 +163,7 @@ mapfiles(ino_t maxino, long *tapesize) continue; } if (mode == IFDIR) { - if (!nonodump && (dp->di_flags & UF_NODUMP)) + if (!nonodump && (DIP(dp, di_flags) & UF_NODUMP)) CLRINO(ino, usedinomap); anydirskipped = 1; } @@ -188,11 +191,11 @@ mapfiles(ino_t maxino, long *tapesize) int mapdirs(ino_t maxino, long *tapesize) { - struct dinode *dp; + union dinode *dp; int i, isdir, nodump; char *map; ino_t ino; - struct dinode di; + union dinode di; long filesize; int ret, change = 0; @@ -212,23 +215,29 @@ mapdirs(ino_t maxino, long *tapesize) nodump = !nonodump && (TSTINO(ino, usedinomap) == 0); if ((isdir & 1) == 0 || (TSTINO(ino, dumpinomap) && !nodump)) continue; - dp = getino(ino); - di = *dp; /* inode buf may change in searchdir(). */ - filesize = di.di_size; + dp = getino(ino, &i); + /* + * inode buf may change in searchdir(). + */ + if (sblock->fs_magic == FS_UFS1_MAGIC) + di.dp1 = dp->dp1; + else + di.dp2 = dp->dp2; + filesize = DIP(&di, di_size); for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) { - if (di.di_db[i] != 0) - ret |= searchdir(ino, di.di_db[i], - (long)dblksize(sblock, dp, i), - filesize, tapesize, nodump); + if (DIP(&di, di_db[i]) != 0) + ret |= searchdir(ino, DIP(&di, di_db[i]), + (long)sblksize(sblock, DIP(dp, di_size), i), + filesize, tapesize, nodump); if (ret & HASDUMPEDFILE) filesize = 0; else filesize -= sblock->fs_bsize; } for (i = 0; filesize > 0 && i < NIADDR; i++) { - if (di.di_ib[i] == 0) + if (DIP(&di, di_ib[i]) == 0) continue; - ret |= dirindir(ino, di.di_ib[i], i, &filesize, + ret |= dirindir(ino, DIP(&di, di_ib[i]), i, &filesize, tapesize, nodump); } if (ret & HASDUMPEDFILE) { @@ -256,17 +265,27 @@ mapdirs(ino_t maxino, long *tapesize) * require the directory to be dumped. */ static int -dirindir(ino_t ino, ufs_daddr_t blkno, int ind_level, long *filesize, - long *tapesize, int nodump) +dirindir( + ino_t ino, + ufs2_daddr_t blkno, + int ind_level, + long *filesize, + long *tapesize, + int nodump) { int ret = 0; int i; - ufs_daddr_t idblk[MAXNINDIR]; + static caddr_t idblk; - bread(fsbtodb(sblock, blkno), (char *)idblk, (int)sblock->fs_bsize); + if (idblk == NULL && (idblk = malloc(sblock->fs_bsize)) == NULL) + quit("dirindir: cannot allocate indirect memory.\n"); + bread(fsbtodb(sblock, blkno), idblk, (int)sblock->fs_bsize); if (ind_level <= 0) { for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) { - blkno = idblk[i]; + if (sblock->fs_magic == FS_UFS1_MAGIC) + blkno = ((ufs1_daddr_t *)idblk)[i]; + else + blkno = ((ufs2_daddr_t *)idblk)[i]; if (blkno != 0) ret |= searchdir(ino, blkno, sblock->fs_bsize, *filesize, tapesize, nodump); @@ -279,7 +298,10 @@ dirindir(ino_t ino, ufs_daddr_t blkno, int ind_level, long *filesize, } ind_level--; for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) { - blkno = idblk[i]; + if (sblock->fs_magic == FS_UFS1_MAGIC) + blkno = ((ufs1_daddr_t *)idblk)[i]; + else + blkno = ((ufs2_daddr_t *)idblk)[i]; if (blkno != 0) ret |= dirindir(ino, blkno, ind_level, filesize, tapesize, nodump); @@ -293,14 +315,22 @@ dirindir(ino_t ino, ufs_daddr_t blkno, int ind_level, long *filesize, * contains any subdirectories. */ static int -searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize, - long *tapesize, int nodump) +searchdir( + ino_t ino, + ufs2_daddr_t blkno, + long size, + long filesize, + long *tapesize, + int nodump) { + int mode; struct direct *dp; - struct dinode *ip; + union dinode *ip; long loc, ret = 0; - char dblk[MAXBSIZE]; + static caddr_t dblk; + if (dblk == NULL && (dblk = malloc(sblock->fs_bsize)) == NULL) + quit("searchdir: cannot allocate indirect memory.\n"); bread(fsbtodb(sblock, blkno), dblk, (int)size); if (filesize < size) size = filesize; @@ -320,7 +350,7 @@ searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize, continue; } if (nodump) { - ip = getino(dp->d_ino); + ip = getino(dp->d_ino, &mode); if (TSTINO(dp->d_ino, dumpinomap)) { CLRINO(dp->d_ino, dumpinomap); *tapesize -= blockest(ip); @@ -329,7 +359,7 @@ searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize, * Add back to dumpdirmap and remove from usedinomap * to propagate nodump. */ - if ((ip->di_mode & IFMT) == IFDIR) { + if (mode == IFDIR) { SETINO(dp->d_ino, dumpdirmap); CLRINO(dp->d_ino, usedinomap); ret |= HASSUBDIRS; @@ -356,10 +386,12 @@ searchdir(ino_t ino, ufs_daddr_t blkno, long size, long filesize, * Dump the contents of an inode to tape. */ void -dumpino(struct dinode *dp, ino_t ino) +dumpino(union dinode *dp, ino_t ino) { + struct ufs1_dinode *dp1; + struct ufs2_dinode *dp2; int ind_level, cnt; - fsizeT size; + off_t size; char buf[TP_BSIZE]; if (newtape) { @@ -367,10 +399,36 @@ dumpino(struct dinode *dp, ino_t ino) dumpmap(dumpinomap, TS_BITS, ino); } CLRINO(ino, dumpinomap); - spcl.c_dinode = *dp; + if (sblock->fs_magic == FS_UFS1_MAGIC) { + spcl.c_mode = dp->dp1.di_mode; + spcl.c_size = dp->dp1.di_size; + spcl.c_atime = _time32_to_time(dp->dp1.di_atime); + spcl.c_atimensec = dp->dp1.di_atimensec; + spcl.c_mtime = _time32_to_time(dp->dp1.di_mtime); + spcl.c_mtimensec = dp->dp1.di_mtimensec; + spcl.c_createtime = 0; + spcl.c_createtimensec = 0; + spcl.c_rdev = dp->dp1.di_rdev; + spcl.c_file_flags = dp->dp1.di_flags; + spcl.c_uid = dp->dp1.di_uid; + spcl.c_gid = dp->dp1.di_gid; + } else { + spcl.c_mode = dp->dp2.di_mode; + spcl.c_size = dp->dp2.di_size; + spcl.c_atime = _time64_to_time(dp->dp2.di_atime); + spcl.c_atimensec = dp->dp2.di_atimensec; + spcl.c_mtime = _time64_to_time(dp->dp2.di_mtime); + spcl.c_mtimensec = dp->dp2.di_mtimensec; + spcl.c_createtime = _time64_to_time(dp->dp2.di_createtime); + spcl.c_createtimensec = dp->dp2.di_creatensec; + spcl.c_rdev = dp->dp2.di_rdev; + spcl.c_file_flags = dp->dp2.di_flags; + spcl.c_uid = dp->dp2.di_uid; + spcl.c_gid = dp->dp2.di_gid; + } spcl.c_type = TS_INODE; spcl.c_count = 0; - switch (dp->di_mode & S_IFMT) { + switch (DIP(dp, di_mode) & S_IFMT) { case 0: /* @@ -383,13 +441,18 @@ dumpino(struct dinode *dp, ino_t ino) * Check for short symbolic link. */ #ifdef FS_44INODEFMT - if (dp->di_size > 0 && - dp->di_size < sblock->fs_maxsymlinklen) { + if (DIP(dp, di_size) > 0 && + DIP(dp, di_size) < sblock->fs_maxsymlinklen) { spcl.c_addr[0] = 1; spcl.c_count = 1; writeheader(ino); - memmove(buf, dp->di_shortlink, (u_long)dp->di_size); - buf[dp->di_size] = '\0'; + if (sblock->fs_magic == FS_UFS1_MAGIC) + memmove(buf, (caddr_t)dp->dp1.di_db, + (u_long)DIP(dp, di_size)); + else + memmove(buf, (caddr_t)dp->dp2.di_db, + (u_long)DIP(dp, di_size)); + buf[DIP(dp, di_size)] = '\0'; writerec(buf, 0); return; } @@ -398,7 +461,7 @@ dumpino(struct dinode *dp, ino_t ino) case S_IFDIR: case S_IFREG: - if (dp->di_size > 0) + if (DIP(dp, di_size) > 0) break; /* fall through */ @@ -410,18 +473,22 @@ dumpino(struct dinode *dp, ino_t ino) return; default: - msg("Warning: undefined file type 0%o\n", dp->di_mode & IFMT); + msg("Warning: undefined file type 0%o\n", + DIP(dp, di_mode) & IFMT); return; } - if (dp->di_size > NDADDR * sblock->fs_bsize) + if (DIP(dp, di_size) > NDADDR * sblock->fs_bsize) cnt = NDADDR * sblock->fs_frag; else - cnt = howmany(dp->di_size, sblock->fs_fsize); - blksout(&dp->di_db[0], cnt, ino); - if ((size = dp->di_size - NDADDR * sblock->fs_bsize) <= 0) + cnt = howmany(DIP(dp, di_size), sblock->fs_fsize); + if (sblock->fs_magic == FS_UFS1_MAGIC) + ufs1_blksout(&dp->dp1.di_db[0], cnt, ino); + else + ufs2_blksout(&dp->dp2.di_db[0], cnt, ino); + if ((size = DIP(dp, di_size) - NDADDR * sblock->fs_bsize) <= 0) return; for (ind_level = 0; ind_level < NIADDR; ind_level++) { - dmpindir(ino, dp->di_ib[ind_level], ind_level, &size); + dmpindir(ino, DIP(dp, di_ib[ind_level]), ind_level, &size); if (size <= 0) return; } @@ -431,13 +498,15 @@ dumpino(struct dinode *dp, ino_t ino) * Read indirect blocks, and pass the data blocks to be dumped. */ static void -dmpindir(ino_t ino, ufs_daddr_t blk, int ind_level, fsizeT *size) +dmpindir(ino_t ino, ufs2_daddr_t blk, int ind_level, off_t *size) { int i, cnt; - ufs_daddr_t idblk[MAXNINDIR]; + static caddr_t idblk; + if (idblk == NULL && (idblk = malloc(sblock->fs_bsize)) == NULL) + quit("dmpindir: cannot allocate indirect memory.\n"); if (blk != 0) - bread(fsbtodb(sblock, blk), (char *)idblk, (int) sblock->fs_bsize); + bread(fsbtodb(sblock, blk), idblk, (int) sblock->fs_bsize); else memset(idblk, 0, (int)sblock->fs_bsize); if (ind_level <= 0) { @@ -446,12 +515,20 @@ dmpindir(ino_t ino, ufs_daddr_t blk, int ind_level, fsizeT *size) else cnt = NINDIR(sblock) * sblock->fs_frag; *size -= NINDIR(sblock) * sblock->fs_bsize; - blksout(&idblk[0], cnt, ino); + if (sblock->fs_magic == FS_UFS1_MAGIC) + ufs1_blksout((ufs1_daddr_t *)idblk, cnt, ino); + else + ufs2_blksout((ufs2_daddr_t *)idblk, cnt, ino); return; } ind_level--; for (i = 0; i < NINDIR(sblock); i++) { - dmpindir(ino, idblk[i], ind_level, size); + if (sblock->fs_magic == FS_UFS1_MAGIC) + dmpindir(ino, ((ufs1_daddr_t *)idblk)[i], ind_level, + size); + else + dmpindir(ino, ((ufs2_daddr_t *)idblk)[i], ind_level, + size); if (*size <= 0) return; } @@ -461,9 +538,44 @@ dmpindir(ino_t ino, ufs_daddr_t blk, int ind_level, fsizeT *size) * Collect up the data into tape record sized buffers and output them. */ void -blksout(ufs_daddr_t *blkp, int frags, ino_t ino) +ufs1_blksout(ufs1_daddr_t *blkp, int frags, ino_t ino) { - ufs_daddr_t *bp; + ufs1_daddr_t *bp; + int i, j, count, blks, tbperdb; + + blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); + tbperdb = sblock->fs_bsize >> tp_bshift; + for (i = 0; i < blks; i += TP_NINDIR) { + if (i + TP_NINDIR > blks) + count = blks; + else + count = i + TP_NINDIR; + for (j = i; j < count; j++) + if (blkp[j / tbperdb] != 0) + spcl.c_addr[j - i] = 1; + else + spcl.c_addr[j - i] = 0; + spcl.c_count = count - i; + writeheader(ino); + bp = &blkp[i / tbperdb]; + for (j = i; j < count; j += tbperdb, bp++) + if (*bp != 0) { + if (j + tbperdb <= count) + dumpblock(*bp, (int)sblock->fs_bsize); + else + dumpblock(*bp, (count - j) * TP_BSIZE); + } + spcl.c_type = TS_ADDR; + } +} + +/* + * Collect up the data into tape record sized buffers and output them. + */ +void +ufs2_blksout(ufs2_daddr_t *blkp, int frags, ino_t ino) +{ + ufs2_daddr_t *bp; int i, j, count, blks, tbperdb; blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); @@ -517,7 +629,7 @@ writeheader(ino_t ino) int32_t sum, cnt, *lp; spcl.c_inumber = ino; - spcl.c_magic = NFS_MAGIC; + spcl.c_magic = FS_UFS2_MAGIC; spcl.c_checksum = 0; lp = (int32_t *)&spcl; sum = 0; @@ -532,20 +644,32 @@ writeheader(ino_t ino) writerec((char *)&spcl, 1); } -struct dinode * -getino(ino_t inum) +union dinode * +getino(ino_t inum, int *modep) { - static ufs_daddr_t minino, maxino; - static struct dinode inoblock[MAXINOPB]; + static ino_t minino, maxino; + static caddr_t inoblock; + struct ufs1_dinode *dp1; + struct ufs2_dinode *dp2; + if (inoblock == NULL && (inoblock = malloc(sblock->fs_bsize)) == NULL) + quit("cannot allocate inode memory.\n"); curino = inum; if (inum >= minino && inum < maxino) - return (&inoblock[inum - minino]); - bread(fsbtodb(sblock, ino_to_fsba(sblock, inum)), (char *)inoblock, + goto gotit; + bread(fsbtodb(sblock, ino_to_fsba(sblock, inum)), inoblock, (int)sblock->fs_bsize); minino = inum - (inum % INOPB(sblock)); maxino = minino + INOPB(sblock); - return (&inoblock[inum - minino]); +gotit: + if (sblock->fs_magic == FS_UFS1_MAGIC) { + dp1 = &((struct ufs1_dinode *)inoblock)[inum - minino]; + *modep = (dp1->di_mode & IFMT); + return ((union dinode *)dp1); + } + dp2 = &((struct ufs2_dinode *)inoblock)[inum - minino]; + *modep = (dp2->di_mode & IFMT); + return ((union dinode *)dp2); } /* @@ -558,7 +682,7 @@ int breaderrors = 0; #define BREADEMAX 32 void -bread(ufs_daddr_t blkno, char *buf, int size) +bread(ufs2_daddr_t blkno, char *buf, int size) { int cnt, i; diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c index dd18313..aae7e1e 100644 --- a/sbin/dumpfs/dumpfs.c +++ b/sbin/dumpfs/dumpfs.c @@ -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) 1983, 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -49,6 +61,7 @@ static const char rcsid[] = #include <sys/time.h> #include <sys/disklabel.h> +#include <ufs/ufs/dinode.h> #include <ufs/ffs/fs.h> #include <err.h> @@ -72,6 +85,11 @@ union { long dev_bsize = 1; +/* + * Possible superblock locations ordered from most to least likely. + */ +static int sblock_try[] = SBLOCKSEARCH; + int dumpfs(const char *); int dumpcg(const char *, int, int); void pbits(void *, int); @@ -107,67 +125,94 @@ int dumpfs(const char *name) { ssize_t n; + time_t time; + int64_t fssize; int fd, c, i, j, k, size; if ((fd = open(name, O_RDONLY, 0)) < 0) goto err; - if (lseek(fd, (off_t)SBOFF, SEEK_SET) == (off_t)-1) - goto err; - if ((n = read(fd, &afs, SBSIZE)) == -1) - goto err; - - if (n != SBSIZE) { - warnx("%s: non-existent or truncated superblock, skipped", - name); - (void)close(fd); - return (1); + for (i = 0; sblock_try[i] != -1; i++) { + if (lseek(fd, (off_t)sblock_try[i], SEEK_SET) == (off_t)-1) + goto err; + if ((n = read(fd, &afs, SBLOCKSIZE)) == -1) + goto err; + if ((afs.fs_magic == FS_UFS1_MAGIC || + (afs.fs_magic == FS_UFS2_MAGIC && + afs.fs_sblockloc == numfrags(&afs, sblock_try[i]))) && + afs.fs_bsize <= MAXBSIZE && + afs.fs_bsize >= sizeof(struct fs)) + break; + } + if (sblock_try[i] == -1) { + fprintf(stderr, "Cannot find filesystem superblock\n"); + return (1); } - if (afs.fs_magic != FS_MAGIC) { - warnx("%s: superblock has bad magic number, skipped", name); - (void)close(fd); - return (1); - } - if (afs.fs_postblformat == FS_42POSTBLFMT) - afs.fs_nrpos = 8; dev_bsize = afs.fs_fsize / fsbtodb(&afs, 1); - printf("magic\t%x\ttime\t%s", afs.fs_magic, - ctime(&afs.fs_time)); - printf("id\t[ %x %x ]\n", afs.fs_id[0], afs.fs_id[1]); - printf("cylgrp\t%s\tinodes\t%s\n", - afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic", - afs.fs_inodefmt < FS_44INODEFMT ? "4.2/4.3BSD" : "4.4BSD"); - printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", - afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir, - afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree); - printf("ncg\t%d\tncyl\t%d\tsize\t%d\tblocks\t%d\n", - afs.fs_ncg, afs.fs_ncyl, afs.fs_size, afs.fs_dsize); + if (afs.fs_magic == FS_UFS2_MAGIC) { + fssize = afs.fs_size; + time = afs.fs_time; + printf("magic\t%x (UFS2)\ttime\t%s", + afs.fs_magic, ctime(&time)); + printf("offset\t%qd\tid\t[ %x %x ]\n", + afs.fs_sblockloc, afs.fs_id[0], afs.fs_id[1]); + printf("ncg\t%d\tsize\t%qd\tblocks\t%d\n", + afs.fs_ncg, fssize, afs.fs_dsize); + } else { + fssize = afs.fs_old_size; + printf("magic\t%x (UFS1)\ttime\t%s", + afs.fs_magic, ctime(&afs.fs_old_time)); + printf("id\t[ %x %x ]\n", afs.fs_id[0], afs.fs_id[1]); + printf("ncg\t%d\tsize\t%qd\tblocks\t%d\n", + afs.fs_ncg, fssize, afs.fs_dsize); + } printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n", afs.fs_bsize, afs.fs_bshift, afs.fs_bmask); printf("fsize\t%d\tshift\t%d\tmask\t0x%08x\n", afs.fs_fsize, afs.fs_fshift, afs.fs_fmask); printf("frag\t%d\tshift\t%d\tfsbtodb\t%d\n", afs.fs_frag, afs.fs_fragshift, afs.fs_fsbtodb); - printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n", - afs.fs_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg); - printf("minfree\t%d%%\toptim\t%s\tmaxcontig %d\tmaxbpg\t%d\n", + printf("minfree\t%d%%\toptim\t%s\tsymlinklen %d\n", afs.fs_minfree, afs.fs_optim == FS_OPTSPACE ? "space" : "time", - afs.fs_maxcontig, afs.fs_maxbpg); - printf("rotdelay %dms\trps\t%d\n", - afs.fs_rotdelay, afs.fs_rps); - printf("ntrak\t%d\tnsect\t%d\tnpsect\t%d\tspc\t%d\n", - afs.fs_ntrak, afs.fs_nsect, afs.fs_npsect, afs.fs_spc); - printf("symlinklen %d\ttrackskew %d\tinterleave %d\tcontigsumsize %d\n", - afs.fs_maxsymlinklen, afs.fs_trackskew, afs.fs_interleave, - afs.fs_contigsumsize); - printf("nindir\t%d\tinopb\t%d\tnspf\t%d\tmaxfilesize\t%qu\n", - afs.fs_nindir, afs.fs_inopb, afs.fs_nspf, afs.fs_maxfilesize); + afs.fs_maxsymlinklen); + if (afs.fs_magic == FS_UFS2_MAGIC) { + printf("%s %d\tmaxbpg\t%d\tmaxcontig %d\tcontigsumsize %d\n", + "maxbsize", afs.fs_maxbsize, afs.fs_maxbpg, + afs.fs_maxcontig, afs.fs_contigsumsize); + printf("nbfree\t%qd\tndir\t%qd\tnifree\t%qd\tnffree\t%qd\n", + afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir, + afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree); + printf("bpg\t%d\tfpg\t%d\tipg\t%d\n", + afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg); + printf("nindir\t%d\tinopb\t%d\tmaxfilesize\t%qu\n", + afs.fs_nindir, afs.fs_inopb, afs.fs_maxfilesize); + printf("sbsize\t%d\tcgsize\t%d\tcsaddr\t%d\tcssize\t%d\n", + afs.fs_sbsize, afs.fs_cgsize, afs.fs_csaddr, afs.fs_cssize); + } else { + printf("maxbpg\t%d\tmaxcontig %d\tcontigsumsize %d\n", + afs.fs_maxbpg, afs.fs_maxcontig, afs.fs_contigsumsize); + printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", + afs.fs_old_cstotal.cs_nbfree, afs.fs_old_cstotal.cs_ndir, + afs.fs_old_cstotal.cs_nifree, afs.fs_old_cstotal.cs_nffree); + printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n", + afs.fs_old_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg, + afs.fs_ipg); + printf("nindir\t%d\tinopb\t%d\tnspf\t%d\tmaxfilesize\t%qu\n", + afs.fs_nindir, afs.fs_inopb, afs.fs_old_nspf, + afs.fs_maxfilesize); + printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n", + afs.fs_sbsize, afs.fs_cgsize, afs.fs_old_cgoffset, + afs.fs_old_cgmask); + printf("csaddr\t%d\tcssize\t%d\n", + afs.fs_old_csaddr, afs.fs_cssize); + printf("rotdelay %dms\trps\t%d\ttrackskew %d\tinterleave %d\n", + afs.fs_old_rotdelay, afs.fs_old_rps, afs.fs_old_trackskew, + afs.fs_old_interleave); + printf("nsect\t%d\tnpsect\t%d\tspc\t%d\n", + afs.fs_old_nsect, afs.fs_old_npsect, afs.fs_old_spc); + } printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n", afs.fs_sblkno, afs.fs_cblkno, afs.fs_iblkno, afs.fs_dblkno); - printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n", - afs.fs_sbsize, afs.fs_cgsize, afs.fs_cgoffset, afs.fs_cgmask); - printf("csaddr\t%d\tcssize\t%d\tshift\t%d\tmask\t0x%08x\n", - afs.fs_csaddr, afs.fs_cssize, afs.fs_csshift, afs.fs_csmask); printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\tclean\t%d\n", afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly, afs.fs_clean); printf("flags\t"); @@ -177,43 +222,24 @@ dumpfs(const char *name) printf("unclean "); if (afs.fs_flags & FS_DOSOFTDEP) printf("soft-updates "); - if ((afs.fs_flags & ~(FS_UNCLEAN | FS_DOSOFTDEP)) != 0) - printf("unknown flags (%#x)", - afs.fs_flags & ~(FS_UNCLEAN | FS_DOSOFTDEP)); + if (afs.fs_flags & FS_NEEDSFSCK) + printf("needs fsck run "); + if (afs.fs_flags & FS_INDEXDIRS) + printf("indexed directories "); + if ((afs.fs_flags & + ~(FS_UNCLEAN | FS_DOSOFTDEP | FS_NEEDSFSCK | FS_INDEXDIRS)) != 0) + printf("unknown flags (%#x)", afs.fs_flags & + ~(FS_UNCLEAN | FS_DOSOFTDEP | + FS_NEEDSFSCK | FS_INDEXDIRS)); putchar('\n'); - if (afs.fs_cpc != 0) - printf("blocks available in each of %d rotational positions", - afs.fs_nrpos); - else - printf("(no rotational position table)\n"); - for (c = 0; c < afs.fs_cpc; c++) { - printf("\ncylinder number %d:", c); - for (i = 0; i < afs.fs_nrpos; i++) { - if (fs_postbl(&afs, c)[i] == -1) - continue; - printf("\n position %d:\t", i); - for (j = fs_postbl(&afs, c)[i], k = 1; ; - j += fs_rotbl(&afs)[j], k++) { - printf("%5d", j); - if (k % 12 == 0) - printf("\n\t\t"); - if (fs_rotbl(&afs)[j] == 0) - break; - } - } - } printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t"); afs.fs_csp = calloc(1, afs.fs_cssize); - for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) { - size = afs.fs_cssize - i < afs.fs_bsize ? - afs.fs_cssize - i : afs.fs_bsize; - if (lseek(fd, - (off_t)(fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag))) * - (off_t)dev_bsize, SEEK_SET) == (off_t)-1) - goto err; - if (read(fd, (char *)afs.fs_csp + i, size) != size) - goto err; - } + if (lseek(fd, + (off_t)(fsbtodb(&afs, afs.fs_csaddr)) * (off_t)dev_bsize, + SEEK_SET) == (off_t)-1) + goto err; + if (read(fd, (char *)afs.fs_csp, afs.fs_cssize) != afs.fs_cssize) + goto err; for (i = 0; i < afs.fs_ncg; i++) { struct csum *cs = &afs.fs_cs(&afs, i); if (i && i % 4 == 0) @@ -222,13 +248,14 @@ dumpfs(const char *name) cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree); } printf("\n"); - if (afs.fs_ncyl % afs.fs_cpg) { - printf("cylinders in last group %d\n", - i = afs.fs_ncyl % afs.fs_cpg); - printf("blocks in last group %d\n", - i * afs.fs_spc / NSPB(&afs)); + if (fssize % afs.fs_fpg) { + if (afs.fs_magic == FS_UFS1_MAGIC) + printf("cylinders in last group %d\n", + howmany(afs.fs_old_size % afs.fs_fpg, + afs.fs_old_spc / afs.fs_old_nspf)); + printf("blocks in last group %d\n\n", + (fssize % afs.fs_fpg) / afs.fs_frag); } - printf("\n"); for (i = 0; i < afs.fs_ncg; i++) if (dumpcg(name, fd, i)) goto err; @@ -244,6 +271,7 @@ err: if (fd != -1) int dumpcg(const char *name, int fd, int c) { + time_t time; off_t cur; int i, j; @@ -255,12 +283,19 @@ dumpcg(const char *name, int fd, int c) warnx("%s: error reading cg", name); return (1); } - printf("magic\t%x\ttell\t%qx\ttime\t%s", - afs.fs_postblformat == FS_42POSTBLFMT ? - ((struct ocg *)&acg)->cg_magic : acg.cg_magic, - cur, ctime(&acg.cg_time)); - printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n", - acg.cg_cgx, acg.cg_ncyl, acg.cg_niblk, acg.cg_ndblk); + if (afs.fs_magic == FS_UFS2_MAGIC) { + time = acg.cg_time; + printf("magic\t%x\ttell\t%qx\ttime\t%s", + acg.cg_magic, cur, ctime(&time)); + printf("cgx\t%d\tndblk\t%d\tniblk\t%d\tinitiblk %d\n", + acg.cg_cgx, acg.cg_ndblk, acg.cg_niblk, acg.cg_initediblk); + } else { + printf("magic\t%x\ttell\t%qx\ttime\t%s", + acg.cg_magic, cur, ctime(&acg.cg_old_time)); + printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n", + acg.cg_cgx, acg.cg_old_ncyl, acg.cg_old_niblk, + acg.cg_ndblk); + } printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", acg.cg_cs.cs_nbfree, acg.cg_cs.cs_ndir, acg.cg_cs.cs_nifree, acg.cg_cs.cs_nffree); @@ -286,23 +321,10 @@ dumpcg(const char *name, int fd, int c) pbits(cg_clustersfree(&acg), acg.cg_nclusterblks); } else printf("\n"); - printf("iused:\t"); + printf("inodes used:\t"); pbits(cg_inosused(&acg), afs.fs_ipg); - printf("free:\t"); + printf("blks free:\t"); pbits(cg_blksfree(&acg), afs.fs_fpg); - printf("b:\n"); - for (i = 0; i < afs.fs_cpg; i++) { - if (cg_blktot(&acg)[i] == 0) - continue; - printf(" c%d:\t(%d)\t", i, cg_blktot(&acg)[i]); - for (j = 0; j < afs.fs_nrpos; j++) { - if (afs.fs_cpc > 0 && - fs_postbl(&afs, i % afs.fs_cpc)[j] == -1) - continue; - printf(" %d", cg_blks(&afs, &acg, i)[j]); - } - printf("\n"); - } return (0); }; 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); } diff --git a/sbin/fsdb/fsdb.c b/sbin/fsdb/fsdb.c index 0f32762..9971b7c 100644 --- a/sbin/fsdb/fsdb.c +++ b/sbin/fsdb/fsdb.c @@ -280,7 +280,7 @@ cmdloop(void) return rval; } -struct dinode *curinode; +union dinode *curinode; ino_t curinum, ocurrent; #define GETINUM(ac,inum) inum = strtoul(argv[ac], &cp, 0); \ @@ -317,7 +317,7 @@ CMDFUNCSTART(back) CMDFUNCSTART(zapi) { ino_t inum; - struct dinode *dp; + union dinode *dp; char *cp; GETINUM(1,inum); @@ -350,7 +350,8 @@ CMDFUNCSTART(uplink) { if (!checkactive()) return 1; - printf("inode %d link count now %d\n", curinum, ++curinode->di_nlink); + DIP(curinode, di_nlink) += 1; + printf("inode %d link count now %d\n", curinum, DIP(curinode, di_nlink)); inodirty(); return 0; } @@ -359,7 +360,8 @@ CMDFUNCSTART(downlink) { if (!checkactive()) return 1; - printf("inode %d link count now %d\n", curinum, --curinode->di_nlink); + DIP(curinode, di_nlink) -= 1; + printf("inode %d link count now %d\n", curinum, DIP(curinode, di_nlink)); inodirty(); return 0; } @@ -617,7 +619,7 @@ CMDFUNCSTART(newtype) if (!checkactive()) return 1; - type = curinode->di_mode & IFMT; + type = DIP(curinode, di_mode) & IFMT; for (tp = typenamemap; tp < &typenamemap[sizeof(typenamemap)/sizeof(*typenamemap)]; tp++) { @@ -632,8 +634,8 @@ CMDFUNCSTART(newtype) warnx("try one of `file', `dir', `socket', `fifo'"); return 1; } - curinode->di_mode &= ~IFMT; - curinode->di_mode |= type; + DIP(curinode, di_mode) &= ~IFMT; + DIP(curinode, di_mode) |= type; inodirty(); printactive(0); return 0; @@ -654,7 +656,7 @@ CMDFUNCSTART(chlen) return 1; } - curinode->di_size = len; + DIP(curinode, di_size) = len; inodirty(); printactive(0); return rval; @@ -675,8 +677,8 @@ CMDFUNCSTART(chmode) return 1; } - curinode->di_mode &= ~07777; - curinode->di_mode |= modebits; + DIP(curinode, di_mode) &= ~07777; + DIP(curinode, di_mode) |= modebits; inodirty(); printactive(0); return rval; @@ -701,7 +703,7 @@ CMDFUNCSTART(chaflags) warnx("flags set beyond 32-bit range of field (%lx)\n", flags); return(1); } - curinode->di_flags = flags; + DIP(curinode, di_flags) = flags; inodirty(); printactive(0); return rval; @@ -726,7 +728,7 @@ CMDFUNCSTART(chgen) warnx("gen set beyond 32-bit range of field (%lx)\n", gen); return(1); } - curinode->di_gen = gen; + DIP(curinode, di_gen) = gen; inodirty(); printactive(0); return rval; @@ -751,7 +753,7 @@ CMDFUNCSTART(linkcount) return 1; } - curinode->di_nlink = lcnt; + DIP(curinode, di_nlink) = lcnt; inodirty(); printactive(0); return rval; @@ -778,7 +780,7 @@ CMDFUNCSTART(chowner) } } - curinode->di_uid = uid; + DIP(curinode, di_uid) = uid; inodirty(); printactive(0); return rval; @@ -804,18 +806,17 @@ CMDFUNCSTART(chgroup) } } - curinode->di_gid = gid; + DIP(curinode, di_gid) = gid; inodirty(); printactive(0); return rval; } int -dotime(char *name, struct timespec *rts) +dotime(char *name, time_t *secp, int32_t *nsecp) { char *p, *val; struct tm t; - int32_t sec; int32_t nsec; p = strchr(name, '.'); if (p) { @@ -832,6 +833,7 @@ badformat: warnx("date format: YYYYMMDDHHMMSS[.nsec]"); return 1; } + *nsecp = nsec; for (p = name; *p; p++) if (*p < '0' || *p > '9') @@ -855,20 +857,26 @@ badformat: t.tm_sec = VAL() + t.tm_sec * 10; t.tm_isdst = -1; - sec = mktime(&t); - if (sec == -1) { + *secp = mktime(&t); + if (*secp == -1) { warnx("date/time out of range"); return 1; } - rts->tv_sec = sec; - rts->tv_nsec = nsec; return 0; } CMDFUNCSTART(chmtime) { - if (dotime(argv[1], &curinode->di_ctime)) + time_t secs; + int32_t nsecs; + + if (dotime(argv[1], &secs, &nsecs)) return 1; + if (sblock.fs_magic == FS_UFS1_MAGIC) + curinode->dp1.di_mtime = _time_to_time32(secs); + else + curinode->dp2.di_mtime = _time_to_time64(secs); + DIP(curinode, di_mtimensec) = nsecs; inodirty(); printactive(0); return 0; @@ -876,8 +884,16 @@ CMDFUNCSTART(chmtime) CMDFUNCSTART(chatime) { - if (dotime(argv[1], &curinode->di_ctime)) + time_t secs; + int32_t nsecs; + + if (dotime(argv[1], &secs, &nsecs)) return 1; + if (sblock.fs_magic == FS_UFS1_MAGIC) + curinode->dp1.di_atime = _time_to_time32(secs); + else + curinode->dp2.di_atime = _time_to_time64(secs); + DIP(curinode, di_atimensec) = nsecs; inodirty(); printactive(0); return 0; @@ -885,8 +901,16 @@ CMDFUNCSTART(chatime) CMDFUNCSTART(chctime) { - if (dotime(argv[1], &curinode->di_ctime)) + time_t secs; + int32_t nsecs; + + if (dotime(argv[1], &secs, &nsecs)) return 1; + if (sblock.fs_magic == FS_UFS1_MAGIC) + curinode->dp1.di_ctime = _time_to_time32(secs); + else + curinode->dp2.di_ctime = _time_to_time64(secs); + DIP(curinode, di_ctimensec) = nsecs; inodirty(); printactive(0); return 0; diff --git a/sbin/fsdb/fsdb.h b/sbin/fsdb/fsdb.h index be16016..442ae12 100644 --- a/sbin/fsdb/fsdb.h +++ b/sbin/fsdb/fsdb.h @@ -30,9 +30,9 @@ * $FreeBSD$ */ -extern int bread(int fd, char *buf, ufs_daddr_t blk, long size); -extern void bwrite(int fd, char *buf, ufs_daddr_t blk, long size); -extern void rwerror(char *mesg, ufs_daddr_t blk); +extern int bread(int fd, char *buf, ufs2_daddr_t blk, long size); +extern void bwrite(int fd, char *buf, ufs2_daddr_t blk, long size); +extern void rwerror(char *mesg, ufs2_daddr_t blk); extern int reply(char *question); extern long dev_bsize; @@ -50,13 +50,13 @@ struct cmdtable { #define FL_WR 0x0001 /* wants to write */ int (*handler)(int argc, char *argv[]); }; -extern struct dinode *curinode; +extern union dinode *curinode; extern ino_t curinum; int argcount(struct cmdtable *cmdp, int argc, char *argv[]); char **crack(char *line, int *argc); char **recrack(char *line, int *argc, int argc_max); -void printstat(const char *cp, ino_t inum, struct dinode *dp); +void printstat(const char *cp, ino_t inum, union dinode *dp); int printactive(int doblocks); int checkactive(void); int checkactivedir(void); diff --git a/sbin/fsdb/fsdbutil.c b/sbin/fsdb/fsdbutil.c index 96c48b0..b0d4c12 100644 --- a/sbin/fsdb/fsdbutil.c +++ b/sbin/fsdb/fsdbutil.c @@ -50,8 +50,8 @@ static const char rcsid[] = #include "fsck.h" static int charsperline(void); -static int printindir(ufs_daddr_t blk, int level, char *bufp); -static void printblocks(ino_t inum, struct dinode *dp); +static int printindir(ufs2_daddr_t blk, int level, char *bufp); +static void printblocks(ino_t inum, union dinode *dp); char ** crack(char *line, int *argc) @@ -106,15 +106,17 @@ argcount(struct cmdtable *cmdp, int argc, char *argv[]) } void -printstat(const char *cp, ino_t inum, struct dinode *dp) +printstat(const char *cp, ino_t inum, union dinode *dp) { struct group *grp; struct passwd *pw; + ufs2_daddr_t blocks; + int64_t gen; char *p; time_t t; printf("%s: ", cp); - switch (dp->di_mode & IFMT) { + switch (DIP(dp, di_mode) & IFMT) { case IFDIR: puts("directory"); break; @@ -123,19 +125,25 @@ printstat(const char *cp, ino_t inum, struct dinode *dp) break; case IFBLK: printf("block special (%d,%d)", - major(dp->di_rdev), minor(dp->di_rdev)); + major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev))); break; case IFCHR: printf("character special (%d,%d)", - major(dp->di_rdev), minor(dp->di_rdev)); + major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev))); break; case IFLNK: fputs("symlink",stdout); - if (dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN && - dp->di_blocks == 0) - printf(" to `%.*s'\n", (int) dp->di_size, (char *)dp->di_shortlink); - else - putchar('\n'); + if (DIP(dp, di_size) > 0 && + DIP(dp, di_size) < sblock.fs_maxsymlinklen && + DIP(dp, di_blocks) == 0) { + if (sblock.fs_magic == FS_UFS1_MAGIC) + p = (caddr_t)dp->dp1.di_db; + else + p = (caddr_t)dp->dp2.di_db; + printf(" to `%.*s'\n", (int) DIP(dp, di_size), p); + } else { + putchar('\n'); + } break; case IFSOCK: puts("socket"); @@ -144,31 +152,43 @@ printstat(const char *cp, ino_t inum, struct dinode *dp) puts("fifo"); break; } - printf("I=%lu MODE=%o SIZE=%qu", (u_long)inum, dp->di_mode, dp->di_size); - t = dp->di_mtime; + printf("I=%lu MODE=%o SIZE=%qu", (u_long)inum, DIP(dp, di_mode), + DIP(dp, di_size)); + if (sblock.fs_magic == FS_UFS1_MAGIC) + t = _time32_to_time(dp->dp1.di_mtime); + else + t = _time64_to_time(dp->dp2.di_mtime); p = ctime(&t); printf("\n\tMTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20], - dp->di_mtimensec); - t = dp->di_ctime; + DIP(dp, di_mtimensec)); + if (sblock.fs_magic == FS_UFS1_MAGIC) + t = _time32_to_time(dp->dp1.di_ctime); + else + t = _time64_to_time(dp->dp2.di_ctime); p = ctime(&t); printf("\n\tCTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20], - dp->di_ctimensec); - t = dp->di_atime; + DIP(dp, di_ctimensec)); + if (sblock.fs_magic == FS_UFS1_MAGIC) + t = _time32_to_time(dp->dp1.di_atime); + else + t = _time64_to_time(dp->dp2.di_atime); p = ctime(&t); printf("\n\tATIME=%15.15s %4.4s [%d nsec]\n", &p[4], &p[20], - dp->di_atimensec); + DIP(dp, di_atimensec)); - if ((pw = getpwuid(dp->di_uid))) + if ((pw = getpwuid(DIP(dp, di_uid)))) printf("OWNER=%s ", pw->pw_name); else - printf("OWNUID=%u ", dp->di_uid); - if ((grp = getgrgid(dp->di_gid))) + printf("OWNUID=%u ", DIP(dp, di_uid)); + if ((grp = getgrgid(DIP(dp, di_gid)))) printf("GRP=%s ", grp->gr_name); else - printf("GID=%u ", dp->di_gid); + printf("GID=%u ", DIP(dp, di_gid)); - printf("LINKCNT=%hd FLAGS=%#x BLKCNT=%x GEN=%x\n", dp->di_nlink, dp->di_flags, - dp->di_blocks, dp->di_gen); + blocks = DIP(dp, di_blocks); + gen = DIP(dp, di_gen); + printf("LINKCNT=%hd FLAGS=%#x BLKCNT=%qx GEN=%qx\n", DIP(dp, di_nlink), + DIP(dp, di_flags), blocks, gen); } @@ -199,12 +219,12 @@ charsperline(void) * Recursively print a list of indirect blocks. */ static int -printindir(ufs_daddr_t blk, int level, char *bufp) +printindir(ufs2_daddr_t blk, int level, char *bufp) { struct bufarea buf, *bp; - char tempbuf[32]; /* enough to print an ufs_daddr_t */ + char tempbuf[32]; /* enough to print an ufs2_daddr_t */ int i, j, cpl, charssofar; - ufs_daddr_t blkno; + ufs2_daddr_t blkno; if (level == 0) { /* for the final indirect level, don't use the cache */ @@ -219,13 +239,16 @@ printindir(ufs_daddr_t blk, int level, char *bufp) cpl = charsperline(); for (i = charssofar = 0; i < NINDIR(&sblock); i++) { - blkno = bp->b_un.b_indir[i]; + if (sblock.fs_magic == FS_UFS1_MAGIC) + blkno = bp->b_un.b_indir1[i]; + else + blkno = bp->b_un.b_indir2[i]; if (blkno == 0) { if (level == 0) putchar('\n'); return 0; } - j = sprintf(tempbuf, "%d", blkno); + j = sprintf(tempbuf, "%qd", blkno); if (level == 0) { charssofar += j; if (charssofar >= cpl - 2) { @@ -253,30 +276,32 @@ printindir(ufs_daddr_t blk, int level, char *bufp) * Print the block pointers for one inode. */ static void -printblocks(ino_t inum, struct dinode *dp) +printblocks(ino_t inum, union dinode *dp) { char *bufp; int i, j, nfrags; long ndb, offset; + ufs2_daddr_t blkno; printf("Blocks for inode %d:\n", inum); printf("Direct blocks:\n"); - ndb = howmany(dp->di_size, sblock.fs_bsize); + ndb = howmany(DIP(dp, di_size), sblock.fs_bsize); for (i = 0; i < NDADDR; i++) { - if (dp->di_db[i] == 0) { + if (DIP(dp, di_db[i]) == 0) { putchar('\n'); return; } if (i > 0) printf(", "); - printf("%d", dp->di_db[i]); - if (--ndb == 0 && (offset = blkoff(&sblock, dp->di_size)) != 0) { + blkno = DIP(dp, di_db[i]); + printf("%qd", blkno); + if (--ndb == 0 && (offset = blkoff(&sblock, DIP(dp, di_size))) != 0) { nfrags = numfrags(&sblock, fragroundup(&sblock, offset)); printf(" (%d frag%s)", nfrags, nfrags > 1? "s": ""); } } putchar('\n'); - if (dp->di_ib[0] == 0) + if (DIP(dp, di_ib[0]) == 0) return; bufp = malloc((unsigned int)sblock.fs_bsize); @@ -284,7 +309,7 @@ printblocks(ino_t inum, struct dinode *dp) errx(EEXIT, "cannot allocate indirect block buffer"); printf("Indirect blocks:\n"); for (i = 0; i < NIADDR; i++) - if (printindir(dp->di_ib[i], i, bufp) == 0) + if (printindir(DIP(dp, di_ib[i]), i, bufp) == 0) break; free(bufp); } @@ -307,7 +332,7 @@ checkactivedir(void) warnx("no current inode\n"); return 0; } - if ((curinode->di_mode & IFMT) != IFDIR) { + if ((DIP(curinode, di_mode) & IFMT) != IFDIR) { warnx("inode %d not a directory", curinum); return 0; } @@ -319,7 +344,7 @@ printactive(int doblocks) { if (!checkactive()) return 1; - switch (curinode->di_mode & IFMT) { + switch (DIP(curinode, di_mode) & IFMT) { case IFDIR: case IFREG: case IFBLK: @@ -337,7 +362,7 @@ printactive(int doblocks) break; default: printf("current inode %d: screwy itype 0%o (mode 0%o)?\n", - curinum, curinode->di_mode & IFMT, curinode->di_mode); + curinum, DIP(curinode, di_mode) & IFMT, DIP(curinode, di_mode)); break; } return 0; diff --git a/sbin/fsirand/fsirand.c b/sbin/fsirand/fsirand.c index e908f2a..2e555be 100644 --- a/sbin/fsirand/fsirand.c +++ b/sbin/fsirand/fsirand.c @@ -40,8 +40,8 @@ static const char rcsid[] = #include <sys/time.h> #include <sys/resource.h> -#include <ufs/ffs/fs.h> #include <ufs/ufs/dinode.h> +#include <ufs/ffs/fs.h> #include <err.h> #include <errno.h> @@ -54,6 +54,11 @@ static const char rcsid[] = static void usage(void) __dead2; int fsirand(char *); +/* + * Possible superblock locations ordered from most to least likely. + */ +static int sblock_try[] = SBLOCKSEARCH; + int printonly = 0, force = 0, ignorelabel = 0; int @@ -104,14 +109,15 @@ main(int argc, char *argv[]) int fsirand(char *device) { - static struct dinode *inodebuf; - static size_t oldibufsize; + struct ufs1_dinode *dp1; + struct ufs2_dinode *dp2; + caddr_t inodebuf; size_t ibufsize; struct fs *sblock; ino_t inumber, maxino; - daddr_t dblk; - char sbuf[SBSIZE], sbuftmp[SBSIZE]; - int devfd, n, cg; + ufs2_daddr_t sblockloc, dblk; + char sbuf[SBLOCKSIZE], sbuftmp[SBLOCKSIZE]; + int i, devfd, n, cg; u_int32_t bsize = DEV_BSIZE; struct disklabel label; @@ -132,27 +138,34 @@ fsirand(char *device) /* Read in master superblock */ (void)memset(&sbuf, 0, sizeof(sbuf)); sblock = (struct fs *)&sbuf; - if (lseek(devfd, SBOFF, SEEK_SET) == -1) { - warn("can't seek to superblock (%qd) on %s", SBOFF, device); - return (1); + for (i = 0; sblock_try[i] != -1; i++) { + sblockloc = sblock_try[i]; + if (lseek(devfd, sblockloc, SEEK_SET) == -1) { + warn("can't seek to superblock (%qd) on %s", + sblockloc, device); + return (1); + } + if ((n = read(devfd, (void *)sblock, SBLOCKSIZE))!=SBLOCKSIZE) { + warnx("can't read superblock on %s: %s", device, + (n < SBLOCKSIZE) ? "short read" : strerror(errno)); + return (1); + } + if ((sblock->fs_magic == FS_UFS1_MAGIC || + (sblock->fs_magic == FS_UFS2_MAGIC && + sblock->fs_sblockloc == + numfrags(sblock, sblock_try[i]))) && + sblock->fs_bsize <= MAXBSIZE && + sblock->fs_bsize >= sizeof(struct fs)) + break; } - if ((n = read(devfd, (void *)sblock, SBSIZE)) != SBSIZE) { - warnx("can't read superblock on %s: %s", device, - (n < SBSIZE) ? "short read" : strerror(errno)); + if (sblock_try[i] == -1) { + fprintf(stderr, "Cannot find filesystem superblock\n"); return (1); } maxino = sblock->fs_ncg * sblock->fs_ipg; - /* Simple sanity checks on the superblock */ - if (sblock->fs_magic != FS_MAGIC) { - warnx("bad magic number in superblock"); - return (1); - } - if (sblock->fs_sbsize > SBSIZE) { - warnx("superblock size is preposterous"); - return (1); - } - if (sblock->fs_postblformat == FS_42POSTBLFMT) { + if (sblock->fs_magic == FS_UFS1_MAGIC && + sblock->fs_old_inodefmt < FS_44INODEFMT) { warnx("filesystem format is too old, sorry"); return (1); } @@ -168,18 +181,19 @@ fsirand(char *device) if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) { warn("can't seek to %qd", (off_t)dblk * bsize); return (1); - } else if ((n = write(devfd, (void *)sblock, SBSIZE)) != SBSIZE) { + } else if ((n = write(devfd, (void *)sblock, SBLOCKSIZE)) != SBLOCKSIZE) { warn("can't read backup superblock %d on %s: %s", - cg + 1, device, (n < SBSIZE) ? "short write" + cg + 1, device, (n < SBLOCKSIZE) ? "short write" : strerror(errno)); return (1); } - if (sblock->fs_magic != FS_MAGIC) { + if (sblock->fs_magic != FS_UFS1_MAGIC && + sblock->fs_magic != FS_UFS2_MAGIC) { warnx("bad magic number in backup superblock %d on %s", cg + 1, device); return (1); } - if (sblock->fs_sbsize > SBSIZE) { + if (sblock->fs_sbsize > SBLOCKSIZE) { warnx("size of backup superblock %d on %s is preposterous", cg + 1, device); return (1); @@ -188,15 +202,15 @@ fsirand(char *device) sblock = (struct fs *)&sbuf; /* XXX - should really cap buffer at 512kb or so */ - ibufsize = sizeof(struct dinode) * sblock->fs_ipg; - if (oldibufsize < ibufsize) { - if ((inodebuf = realloc(inodebuf, ibufsize)) == NULL) - errx(1, "can't allocate memory for inode buffer"); - oldibufsize = ibufsize; - } + if (sblock->fs_magic == FS_UFS1_MAGIC) + ibufsize = sizeof(struct ufs1_dinode) * sblock->fs_ipg; + else + ibufsize = sizeof(struct ufs2_dinode) * sblock->fs_ipg; + if ((inodebuf = malloc(ibufsize)) == NULL) + errx(1, "can't allocate memory for inode buffer"); if (printonly && (sblock->fs_id[0] || sblock->fs_id[1])) { - if (sblock->fs_inodefmt >= FS_44INODEFMT && sblock->fs_id[0]) + if (sblock->fs_id[0]) (void)printf("%s was randomized on %s", device, ctime((const time_t *)&(sblock->fs_id[0]))); (void)printf("fsid: %x %x\n", sblock->fs_id[0], @@ -204,19 +218,20 @@ fsirand(char *device) } /* Randomize fs_id unless old 4.2BSD filesystem */ - if ((sblock->fs_inodefmt >= FS_44INODEFMT) && !printonly) { + if (!printonly) { /* Randomize fs_id and write out new sblock and backups */ sblock->fs_id[0] = (u_int32_t)time(NULL); sblock->fs_id[1] = random(); - if (lseek(devfd, SBOFF, SEEK_SET) == -1) { - warn("can't seek to superblock (%qd) on %s", SBOFF, + if (lseek(devfd, sblockloc, SEEK_SET) == -1) { + warn("can't seek to superblock (%qd) on %s", sblockloc, device); return (1); } - if ((n = write(devfd, (void *)sblock, SBSIZE)) != SBSIZE) { - warn("can't read superblock on %s: %s", device, - (n < SBSIZE) ? "short write" : strerror(errno)); + if ((n = write(devfd, (void *)sblock, SBLOCKSIZE)) != + SBLOCKSIZE) { + warn("can't write superblock on %s: %s", device, + (n < SBLOCKSIZE) ? "short write" : strerror(errno)); return (1); } } @@ -224,15 +239,16 @@ fsirand(char *device) /* For each cylinder group, randomize inodes and update backup sblock */ for (cg = 0, inumber = 0; cg < sblock->fs_ncg; cg++) { /* Update superblock if appropriate */ - if ((sblock->fs_inodefmt >= FS_44INODEFMT) && !printonly) { + if (!printonly) { dblk = fsbtodb(sblock, cgsblock(sblock, cg)); if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) { warn("can't seek to %qd", (off_t)dblk * bsize); return (1); - } else if ((n = write(devfd, (void *)sblock, SBSIZE)) != SBSIZE) { - warn("can't read backup superblock %d on %s: %s", - cg + 1, device, (n < SBSIZE) ? "short write" - : strerror(errno)); + } else if ((n = write(devfd, (void *)sblock, + SBLOCKSIZE)) != SBLOCKSIZE) { + warn("can't write backup superblock %d on %s: %s", + cg + 1, device, (n < SBLOCKSIZE) ? + "short write" : strerror(errno)); return (1); } } @@ -249,12 +265,19 @@ fsirand(char *device) } for (n = 0; n < sblock->fs_ipg; n++, inumber++) { + if (sblock->fs_magic == FS_UFS1_MAGIC) + dp1 = &((struct ufs1_dinode *)inodebuf)[n]; + else + dp2 = &((struct ufs2_dinode *)inodebuf)[n]; if (inumber >= ROOTINO) { if (printonly) - (void)printf("ino %d gen %x\n", inumber, - inodebuf[n].di_gen); + (void)printf("ino %d gen %qx\n", + inumber, + sblock->fs_magic == FS_UFS1_MAGIC ? + (quad_t)dp1->di_gen : dp2->di_gen); else - inodebuf[n].di_gen = random(); + (sblock->fs_magic == FS_UFS1_MAGIC ? + dp1->di_gen : dp2->di_gen) = random(); } } diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c index d11dc98..48cfad9 100644 --- a/sbin/growfs/growfs.c +++ b/sbin/growfs/growfs.c @@ -77,11 +77,17 @@ int _dbg_lvl_ = (DL_INFO); /* DL_TRC */ static union { struct fs fs; - char pad[SBSIZE]; + char pad[SBLOCKSIZE]; } fsun1, fsun2; #define sblock fsun1.fs /* the new superblock */ #define osblock fsun2.fs /* the old superblock */ +/* + * Possible superblock locations ordered from most to least likely. + */ +static int sblock_try[] = SBLOCKSEARCH; +static ufs2_daddr_t sblockloc; + static union { struct cg cg; char pad[MAXBSIZE]; @@ -89,25 +95,20 @@ static union { #define acg cgun1.cg /* a cylinder cgroup (new) */ #define aocg cgun2.cg /* an old cylinder group */ -static char ablk[MAXBSIZE]; /* a block */ -static char i1blk[MAXBSIZE]; /* some indirect blocks */ -static char i2blk[MAXBSIZE]; -static char i3blk[MAXBSIZE]; +static char ablk[MAXBSIZE]; /* a block */ - /* where to write back updated blocks */ -static daddr_t in_src, i1_src, i2_src, i3_src; +static struct csum *fscs; /* cylinder summary */ - /* what object contains the reference */ -enum pointer_source { - GFS_PS_INODE, - GFS_PS_IND_BLK_LVL1, - GFS_PS_IND_BLK_LVL2, - GFS_PS_IND_BLK_LVL3 +union dinode { + struct ufs1_dinode dp1; + struct ufs2_dinode dp2; }; - -static struct csum *fscs; /* cylinder summary */ - -static struct dinode zino[MAXBSIZE/sizeof(struct dinode)]; /* some inodes */ +#define DIP(dp, field) \ + ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ + (dp)->dp1.field : (dp)->dp2.field) +static ufs2_daddr_t inoblk; /* inode block address */ +static char inobuf[MAXBSIZE]; /* inode block */ +static int maxino; /* last valid inode */ /* * An array of elements of type struct gfs_bpp describes all blocks to @@ -115,8 +116,8 @@ static struct dinode zino[MAXBSIZE/sizeof(struct dinode)]; /* some inodes */ * summary for all cylinder groups located in the first cylinder group. */ struct gfs_bpp { - daddr_t old; /* old block number */ - daddr_t new; /* new block number */ + ufs2_daddr_t old; /* old block number */ + ufs2_daddr_t new; /* new block number */ #define GFS_FL_FIRST 1 #define GFS_FL_LAST 2 unsigned int flags; /* special handling required */ @@ -125,9 +126,9 @@ struct gfs_bpp { /* ******************************************************** PROTOTYPES ***** */ static void growfs(int, int, unsigned int); -static void rdfs(daddr_t, size_t, void *, int); -static void wtfs(daddr_t, size_t, void *, int, unsigned int); -static daddr_t alloc(void); +static void rdfs(ufs2_daddr_t, size_t, void *, int); +static void wtfs(ufs2_daddr_t, size_t, void *, int, unsigned int); +static ufs2_daddr_t alloc(void); static int charsperline(void); static void usage(void); static int isblock(struct fs *, unsigned char *, int); @@ -138,12 +139,14 @@ static void updjcg(int, time_t, int, int, unsigned int); static void updcsloc(time_t, int, int, unsigned int); static struct disklabel *get_disklabel(int); static void return_disklabel(int, struct disklabel *, unsigned int); -static struct dinode *ginode(ino_t, int, int); -static void frag_adjust(daddr_t, int); -static void cond_bl_upd(ufs_daddr_t *, struct gfs_bpp *, - enum pointer_source, int, unsigned int); +static union dinode *ginode(ino_t, int, int); +static void frag_adjust(ufs2_daddr_t, int); +static int cond_bl_upd(ufs2_daddr_t *, struct gfs_bpp *, int, int, + unsigned int); static void updclst(int); static void updrefs(int, ino_t, struct gfs_bpp *, int, int, unsigned int); +static void indirchk(ufs_lbn_t, ufs_lbn_t, ufs2_daddr_t, ufs_lbn_t, + struct gfs_bpp *, int, int, unsigned int); /* ************************************************************ growfs ***** */ /* @@ -221,16 +224,16 @@ growfs(int fsi, int fso, unsigned int Nflag) /* * Dump out summary information about filesystem. */ - printf("growfs:\t%d sectors in %d %s of %d tracks, %d sectors\n", - sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, - "cylinders", sblock.fs_ntrak, sblock.fs_nsect); -#define B2MBFACTOR (1 / (1024.0 * 1024.0)) - printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n", +# define B2MBFACTOR (1 / (1024.0 * 1024.0)) + printf("growfs: %.1fMB (%qd sectors) block size %d, fragment size %d\n", (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, - sblock.fs_ncg, sblock.fs_cpg, - (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, - sblock.fs_ipg); -#undef B2MBFACTOR + fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize, sblock.fs_fsize); + printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n", + sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, + sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); + if (sblock.fs_flags & FS_DOSOFTDEP) + printf("\twith soft updates\n"); +# undef B2MBFACTOR /* * Now build the cylinders group blocks and @@ -295,8 +298,7 @@ growfs(int fsi, int fso, unsigned int Nflag) * Now write the new superblock back to disk. */ sblock.fs_time = utime; - wtfs((daddr_t)(SBOFF / DEV_BSIZE), (size_t)SBSIZE, (void *)&sblock, - fso, Nflag); + wtfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag); DBG_PRINT0("sblock written\n"); DBG_DUMP_FS(&sblock, "new initial sblock"); @@ -338,7 +340,7 @@ growfs(int fsi, int fso, unsigned int Nflag) */ for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), - (size_t)SBSIZE, (void *)&sblock, fso, Nflag); + (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag); } DBG_PRINT0("sblock copies written\n"); DBG_DUMP_FS(&sblock, @@ -359,96 +361,110 @@ static void initcg(int cylno, time_t utime, int fso, unsigned int Nflag) { DBG_FUNC("initcg") - daddr_t cbase, d, dlower, dupper, dmax, blkno; - int i; + static caddr_t iobuf; + long i, j, d, dlower, dupper, blkno, start; + ufs2_daddr_t cbase, dmax; + struct ufs1_dinode *dp1; + struct ufs2_dinode *dp2; struct csum *cs; -#ifdef FSIRAND - int j; -#endif - - DBG_ENTER; + if (iobuf == NULL && (iobuf = malloc(sblock.fs_bsize)) == NULL) { + errx(37, "panic: cannot allocate I/O buffer"); + } /* * Determine block bounds for cylinder group. + * Allow space for super block summary information in first + * cylinder group. */ cbase = cgbase(&sblock, cylno); dmax = cbase + sblock.fs_fpg; - if (dmax > sblock.fs_size) { + if (dmax > sblock.fs_size) dmax = sblock.fs_size; - } dlower = cgsblock(&sblock, cylno) - cbase; dupper = cgdmin(&sblock, cylno) - cbase; - if (cylno == 0) { /* XXX fscs may be relocated */ + if (cylno == 0) /* XXX fscs may be relocated */ dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); - } - cs = fscs + cylno; - memset(&acg, 0, (size_t)sblock.fs_cgsize); + cs = &fscs[cylno]; + memset(&acg, 0, sblock.fs_cgsize); acg.cg_time = utime; acg.cg_magic = CG_MAGIC; acg.cg_cgx = cylno; - if (cylno == sblock.fs_ncg - 1) { - acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; - } else { - acg.cg_ncyl = sblock.fs_cpg; - } acg.cg_niblk = sblock.fs_ipg; + acg.cg_initediblk = sblock.fs_ipg; acg.cg_ndblk = dmax - cbase; - if (sblock.fs_contigsumsize > 0) { + if (sblock.fs_contigsumsize > 0) acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; + start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); + if (sblock.fs_magic == FS_UFS2_MAGIC) { + acg.cg_iusedoff = start; + } else { + acg.cg_old_ncyl = sblock.fs_old_cpg; + acg.cg_old_time = acg.cg_time; + acg.cg_time = 0; + acg.cg_old_niblk = acg.cg_niblk; + acg.cg_niblk = 0; + acg.cg_initediblk = 0; + acg.cg_old_btotoff = start; + acg.cg_old_boff = acg.cg_old_btotoff + + sblock.fs_old_cpg * sizeof(int32_t); + acg.cg_iusedoff = acg.cg_old_boff + + sblock.fs_old_cpg * sizeof(u_int16_t); } - acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); - acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t); - acg.cg_iusedoff = acg.cg_boff + - sblock.fs_cpg * sblock.fs_nrpos * sizeof(u_int16_t); acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); - if (sblock.fs_contigsumsize <= 0) { - acg.cg_nextfreeoff = acg.cg_freeoff + - howmany(sblock.fs_cpg* sblock.fs_spc/ NSPF(&sblock), NBBY); - } else { - acg.cg_clustersumoff = acg.cg_freeoff + howmany - (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) - - sizeof(u_int32_t); + acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, NBBY); + if (sblock.fs_contigsumsize > 0) { acg.cg_clustersumoff = - roundup(acg.cg_clustersumoff, sizeof(u_int32_t)); + roundup(acg.cg_nextfreeoff, sizeof(u_int32_t)); + acg.cg_clustersumoff -= sizeof(u_int32_t); acg.cg_clusteroff = acg.cg_clustersumoff + (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t); - acg.cg_nextfreeoff = acg.cg_clusteroff + howmany - (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY); + acg.cg_nextfreeoff = acg.cg_clusteroff + + howmany(fragstoblks(&sblock, sblock.fs_fpg), NBBY); } - if (acg.cg_nextfreeoff-(int)(&acg.cg_firstfield) > sblock.fs_cgsize) { + if (acg.cg_nextfreeoff > sblock.fs_cgsize) { /* - * XXX This should never happen as we would have had that panic - * already on filesystem creation + * This should never happen as we would have had that panic + * already on filesystem creation */ errx(37, "panic: cylinder group too big"); } acg.cg_cs.cs_nifree += sblock.fs_ipg; if (cylno == 0) - for (i = 0; (size_t)i < ROOTINO; i++) { + for (i = 0; i < ROOTINO; i++) { setbit(cg_inosused(&acg), i); acg.cg_cs.cs_nifree--; } + bzero(iobuf, sblock.fs_bsize); for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) { + dp1 = (struct ufs1_dinode *)iobuf; + dp2 = (struct ufs2_dinode *)iobuf; #ifdef FSIRAND - for (j = 0; j < sblock.fs_bsize / sizeof(struct dinode); j++) { - zino[j].di_gen = random(); - } + for (j = 0; j < INOPB(&sblock); j++) + if (sblock.fs_magic == FS_UFS1_MAGIC) { + dp1->di_gen = random(); + dp1++; + } else { + dp2->di_gen = random(); + dp2++; + } #endif wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), - (size_t)sblock.fs_bsize, (void *)zino, fso, Nflag); + sblock.fs_bsize, iobuf, fso, Nflag); } - for (d = 0; d < dlower; d += sblock.fs_frag) { - blkno = d / sblock.fs_frag; - setblock(&sblock, cg_blksfree(&acg), blkno); - if (sblock.fs_contigsumsize > 0) { - setbit(cg_clustersfree(&acg), blkno); + if (cylno > 0) { + /* + * In cylno 0, beginning space is reserved + * for boot and super blocks. + */ + for (d = 0; d < dlower; d += sblock.fs_frag) { + blkno = d / sblock.fs_frag; + setblock(&sblock, cg_blksfree(&acg), blkno); + if (sblock.fs_contigsumsize > 0) + setbit(cg_clustersfree(&acg), blkno); + acg.cg_cs.cs_nbfree++; } - acg.cg_cs.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]++; + sblock.fs_dsize += dlower; } - sblock.fs_dsize += dlower; sblock.fs_dsize += acg.cg_ndblk - dupper; if ((i = dupper % sblock.fs_frag)) { acg.cg_frsum[sblock.fs_frag - i]++; @@ -457,53 +473,47 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag) acg.cg_cs.cs_nffree++; } } - for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) { + for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk; + d += sblock.fs_frag) { blkno = d / sblock.fs_frag; setblock(&sblock, cg_blksfree(&acg), blkno); - if (sblock.fs_contigsumsize > 0) { + if (sblock.fs_contigsumsize > 0) setbit(cg_clustersfree(&acg), blkno); - } acg.cg_cs.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]++; - d += sblock.fs_frag; - } - if (d < dmax - cbase) { - acg.cg_frsum[dmax - cbase - d]++; - for (; d < dmax - cbase; d++) { + } + if (d < acg.cg_ndblk) { + acg.cg_frsum[acg.cg_ndblk - d]++; + for (; d < acg.cg_ndblk; d++) { setbit(cg_blksfree(&acg), d); acg.cg_cs.cs_nffree++; } } if (sblock.fs_contigsumsize > 0) { - int32_t *sump = cg_clustersum(&acg); - u_char *mapp = cg_clustersfree(&acg); - int map = *mapp++; - int bit = 1; - int run = 0; + int32_t *sump = cg_clustersum(&acg); + u_char *mapp = cg_clustersfree(&acg); + int map = *mapp++; + int bit = 1; + int run = 0; for (i = 0; i < acg.cg_nclusterblks; i++) { - if ((map & bit) != 0) { + if ((map & bit) != 0) run++; - } else if (run != 0) { - if (run > sblock.fs_contigsumsize) { + else if (run != 0) { + if (run > sblock.fs_contigsumsize) run = sblock.fs_contigsumsize; - } sump[run]++; run = 0; } - if ((i & (NBBY - 1)) != (NBBY - 1)) { + if ((i & (NBBY - 1)) != NBBY - 1) bit <<= 1; - } else { + else { map = *mapp++; bit = 1; } } if (run != 0) { - if (run > sblock.fs_contigsumsize) { + if (run > sblock.fs_contigsumsize) run = sblock.fs_contigsumsize; - } sump[run]++; } } @@ -513,7 +523,7 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag) sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; *cs = acg.cg_cs; wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), - (size_t)sblock.fs_bsize, (void *)&acg, fso, Nflag); + sblock.fs_bsize, (char *)&acg, fso, Nflag); DBG_DUMP_CG(&sblock, "new cg", &acg); @@ -530,7 +540,7 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag) * statistic, which seems to be otherwise an rather complex operation. */ static void -frag_adjust(daddr_t frag, int sign) +frag_adjust(ufs2_daddr_t frag, int sign) { DBG_FUNC("frag_adjust") int fragsize; @@ -590,72 +600,57 @@ frag_adjust(daddr_t frag, int sign) * as there is no easy way for our general block reading engine to figure * out if a write back operation is needed. */ -static void -cond_bl_upd(ufs_daddr_t *block, struct gfs_bpp *field, - enum pointer_source source, int fso, unsigned int Nflag) +static int +cond_bl_upd(ufs2_daddr_t *block, struct gfs_bpp *field, int fsi, int fso, + unsigned int Nflag) { DBG_FUNC("cond_bl_upd") - struct gfs_bpp *f; - char *src; - daddr_t dst=0; + struct gfs_bpp *f; + ufs2_daddr_t src, dst; + int fragnum; + void *ibuf; DBG_ENTER; - f=field; - while(f->old) { /* for all old blocks */ - if(*block/sblock.fs_frag == f->old) { - /* - * The fragment is part of the block, so update. - */ - *block=(f->new*sblock.fs_frag+(*block%sblock.fs_frag)); - f->found++; - DBG_PRINT3("scg (%d->%d)[%d] reference updated\n", - f->old, - f->new, - *block%sblock.fs_frag); - - /* Write the block back to disk immediately */ - switch (source) { - case GFS_PS_INODE: - src=ablk; - dst=in_src; - break; - case GFS_PS_IND_BLK_LVL1: - src=i1blk; - dst=i1_src; - break; - case GFS_PS_IND_BLK_LVL2: - src=i2blk; - dst=i2_src; - break; - case GFS_PS_IND_BLK_LVL3: - src=i3blk; - dst=i3_src; - break; - default: /* error */ - src=NULL; - break; - } - if(src) { - /* - * XXX If src is not of type inode we have to - * implement copy on write here in case - * of active snapshots. - */ - wtfs(dst, (size_t)sblock.fs_bsize, (void *)src, - fso, Nflag); - } + f = field; + for (f = field; f->old != 0; f++) { + src = *block; + if (fragstoblks(&sblock, src) != f->old) + continue; + /* + * The fragment is part of the block, so update. + */ + dst = blkstofrags(&sblock, f->new); + fragnum = fragnum(&sblock, src); + *block = dst + fragnum; + f->found++; + DBG_PRINT3("scg (%d->%d)[%d] reference updated\n", + f->old, + f->new, + fragnum); - /* - * The same block can't be found again in this loop. - */ - break; - } - f++; + /* + * Copy the block back immediately. + * + * XXX If src is is from an indirect block we have + * to implement copy on write here in case of + * active snapshots. + */ + ibuf = malloc(sblock.fs_bsize); + if (!ibuf) + errx(1, "malloc failed"); + src -= fragnum; + rdfs(fsbtodb(&sblock, src), (size_t)sblock.fs_bsize, ibuf, fsi); + wtfs(dst, (size_t)sblock.fs_bsize, ibuf, fso, Nflag); + free(ibuf); + /* + * The same block can't be found again in this loop. + */ + return (1); } DBG_LEAVE; - return; + return (0); } /* ************************************************************ updjcg ***** */ @@ -674,7 +669,7 @@ static void updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) { DBG_FUNC("updjcg") - daddr_t cbase, dmax, dupper; + ufs2_daddr_t cbase, dmax, dupper; struct csum *cs; int i,k; int j=0; @@ -703,7 +698,8 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) */ if(cgbase(&osblock, cylno+1) == osblock.fs_size) { - acg.cg_ncyl=sblock.fs_cpg; + if (sblock.fs_magic == FS_UFS1_MAGIC) + acg.cg_old_ncyl=sblock.fs_old_cpg; wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); @@ -742,15 +738,20 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) /* * This is still the last cylinder group. */ - acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; + if (sblock.fs_magic == FS_UFS1_MAGIC) + acg.cg_old_ncyl = + sblock.fs_old_ncyl % sblock.fs_old_cpg; } else { - acg.cg_ncyl = sblock.fs_cpg; + acg.cg_old_ncyl = sblock.fs_old_cpg; } - DBG_PRINT4("jcg dbg: %d %u %d %u\n", + DBG_PRINT2("jcg dbg: %d %u", cylno, - sblock.fs_ncg, - acg.cg_ncyl, - sblock.fs_cpg); + sblock.fs_ncg); + if (sblock.fs_magic == FS_UFS1_MAGIC) + DBG_PRINT2("%d %u", + acg.cg_old_ncyl, + sblock.fs_old_cpg); + DBG_PRINT0("\n"); acg.cg_ndblk = dmax - cbase; sblock.fs_dsize += acg.cg_ndblk-aocg.cg_ndblk; if (sblock.fs_contigsumsize > 0) { @@ -801,9 +802,6 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) acg.cg_cs.cs_nffree-=sblock.fs_frag; k=rounddown(osblock.fs_size-cbase, sblock.fs_frag); - cg_blktot(&acg)[cbtocylno(&sblock, k)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, k)) - [cbtorpos(&sblock, k)]++; updclst((osblock.fs_size-cbase)/sblock.fs_frag); } else { /* @@ -861,9 +859,6 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) setblock(&sblock, cg_blksfree(&acg), j); updclst(j); acg.cg_cs.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, i)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, i)) - [cbtorpos(&sblock, i)]++; } /* @@ -930,7 +925,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) struct csum *cs; int ocscg, ncscg; int blocks; - daddr_t cbase, dupper, odupper, d, f, g; + ufs2_daddr_t cbase, dupper, odupper, d, f, g; int ind; int cylno, inc; struct gfs_bpp *bp; @@ -1062,11 +1057,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) acg.cg_cs.cs_nbfree++; sblock.fs_cstotal.cs_nffree-=sblock.fs_frag; sblock.fs_cstotal.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, - d%sblock.fs_fpg)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, - d%sblock.fs_fpg))[cbtorpos(&sblock, - d%sblock.fs_fpg)]++; if(sblock.fs_contigsumsize > 0) { setbit(cg_clustersfree(&acg), (d%sblock.fs_fpg)/sblock.fs_frag); @@ -1098,10 +1088,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) (d%sblock.fs_fpg)/sblock.fs_frag); acg.cg_cs.cs_nbfree++; sblock.fs_cstotal.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, - d%sblock.fs_fpg))[cbtorpos(&sblock, - d%sblock.fs_fpg)]++; if(sblock.fs_contigsumsize > 0) { setbit(cg_clustersfree(&acg), (d%sblock.fs_fpg)/sblock.fs_frag); @@ -1174,10 +1160,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) (d%sblock.fs_fpg)/sblock.fs_frag); acg.cg_cs.cs_nbfree--; sblock.fs_cstotal.cs_nbfree--; - cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, - d%sblock.fs_fpg))[cbtorpos(&sblock, - d%sblock.fs_fpg)]--; if(sblock.fs_contigsumsize > 0) { clrbit(cg_clustersfree(&acg), (d%sblock.fs_fpg)/sblock.fs_frag); @@ -1200,10 +1182,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) acg.cg_cs.cs_nffree+=sblock.fs_frag; sblock.fs_cstotal.cs_nbfree--; sblock.fs_cstotal.cs_nffree+=sblock.fs_frag; - cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, - d%sblock.fs_fpg))[cbtorpos(&sblock, - d%sblock.fs_fpg)]--; if(sblock.fs_contigsumsize > 0) { clrbit(cg_clustersfree(&acg), (d%sblock.fs_fpg)/sblock.fs_frag); @@ -1323,9 +1301,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) clrblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag); acg.cg_cs.cs_nbfree--; sblock.fs_cstotal.cs_nbfree--; - cg_blktot(&acg)[cbtocylno(&sblock, d)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]--; if(sblock.fs_contigsumsize > 0) { clrbit(cg_clustersfree(&acg), d/sblock.fs_frag); for(lcs=0, l=(d/sblock.fs_frag)+1; @@ -1360,9 +1335,6 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) sblock.fs_cstotal.cs_nbfree--; acg.cg_cs.cs_nffree+=sblock.fs_frag; sblock.fs_cstotal.cs_nffree+=sblock.fs_frag; - cg_blktot(&acg)[cbtocylno(&sblock, d)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]--; if(sblock.fs_contigsumsize > 0) { clrbit(cg_clustersfree(&acg), d/sblock.fs_frag); for(lcs=0, l=(d/sblock.fs_frag)+1; @@ -1559,7 +1531,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * Here we read some block(s) from disk. */ static void -rdfs(daddr_t bno, size_t size, void *bf, int fsi) +rdfs(ufs2_daddr_t bno, size_t size, void *bf, int fsi) { DBG_FUNC("rdfs") ssize_t n; @@ -1583,7 +1555,7 @@ rdfs(daddr_t bno, size_t size, void *bf, int fsi) * Here we write some block(s) to disk. */ static void -wtfs(daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag) +wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag) { DBG_FUNC("wtfs") ssize_t n; @@ -1612,11 +1584,11 @@ wtfs(daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag) * that acg contains the current cylinder group. As we may take a block from * somewhere in the filesystem we have to handle cluster summary here. */ -static daddr_t +static ufs2_daddr_t alloc(void) { DBG_FUNC("alloc") - daddr_t d, blkno; + ufs2_daddr_t d, blkno; int lcs1, lcs2; int l; int csmin, csmax; @@ -1735,8 +1707,6 @@ alloc(void) */ acg.cg_cs.cs_nbfree--; sblock.fs_cstotal.cs_nbfree--; - cg_blktot(&acg)[cbtocylno(&sblock, d)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; DBG_LEAVE; return (d); @@ -1857,32 +1827,29 @@ setblock(struct fs *fs, unsigned char *cp, int h) * not read the same block again and again if we iterate linearly over all * inodes. */ -static struct dinode * +static union dinode * ginode(ino_t inumber, int fsi, int cg) { DBG_FUNC("ginode") - ufs_daddr_t iblk; - static ino_t startinum=0; /* first inode in cached block */ - struct dinode *pi; + static ino_t startinum = 0; /* first inode in cached block */ DBG_ENTER; - pi=(struct dinode *)(void *)ablk; - inumber+=(cg * sblock.fs_ipg); - if (startinum == 0 || inumber < startinum || - inumber >= startinum + INOPB(&sblock)) { - /* - * The block needed is not cached, so we have to read it from - * disk now. - */ - iblk = ino_to_fsba(&sblock, inumber); - in_src=fsbtodb(&sblock, iblk); - rdfs(in_src, (size_t)sblock.fs_bsize, (void *)&ablk, fsi); + inumber += (cg * sblock.fs_ipg); + if (inumber < ROOTINO || inumber > maxino) + errx(8, "bad inode number %d to ginode", inumber); + if (startinum == 0 || + inumber < startinum || inumber >= startinum + INOPB(&sblock)) { + inoblk = fsbtodb(&sblock, ino_to_fsba(&sblock, inumber)); + rdfs(inoblk, (size_t)sblock.fs_bsize, inobuf, fsi); startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); } - DBG_LEAVE; - return (&(pi[inumber % INOPB(&sblock)])); + if (sblock.fs_magic == FS_UFS1_MAGIC) + return ((union dinode *) + &((struct ufs1_dinode *)inobuf)[inumber % INOPB(&sblock)]); + return ((union dinode *) + &((struct ufs2_dinode *)inobuf)[inumber % INOPB(&sblock)]); } /* ****************************************************** charsperline ***** */ @@ -1952,7 +1919,7 @@ main(int argc, char **argv) struct stat st; struct disklabel *lp; struct partition *pp; - int fsi,fso; + int i,fsi,fso; char reply[5]; #ifdef FSMAXSNAP int j; @@ -2075,12 +2042,22 @@ main(int argc, char **argv) /* * Read the current superblock, and take a backup. */ - rdfs((daddr_t)(SBOFF/DEV_BSIZE), (size_t)SBSIZE, (void *)&(osblock), - fsi); - if (osblock.fs_magic != FS_MAGIC) { + for (i = 0; sblock_try[i] != -1; i++) { + sblockloc = sblock_try[i] / DEV_BSIZE; + rdfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&(osblock), fsi); + if ((osblock.fs_magic == FS_UFS1_MAGIC || + (osblock.fs_magic == FS_UFS2_MAGIC && + osblock.fs_sblockloc == + numfrags(&osblock, sblock_try[i]))) && + osblock.fs_bsize <= MAXBSIZE && + osblock.fs_bsize >= sizeof(struct fs)) + break; + } + if (sblock_try[i] == -1) { errx(1, "superblock not recognized"); } memcpy((void *)&fsun1, (void *)&fsun2, sizeof(fsun2)); + maxino = sblock.fs_ncg * sblock.fs_ipg; DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */ DBG_DUMP_FS(&sblock, @@ -2144,8 +2121,8 @@ main(int argc, char **argv) * later on realize we have to abort our operation, on that block * there should be no data, so we can't destroy something yet. */ - wtfs((daddr_t)pp->p_size-1, (size_t)DEV_BSIZE, (void *)&sblock, fso, - Nflag); + wtfs((ufs2_daddr_t)pp->p_size-1, (size_t)DEV_BSIZE, (void *)&sblock, + fso, Nflag); /* * Now calculate new superblock values and check for reasonable @@ -2158,40 +2135,30 @@ main(int argc, char **argv) */ /* - * Update the number of cylinders in the filesystem. - */ - sblock.fs_ncyl = sblock.fs_size * NSPF(&sblock) / sblock.fs_spc; - if (sblock.fs_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { - sblock.fs_ncyl++; - } - - /* - * Update the number of cylinder groups in the filesystem. + * Update the number of cylinders and cylinder groups in the filesystem. */ - sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; - if (sblock.fs_ncyl % sblock.fs_cpg) { - sblock.fs_ncg++; - } - - if ((sblock.fs_size - (sblock.fs_ncg-1) * sblock.fs_fpg) < - sblock.fs_fpg && cgdmin(&sblock, (sblock.fs_ncg-1))- - cgbase(&sblock, (sblock.fs_ncg-1)) > (sblock.fs_size - - (sblock.fs_ncg-1) * sblock.fs_fpg )) { + if (sblock.fs_magic == FS_UFS1_MAGIC) { + sblock.fs_old_ncyl = + sblock.fs_size * sblock.fs_old_nspf / sblock.fs_old_spc; + if (sblock.fs_size * sblock.fs_old_nspf > + sblock.fs_old_ncyl * sblock.fs_old_spc) + sblock.fs_old_ncyl++; + } + sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg); + maxino = sblock.fs_ncg * sblock.fs_ipg; + + if (sblock.fs_size % sblock.fs_fpg != 0 && + sblock.fs_size % sblock.fs_fpg < cgdmin(&sblock, sblock.fs_ncg)) { /* * The space in the new last cylinder group is too small, * so revert back. */ sblock.fs_ncg--; -#if 1 /* this is a bit more safe */ - sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg; -#else - sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; -#endif - sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; - printf( "Warning: %d sector(s) cannot be allocated.\n", - (sblock.fs_size-(sblock.fs_ncg)*sblock.fs_fpg) * - NSPF(&sblock)); - sblock.fs_size = sblock.fs_ncyl * sblock.fs_spc / NSPF(&sblock); + if (sblock.fs_magic == FS_UFS1_MAGIC) + sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg; + printf("Warning: %d sector(s) cannot be allocated.\n", + fsbtodb(&sblock, sblock.fs_size % sblock.fs_fpg)); + sblock.fs_size = sblock.fs_ncg * sblock.fs_fpg; } /* @@ -2217,7 +2184,7 @@ main(int argc, char **argv) */ pp->p_fsize = sblock.fs_fsize; pp->p_frag = sblock.fs_frag; - pp->p_cpg = sblock.fs_cpg; + pp->p_cpg = sblock.fs_fpg; return_disklabel(fso, lp, Nflag); DBG_PRINT0("label rewritten\n"); @@ -2370,32 +2337,33 @@ updrefs(int cg, ino_t in, struct gfs_bpp *bp, int fsi, int fso, unsigned int Nflag) { DBG_FUNC("updrefs") - unsigned int ictr, ind2ctr, ind3ctr; - ufs_daddr_t *iptr, *ind2ptr, *ind3ptr; - struct dinode *ino; - int remaining_blocks; + ufs_lbn_t len, lbn, numblks; + ufs2_daddr_t iptr, blksperindir; + union dinode *ino; + int i, mode, remaining_blocks, inodeupdated; DBG_ENTER; /* - * XXX We should skip unused inodes even from beeing read from disk + * XXX We should skip unused inodes even from being read from disk * here by using the bitmap. */ - ino=ginode(in, fsi, cg); - if(!((ino->di_mode & IFMT)==IFDIR || (ino->di_mode & IFMT)==IFREG || - (ino->di_mode & IFMT)==IFLNK)) { + ino = ginode(in, fsi, cg); + mode = DIP(ino, di_mode) & IFMT; + if (mode != IFDIR && mode != IFREG && mode != IFLNK) { DBG_LEAVE; return; /* only check DIR, FILE, LINK */ } - if(((ino->di_mode & IFMT)==IFLNK) && (ino->di_size<MAXSYMLINKLEN)) { + if (mode == IFLNK && DIP(ino, di_size) < sblock.fs_maxsymlinklen) { DBG_LEAVE; return; /* skip short symlinks */ } - if(!ino->di_size) { + numblks = howmany(DIP(ino, di_size), sblock.fs_bsize); + if (numblks == 0) { DBG_LEAVE; return; /* skip empty file */ } - if(!ino->di_blocks) { + if (DIP(ino, di_blocks) == 0) { DBG_LEAVE; return; /* skip empty swiss cheesy file or old fastlink */ } @@ -2404,134 +2372,87 @@ updrefs(int cg, ino_t in, struct gfs_bpp *bp, int fsi, int fso, unsigned int cg); /* - * Start checking all direct blocks. + * Check all the blocks. */ - remaining_blocks=howmany(ino->di_size, sblock.fs_bsize); - for(ictr=0; ictr < MIN(NDADDR, (unsigned int)remaining_blocks); - ictr++) { - iptr=&(ino->di_db[ictr]); - if(*iptr) { - cond_bl_upd(iptr, bp, GFS_PS_INODE, fso, Nflag); + inodeupdated = 0; + len = numblks < NDADDR ? numblks : NDADDR; + for (i = 0; i < len; i++) { + iptr = DIP(ino, di_db[i]); + if (iptr == 0) + continue; + if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) { + DIP(ino, di_db[i]) = iptr; + inodeupdated++; } } DBG_PRINT0("~~scg direct blocks checked\n"); - remaining_blocks-=NDADDR; - if(remaining_blocks<0) { - DBG_LEAVE; - return; - } - if(ino->di_ib[0]) { - /* - * Start checking first indirect block - */ - cond_bl_upd(&(ino->di_ib[0]), bp, GFS_PS_INODE, fso, Nflag); - i1_src=fsbtodb(&sblock, ino->di_ib[0]); - rdfs(i1_src, (size_t)sblock.fs_bsize, (void *)&i1blk, fsi); - for(ictr=0; ictr < MIN(howmany(sblock.fs_bsize, - sizeof(ufs_daddr_t)), (unsigned int)remaining_blocks); - ictr++) { - iptr=&((ufs_daddr_t *)(void *)&i1blk)[ictr]; - if(*iptr) { - cond_bl_upd(iptr, bp, GFS_PS_IND_BLK_LVL1, - fso, Nflag); - } + blksperindir = 1; + len = numblks - NDADDR; + lbn = NDADDR; + for (i = 0; len > 0 && i < NIADDR; i++) { + iptr = DIP(ino, di_ib[i]); + if (iptr == 0) + continue; + if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) { + DIP(ino, di_ib[i]) = iptr; + inodeupdated++; } + indirchk(blksperindir, lbn, iptr, numblks, bp, fsi, fso, Nflag); + blksperindir *= NINDIR(&sblock); + lbn += blksperindir; + len -= blksperindir; + DBG_PRINT1("scg indirect_%d blocks checked\n", i + 1); } - DBG_PRINT0("scg indirect_1 blocks checked\n"); + if (inodeupdated) + wtfs(inoblk, sblock.fs_bsize, inobuf, fso, Nflag); - remaining_blocks-= howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)); - if(remaining_blocks<0) { - DBG_LEAVE; - return; - } - if(ino->di_ib[1]) { - /* - * Start checking second indirect block - */ - cond_bl_upd(&(ino->di_ib[1]), bp, GFS_PS_INODE, fso, Nflag); - i2_src=fsbtodb(&sblock, ino->di_ib[1]); - rdfs(i2_src, (size_t)sblock.fs_bsize, (void *)&i2blk, fsi); - for(ind2ctr=0; ind2ctr < howmany(sblock.fs_bsize, - sizeof(ufs_daddr_t)); ind2ctr++) { - ind2ptr=&((ufs_daddr_t *)(void *)&i2blk)[ind2ctr]; - if(!*ind2ptr) { - continue; - } - cond_bl_upd(ind2ptr, bp, GFS_PS_IND_BLK_LVL2, fso, - Nflag); - i1_src=fsbtodb(&sblock, *ind2ptr); - rdfs(i1_src, (size_t)sblock.fs_bsize, (void *)&i1blk, - fsi); - for(ictr=0; ictr<MIN(howmany((unsigned int) - sblock.fs_bsize, sizeof(ufs_daddr_t)), - (unsigned int)remaining_blocks); ictr++) { - iptr=&((ufs_daddr_t *)(void *)&i1blk)[ictr]; - if(*iptr) { - cond_bl_upd(iptr, bp, - GFS_PS_IND_BLK_LVL1, fso, Nflag); - } - } - } - } - DBG_PRINT0("scg indirect_2 blocks checked\n"); + DBG_LEAVE; + return; +} -#define SQUARE(a) ((a)*(a)) - remaining_blocks-=SQUARE(howmany(sblock.fs_bsize, sizeof(ufs_daddr_t))); -#undef SQUARE - if(remaining_blocks<0) { - DBG_LEAVE; - return; - } - - if(ino->di_ib[2]) { - /* - * Start checking third indirect block - */ - cond_bl_upd(&(ino->di_ib[2]), bp, GFS_PS_INODE, fso, Nflag); - i3_src=fsbtodb(&sblock, ino->di_ib[2]); - rdfs(i3_src, (size_t)sblock.fs_bsize, (void *)&i3blk, fsi); - for(ind3ctr=0; ind3ctr < howmany(sblock.fs_bsize, - sizeof(ufs_daddr_t)); ind3ctr ++) { - ind3ptr=&((ufs_daddr_t *)(void *)&i3blk)[ind3ctr]; - if(!*ind3ptr) { - continue; - } - cond_bl_upd(ind3ptr, bp, GFS_PS_IND_BLK_LVL3, fso, - Nflag); - i2_src=fsbtodb(&sblock, *ind3ptr); - rdfs(i2_src, (size_t)sblock.fs_bsize, (void *)&i2blk, - fsi); - for(ind2ctr=0; ind2ctr < howmany(sblock.fs_bsize, - sizeof(ufs_daddr_t)); ind2ctr ++) { - ind2ptr=&((ufs_daddr_t *)(void *)&i2blk) - [ind2ctr]; - if(!*ind2ptr) { - continue; - } - cond_bl_upd(ind2ptr, bp, GFS_PS_IND_BLK_LVL2, - fso, Nflag); - i1_src=fsbtodb(&sblock, *ind2ptr); - rdfs(i1_src, (size_t)sblock.fs_bsize, - (void *)&i1blk, fsi); - for(ictr=0; ictr < MIN(howmany(sblock.fs_bsize, - sizeof(ufs_daddr_t)), - (unsigned int)remaining_blocks); ictr++) { - iptr=&((ufs_daddr_t *)(void *)&i1blk) - [ictr]; - if(*iptr) { - cond_bl_upd(iptr, bp, - GFS_PS_IND_BLK_LVL1, fso, - Nflag); - } - } - } +/* + * Recursively check all the indirect blocks. + */ +static void +indirchk(ufs_lbn_t blksperindir, ufs_lbn_t lbn, ufs2_daddr_t blkno, + ufs_lbn_t lastlbn, struct gfs_bpp *bp, int fsi, int fso, unsigned int Nflag) +{ + DBG_FUNC("indirchk") + void *ibuf; + off_t offset; + int i, last; + ufs2_daddr_t iptr; + + DBG_ENTER; + + /* read in the indirect block. */ + ibuf = malloc(sblock.fs_bsize); + if (!ibuf) + errx(1, "malloc failed"); + rdfs(fsbtodb(&sblock, blkno), (size_t)sblock.fs_bsize, ibuf, fsi); + last = howmany(lastlbn - lbn, blksperindir) < NINDIR(&sblock) ? + howmany(lastlbn - lbn, blksperindir) : NINDIR(&sblock); + for (i = 0; i < last; i++) { + if (sblock.fs_magic == FS_UFS1_MAGIC) + iptr = ((ufs1_daddr_t *)ibuf)[i]; + else + iptr = ((ufs2_daddr_t *)ibuf)[i]; + if (iptr == 0) + continue; + if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) { + if (sblock.fs_magic == FS_UFS1_MAGIC) + ((ufs1_daddr_t *)ibuf)[i] = iptr; + else + ((ufs2_daddr_t *)ibuf)[i] = iptr; } + if (blksperindir == 1) + continue; + indirchk(blksperindir / NINDIR(&sblock), lbn + blksperindir * i, + iptr, lastlbn, bp, fsi, fso, Nflag); } - - DBG_PRINT0("scg indirect_3 blocks checked\n"); + free(ibuf); DBG_LEAVE; return; } - diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c index 16e7de7..03c76f6 100644 --- a/sbin/newfs/mkfs.c +++ b/sbin/newfs/mkfs.c @@ -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, 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -63,23 +75,12 @@ static const char rcsid[] = /* * make filesystem for cylinder-group style filesystems */ - -/* - * We limit the size of the inode map to be no more than a - * third of the cylinder group space, since we must leave at - * least an equal amount of space for the block map. - * - * N.B.: MAXIPG must be a multiple of INOPB(fs). - */ -#define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) - #define UMASK 0755 -#define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) #define POWEROF2(num) (((num) & ((num) - 1)) == 0) static union { struct fs fs; - char pad[SBSIZE]; + char pad[SBLOCKSIZE]; } fsun; #define sblock fsun.fs static struct csum *fscs; @@ -90,32 +91,36 @@ static union { } cgun; #define acg cgun.cg -static struct dinode zino[MAXBSIZE / sizeof(struct dinode)]; +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) static int randinit; -static daddr_t alloc(int size, int mode); -static long calcipg(long lcpg, long bpcg, off_t *usedbp); +static caddr_t iobuf; +static long iobufsize; +static ufs2_daddr_t alloc(int size, int mode); static int charsperline(void); static void clrblock(struct fs *, unsigned char *, int); static void fsinit(time_t); static int ilog2(int); static void initcg(int, time_t); static int isblock(struct fs *, unsigned char *, int); -static void iput(struct dinode *, ino_t); +static void iput(union dinode *, ino_t); static int makedir(struct direct *, int); -static void rdfs(daddr_t, int, char *); +static void rdfs(ufs2_daddr_t, int, char *); static void setblock(struct fs *, unsigned char *, int); -static void wtfs(daddr_t, int, char *); +static void wtfs(ufs2_daddr_t, int, char *); static void wtfsflush(void); void mkfs(struct partition *pp, char *fsys) { - long i, mincpc, mincpg, inospercg; - long cylno, j, lwarn = 0; - long used, mincpgcnt, bpcg; - off_t usedb; - long mapcramped, inodecramped; + int fragsperinode, optimalfpg, origdensity, minfpg, lastminfpg; + long i, j, cylno, csfrags; time_t utime; quad_t sizepb; int width; @@ -129,26 +134,34 @@ mkfs(struct partition *pp, char *fsys) randinit = 1; srandomdev(); } - sblock.fs_inodefmt = FS_44INODEFMT; - sblock.fs_maxsymlinklen = MAXSYMLINKLEN; + /* + * allocate space for superblock, cylinder group map, and + * two sets of inode blocks. + */ + if (bsize < SBLOCKSIZE) + iobufsize = SBLOCKSIZE + 3 * bsize; + else + iobufsize = 4 * bsize; + if ((iobuf = malloc(iobufsize)) == 0) { + printf("Cannot allocate I/O buffer\n"); + exit(38); + } + bzero(iobuf, iobufsize); + sblock.fs_flags = 0; if (Uflag) sblock.fs_flags |= FS_DOSOFTDEP; /* * Validate the given filesystem size. * Verify that its last block can actually be accessed. + * Convert to filesystem fragment sized units. */ - if (fssize <= 0) - printf("preposterous size %d\n", fssize), exit(13); + if (fssize <= 0) { + printf("preposterous size %qd\n", fssize); + exit(13); + } wtfs(fssize - (realsectorsize / DEV_BSIZE), realsectorsize, (char *)&sblock); /* - * collect and verify the sector and track info - */ - sblock.fs_nsect = secpercyl; - sblock.fs_ntrak = 1; - if (sblock.fs_nsect <= 0) - printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15); - /* * collect and verify the filesystem density info */ sblock.fs_avgfilesize = avgfilesize; @@ -195,6 +208,22 @@ mkfs(struct partition *pp, char *fsys) sblock.fs_fsize, MAXFRAG, sblock.fs_bsize / MAXFRAG); sblock.fs_fsize = sblock.fs_bsize / MAXFRAG; } + if (maxbsize < bsize || !POWEROF2(maxbsize)) { + sblock.fs_maxbsize = sblock.fs_bsize; + printf("Extent size set to %d\n", sblock.fs_maxbsize); + } else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) { + sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize; + printf("Extent size reduced to %d\n", sblock.fs_maxbsize); + } else { + sblock.fs_maxbsize = maxbsize; + } + sblock.fs_maxcontig = maxcontig; + if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) { + sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize; + printf("Maxcontig raised to %d\n", sblock.fs_maxbsize); + } + if (sblock.fs_maxcontig > 1) + sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG); sblock.fs_bmask = ~(sblock.fs_bsize - 1); sblock.fs_fmask = ~(sblock.fs_fsize - 1); sblock.fs_qbmask = ~sblock.fs_bmask; @@ -208,257 +237,138 @@ mkfs(struct partition *pp, char *fsys) sblock.fs_bsize / MAXFRAG); exit(21); } - sblock.fs_nrpos = 1; - sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); - sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode); - sblock.fs_nspf = sblock.fs_fsize / sectorsize; - sblock.fs_fsbtodb = ilog2(NSPF(&sblock)); + sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize); + sblock.fs_size = fssize = dbtofsb(&sblock, fssize); + if (Oflag == 1) { + sblock.fs_magic = FS_UFS1_MAGIC; + sblock.fs_sblockloc = numfrags(&sblock, SBLOCK_UFS1); + sblock.fs_nindir = sblock.fs_bsize / sizeof(ufs1_daddr_t); + sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode); + sblock.fs_maxsymlinklen = ((NDADDR + NIADDR) * + sizeof(ufs1_daddr_t)); + sblock.fs_old_inodefmt = FS_44INODEFMT; + sblock.fs_old_cgoffset = 0; + sblock.fs_old_cgmask = 0xffffffff; + sblock.fs_old_size = sblock.fs_size; + sblock.fs_old_rotdelay = 0; + sblock.fs_old_rps = 60; + sblock.fs_old_nspf = sblock.fs_fsize / sectorsize; + sblock.fs_old_cpg = 1; + sblock.fs_old_interleave = 1; + sblock.fs_old_trackskew = 0; + sblock.fs_old_cpc = 0; + sblock.fs_old_postblformat = 1; + sblock.fs_old_nrpos = 1; + } else { + sblock.fs_magic = FS_UFS2_MAGIC; + sblock.fs_sblockloc = numfrags(&sblock, SBLOCK_UFS2); + sblock.fs_nindir = sblock.fs_bsize / sizeof(ufs2_daddr_t); + sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode); + sblock.fs_maxsymlinklen = ((NDADDR + NIADDR) * + sizeof(ufs2_daddr_t)); + } sblock.fs_sblkno = - roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag); - sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + - roundup(howmany(SBSIZE, sblock.fs_fsize), sblock.fs_frag)); + roundup(howmany(lfragtosize(&sblock, sblock.fs_sblockloc) + + SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag); + sblock.fs_cblkno = sblock.fs_sblkno + + roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag); sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; - sblock.fs_cgoffset = - roundup(howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); - sblock.fs_cgmask = 0xffffffff; sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) { sizepb *= NINDIR(&sblock); sblock.fs_maxfilesize += sizepb; } /* - * Validate specified/determined secpercyl - * and calculate minimum cylinders per group. - */ - sblock.fs_spc = secpercyl; - for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; - sblock.fs_cpc > 1 && (i & 1) == 0; - sblock.fs_cpc >>= 1, i >>= 1) - /* void */; - mincpc = sblock.fs_cpc; - bpcg = sblock.fs_spc * sectorsize; - inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock)); - if (inospercg > MAXIPG(&sblock)) - inospercg = MAXIPG(&sblock); - used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); - mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used, - sblock.fs_spc); - mincpg = roundup(mincpgcnt, mincpc); - /* - * Ensure that cylinder group with mincpg has enough space - * for block maps. + * Calculate the number of blocks to put into each cylinder group. + * + * This algorithm selects the number of blocks per cylinder + * group. The first goal is to have at least enough data blocks + * in each cylinder group to meet the density requirement. Once + * this goal is achieved we try to expand to have at least + * MINCYLGRPS cylinder groups. Once this goal is achieved, we + * pack as many blocks into each cylinder group map as will fit. + * + * We start by calculating the smallest number of blocks that we + * can put into each cylinder group. If this is too big, we reduce + * the density until it fits. */ - sblock.fs_cpg = mincpg; - sblock.fs_ipg = inospercg; - if (maxcontig > 1) - sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG); - mapcramped = 0; - while (CGSIZE(&sblock) > sblock.fs_bsize) { - mapcramped = 1; - if (sblock.fs_bsize < MAXBSIZE) { - sblock.fs_bsize <<= 1; - if ((i & 1) == 0) - i >>= 1; - else { - sblock.fs_cpc <<= 1; - mincpc <<= 1; - mincpg = roundup(mincpgcnt, mincpc); - sblock.fs_cpg = mincpg; - } - sblock.fs_frag <<= 1; - sblock.fs_fragshift += 1; - if (sblock.fs_frag <= MAXFRAG) - continue; - } - if (sblock.fs_fsize == sblock.fs_bsize) { - printf("There is no block size that"); - printf(" can support this disk\n"); - exit(22); - } - sblock.fs_frag >>= 1; - sblock.fs_fragshift -= 1; - sblock.fs_fsize <<= 1; - sblock.fs_nspf <<= 1; + origdensity = density; + for (;;) { + fragsperinode = numfrags(&sblock, density); + minfpg = fragsperinode * INOPB(&sblock); + if (minfpg > sblock.fs_size) + minfpg = sblock.fs_size; + sblock.fs_ipg = INOPB(&sblock); + sblock.fs_fpg = roundup(sblock.fs_iblkno + + sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag); + if (sblock.fs_fpg < minfpg) + sblock.fs_fpg = minfpg; + sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), + INOPB(&sblock)); + sblock.fs_fpg = roundup(sblock.fs_iblkno + + sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag); + if (sblock.fs_fpg < minfpg) + sblock.fs_fpg = minfpg; + sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), + INOPB(&sblock)); + if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize) + break; + density -= sblock.fs_fsize; } + if (density != origdensity) + printf("density reduced from %d to %d\n", origdensity, density); /* - * Ensure that cylinder group with mincpg has enough space for inodes. + * Start packing more blocks into the cylinder group until + * it cannot grow any larger, the number of cylinder groups + * drops below MINCYLGRPS, or we reach the size requested. */ - inodecramped = 0; - inospercg = calcipg(mincpg, bpcg, &usedb); - sblock.fs_ipg = inospercg; - while (inospercg > MAXIPG(&sblock)) { - inodecramped = 1; - if (mincpc == 1 || sblock.fs_frag == 1 || - sblock.fs_bsize == MINBSIZE) + for ( ; sblock.fs_fpg < maxblkspercg; sblock.fs_fpg += sblock.fs_frag) { + sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), + INOPB(&sblock)); + if (sblock.fs_size / sblock.fs_fpg < MINCYLGRPS) break; - printf("With a block size of %d %s %d\n", sblock.fs_bsize, - "minimum bytes per inode is", - (int)((mincpg * (off_t)bpcg - usedb) / - MAXIPG(&sblock) + 1)); - sblock.fs_bsize >>= 1; - sblock.fs_frag >>= 1; - sblock.fs_fragshift -= 1; - mincpc >>= 1; - sblock.fs_cpg = roundup(mincpgcnt, mincpc); - if (CGSIZE(&sblock) > sblock.fs_bsize) { - sblock.fs_bsize <<= 1; + if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize) + continue; + if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize) break; - } - mincpg = sblock.fs_cpg; - inospercg = calcipg(mincpg, bpcg, &usedb); - sblock.fs_ipg = inospercg; - } - if (inodecramped) { - if (inospercg > MAXIPG(&sblock)) { - printf("Minimum bytes per inode is %d\n", - (int)((mincpg * (off_t)bpcg - usedb) / - MAXIPG(&sblock) + 1)); - } else if (!mapcramped) { - printf("With %d bytes per inode, ", density); - printf("minimum cylinders per group is %ld\n", mincpg); - } - } - if (mapcramped) { - printf("With %d sectors per cylinder, ", sblock.fs_spc); - printf("minimum cylinders per group is %ld\n", mincpg); - } - if (inodecramped || mapcramped) { - if (sblock.fs_bsize != bsize) - printf("%s to be changed from %d to %d\n", - "This requires the block size", - bsize, sblock.fs_bsize); - if (sblock.fs_fsize != fsize) - printf("\t%s to be changed from %d to %d\n", - "and the fragment size", fsize, sblock.fs_fsize); - exit(23); - } - /* - * Calculate the number of cylinders per group - */ - sblock.fs_cpg = cpg; - if (sblock.fs_cpg % mincpc != 0) { - printf("%s groups must have a multiple of %ld cylinders\n", - cpgflg ? "Cylinder" : "Warning: cylinder", mincpc); - sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); - if (!cpgflg) - cpg = sblock.fs_cpg; - } - /* - * Must ensure there is enough space for inodes. - */ - sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); - while (sblock.fs_ipg > MAXIPG(&sblock)) { - inodecramped = 1; - sblock.fs_cpg -= mincpc; - sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); + sblock.fs_fpg -= sblock.fs_frag; + sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), + INOPB(&sblock)); + break; } /* - * Must ensure there is enough space to hold block map. + * Check to be sure that the last cylinder group has enough blocks + * to be viable. If it is too small, reduce the number of blocks + * per cylinder group which will have the effect of moving more + * blocks into the last cylinder group. */ - while (CGSIZE(&sblock) > sblock.fs_bsize) { - mapcramped = 1; - sblock.fs_cpg -= mincpc; - sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); - } - sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); - if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) { - printf("panic (fs_cpg * fs_spc) %% NSPF != 0"); - exit(24); - } - if (sblock.fs_cpg < mincpg) { - printf("cylinder groups must have at least %ld cylinders\n", - mincpg); - exit(25); - } else if (cpgflg && sblock.fs_cpg != cpg) { - if (!mapcramped && !inodecramped) - exit(26); - if (mapcramped && inodecramped) - printf("Block size and bytes per inode restrict"); - else if (mapcramped) - printf("Block size restricts"); - else - printf("Bytes per inode restrict"); - printf(" cylinders per group to %d.\n", sblock.fs_cpg); - if (cpgflg) - exit(27); + optimalfpg = sblock.fs_fpg; + for (;;) { + sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg); + lastminfpg = roundup(sblock.fs_iblkno + + sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag); + if (sblock.fs_size < lastminfpg) { + printf("Filesystem size %qd < minimum size of %d\n", + sblock.fs_size, lastminfpg); + exit(28); + } + if (sblock.fs_size % sblock.fs_fpg >= lastminfpg || + sblock.fs_size % sblock.fs_fpg == 0) + break; + sblock.fs_fpg -= sblock.fs_frag; + sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode), + INOPB(&sblock)); } + if (optimalfpg != sblock.fs_fpg) + printf("Reduced frags per cylinder group from %d to %d %s\n", + optimalfpg, sblock.fs_fpg, "to enlarge last cyl group"); sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); - /* - * Now have size for filesystem and nsect and ntrak. - * Determine number of cylinders and blocks in the filesystem. - */ - sblock.fs_size = fssize = dbtofsb(&sblock, fssize); - sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; - if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { - sblock.fs_ncyl++; - lwarn = 1; - } - if (sblock.fs_ncyl < 1) { - printf("filesystems must have at least one cylinder\n"); - exit(28); - } - /* - * Determine feasability/values of rotational layout tables. - * - * The size of the rotational layout tables is limited by the - * size of the superblock, SBSIZE. The amount of space available - * for tables is calculated as (SBSIZE - sizeof (struct fs)). - * The size of these tables is inversely proportional to the block - * size of the filesystem. The size increases if sectors per track - * are not powers of two, because more cylinders must be described - * by the tables before the rotational pattern repeats (fs_cpc). - */ - sblock.fs_interleave = 1; - sblock.fs_trackskew = 0; - sblock.fs_npsect = secpercyl; - sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; - sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); - if (sblock.fs_sbsize > SBSIZE) - sblock.fs_sbsize = SBSIZE; - sblock.fs_cpc = 0; - /* - * Compute/validate number of cylinder groups. - */ - sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; - if (sblock.fs_ncyl % sblock.fs_cpg) - sblock.fs_ncg++; sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); - i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); - if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { - printf("inode blocks/cyl group (%ld) >= data blocks (%ld)\n", - cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, - (long)(sblock.fs_fpg / sblock.fs_frag)); - printf("number of cylinders per cylinder group (%d) %s.\n", - sblock.fs_cpg, "must be increased"); - exit(29); - } - j = sblock.fs_ncg - 1; - if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && - cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { - if (j == 0) { - printf("Filesystem must have at least %d sectors\n", - NSPF(&sblock) * - (cgdmin(&sblock, 0) + 3 * sblock.fs_frag)); - exit(30); - } - printf( -"Warning: inode blocks/cyl group (%ld) >= data blocks (%ld) in last\n", - (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, - i / sblock.fs_frag); - printf( -" cylinder group. This implies %ld sector(s) cannot be allocated.\n", - i * NSPF(&sblock)); - sblock.fs_ncg--; - sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; - sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / - NSPF(&sblock); - lwarn = 0; - } - if (lwarn) { - printf("Warning: %d sector(s) in last cylinder unallocated\n", - sblock.fs_spc - - (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) * - sblock.fs_spc)); + if (Oflag == 1) { + sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf; + sblock.fs_old_nsect = sblock.fs_old_spc; + sblock.fs_old_npsect = sblock.fs_old_spc; + sblock.fs_old_ncyl = sblock.fs_ncg; } /* * fill in remaining fields of the super block @@ -466,49 +376,59 @@ mkfs(struct partition *pp, char *fsys) sblock.fs_csaddr = cgdmin(&sblock, 0); sblock.fs_cssize = fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); - /* - * The superblock fields 'fs_csmask' and 'fs_csshift' are no - * longer used. However, we still initialise them so that the - * filesystem remains compatible with old kernels. - */ - i = sblock.fs_bsize / sizeof(struct csum); - sblock.fs_csmask = ~(i - 1); - sblock.fs_csshift = ilog2(i); fscs = (struct csum *)calloc(1, sblock.fs_cssize); if (fscs == NULL) errx(31, "calloc failed"); - sblock.fs_magic = FS_MAGIC; - sblock.fs_rotdelay = 0; + sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); sblock.fs_minfree = minfree; - sblock.fs_maxcontig = maxcontig; sblock.fs_maxbpg = maxbpg; - sblock.fs_rps = 60; sblock.fs_optim = opt; sblock.fs_cgrotor = 0; - sblock.fs_cstotal.cs_ndir = 0; - sblock.fs_cstotal.cs_nbfree = 0; - sblock.fs_cstotal.cs_nifree = 0; - sblock.fs_cstotal.cs_nffree = 0; + sblock.fs_pendingblocks = 0; + sblock.fs_pendinginodes = 0; sblock.fs_fmod = 0; sblock.fs_ronly = 0; + sblock.fs_state = 0; sblock.fs_clean = 1; sblock.fs_id[0] = (long)utime; sblock.fs_id[1] = random(); + sblock.fs_fsmnt[0] = '\0'; + csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize); + sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno - + sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno); + sblock.fs_cstotal.cs_nbfree = + fragstoblks(&sblock, sblock.fs_dsize) - + howmany(csfrags, sblock.fs_frag); + sblock.fs_cstotal.cs_nffree = + fragnum(&sblock, sblock.fs_size) + + (csfrags > 0 ? sblock.fs_frag - csfrags : 0); + sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - ROOTINO; + sblock.fs_cstotal.cs_ndir = 0; + sblock.fs_dsize -= csfrags; + sblock.fs_time = utime; + if (Oflag == 1) { + sblock.fs_old_time = utime; + sblock.fs_old_dsize = sblock.fs_dsize; + sblock.fs_old_csaddr = sblock.fs_csaddr; + sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; + sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; + sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; + sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; + } /* * Dump out summary information about filesystem. */ - printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n", - fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, - "cylinders", sblock.fs_ntrak, sblock.fs_nsect); -#define B2MBFACTOR (1 / (1024.0 * 1024.0)) - printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)%s\n", - (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, - sblock.fs_ncg, sblock.fs_cpg, - (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, - sblock.fs_ipg, - sblock.fs_flags & FS_DOSOFTDEP ? " SOFTUPDATES" : ""); -#undef B2MBFACTOR +# define B2MBFACTOR (1 / (1024.0 * 1024.0)) + printf("%s: %.1fMB (%qd sectors) block size %d, fragment size %d\n", + fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, + fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize, sblock.fs_fsize); + printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n", + sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, + sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); + if (sblock.fs_flags & FS_DOSOFTDEP) + printf("\twith soft updates\n"); +# undef B2MBFACTOR /* * Now build the cylinders group blocks and * then print out indices of cylinder groups. @@ -516,9 +436,14 @@ mkfs(struct partition *pp, char *fsys) printf("super-block backups (for fsck -b #) at:\n"); i = 0; width = charsperline(); + /* + * Make a copy of the superblock into the buffer that we will be + * writing out in each cylinder group. + */ + bcopy((char *)&sblock, iobuf, SBLOCKSIZE); for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { initcg(cylno, utime); - j = snprintf(tmpbuf, sizeof(tmpbuf), " %ld%s", + j = snprintf(tmpbuf, sizeof(tmpbuf), " %qd%s", fsbtodb(&sblock, cgsblock(&sblock, cylno)), cylno < (sblock.fs_ncg-1) ? "," : ""); if (j < 0) @@ -535,23 +460,30 @@ mkfs(struct partition *pp, char *fsys) if (Nflag) exit(0); /* + * Zero out the boot area to avoid old superblocks from being + * found by mistake. Skip over the disklabel area. + */ + bzero(iobuf, sblock.fs_bsize); + for (i = 1; i < sblock.fs_sblkno; i += sblock.fs_frag) + wtfs(fsbtodb(&sblock, i), sblock.fs_bsize, iobuf); + /* * Now construct the initial filesystem, * then write out the super-block. */ fsinit(utime); - sblock.fs_time = utime; - wtfs((int)SBOFF / sectorsize, SBSIZE, (char *)&sblock); + if (Oflag == 1) { + sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; + sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; + sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; + sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; + } + wtfs(lfragtosize(&sblock, sblock.fs_sblockloc) / sectorsize, + SBLOCKSIZE, (char *)&sblock); for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize, ((char *)fscs) + i); - /* - * Write out the duplicate super blocks - */ - for (cylno = 0; cylno < sblock.fs_ncg; cylno++) - wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), - SBSIZE, (char *)&sblock); wtfsflush(); /* * Update information about this partion in pack @@ -561,7 +493,7 @@ mkfs(struct partition *pp, char *fsys) pp->p_fstype = FS_BSDFFS; pp->p_fsize = sblock.fs_fsize; pp->p_frag = sblock.fs_frag; - pp->p_cpg = sblock.fs_cpg; + pp->p_cpg = sblock.fs_fpg; } } @@ -571,9 +503,11 @@ mkfs(struct partition *pp, char *fsys) void initcg(int cylno, time_t utime) { - daddr_t cbase, d, dlower, dupper, dmax, blkno; + long i, j, d, dlower, dupper, blkno, start; + ufs2_daddr_t cbase, dmax; + struct ufs1_dinode *dp1; + struct ufs2_dinode *dp2; struct csum *cs; - long i, j; /* * Determine block bounds for cylinder group. @@ -588,56 +522,54 @@ initcg(int cylno, time_t utime) dupper = cgdmin(&sblock, cylno) - cbase; if (cylno == 0) dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); - cs = fscs + cylno; + cs = &fscs[cylno]; memset(&acg, 0, sblock.fs_cgsize); acg.cg_time = utime; acg.cg_magic = CG_MAGIC; acg.cg_cgx = cylno; - if (cylno == sblock.fs_ncg - 1) - acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; - else - acg.cg_ncyl = sblock.fs_cpg; acg.cg_niblk = sblock.fs_ipg; + acg.cg_initediblk = sblock.fs_ipg < 2 * INOPB(&sblock) ? + sblock.fs_ipg : 2 * INOPB(&sblock); acg.cg_ndblk = dmax - cbase; if (sblock.fs_contigsumsize > 0) acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; - acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); - acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t); - acg.cg_iusedoff = acg.cg_boff + - sblock.fs_cpg * sizeof(u_int16_t); - acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); - if (sblock.fs_contigsumsize <= 0) { - acg.cg_nextfreeoff = acg.cg_freeoff + - howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), - NBBY); + start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); + if (Oflag == 2) { + acg.cg_iusedoff = start; } else { - acg.cg_clustersumoff = acg.cg_freeoff + howmany - (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) - - sizeof(u_int32_t); + acg.cg_old_ncyl = sblock.fs_old_cpg; + acg.cg_old_time = acg.cg_time; + acg.cg_time = 0; + acg.cg_old_niblk = acg.cg_niblk; + acg.cg_niblk = 0; + acg.cg_initediblk = 0; + acg.cg_old_btotoff = start; + acg.cg_old_boff = acg.cg_old_btotoff + + sblock.fs_old_cpg * sizeof(int32_t); + acg.cg_iusedoff = acg.cg_old_boff + + sblock.fs_old_cpg * sizeof(u_int16_t); + } + acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); + acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, NBBY); + if (sblock.fs_contigsumsize > 0) { acg.cg_clustersumoff = - roundup(acg.cg_clustersumoff, sizeof(u_int32_t)); + roundup(acg.cg_nextfreeoff, sizeof(u_int32_t)); + acg.cg_clustersumoff -= sizeof(u_int32_t); acg.cg_clusteroff = acg.cg_clustersumoff + (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t); - acg.cg_nextfreeoff = acg.cg_clusteroff + howmany - (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY); + acg.cg_nextfreeoff = acg.cg_clusteroff + + howmany(fragstoblks(&sblock, sblock.fs_fpg), NBBY); } - if (acg.cg_nextfreeoff - (long)(&acg.cg_firstfield) > - sblock.fs_cgsize) { + if (acg.cg_nextfreeoff > sblock.fs_cgsize) { printf("Panic: cylinder group too big\n"); exit(37); } acg.cg_cs.cs_nifree += sblock.fs_ipg; if (cylno == 0) - for (i = 0; i < ROOTINO; i++) { + for (i = 0; i < (long)ROOTINO; i++) { setbit(cg_inosused(&acg), i); acg.cg_cs.cs_nifree--; } - for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) { - for (j = 0; j < sblock.fs_bsize / sizeof(struct dinode); j++) - zino[j].di_gen = random(); - wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), - sblock.fs_bsize, (char *)zino); - } if (cylno > 0) { /* * In cylno 0, beginning space is reserved @@ -649,13 +581,8 @@ initcg(int cylno, time_t utime) if (sblock.fs_contigsumsize > 0) setbit(cg_clustersfree(&acg), blkno); acg.cg_cs.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]++; } - sblock.fs_dsize += dlower; } - sblock.fs_dsize += acg.cg_ndblk - dupper; if ((i = dupper % sblock.fs_frag)) { acg.cg_frsum[sblock.fs_frag - i]++; for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { @@ -663,20 +590,17 @@ initcg(int cylno, time_t utime) acg.cg_cs.cs_nffree++; } } - for (d = dupper; d + sblock.fs_frag <= dmax - cbase;) { + for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk; + d += sblock.fs_frag) { blkno = d / sblock.fs_frag; setblock(&sblock, cg_blksfree(&acg), blkno); if (sblock.fs_contigsumsize > 0) setbit(cg_clustersfree(&acg), blkno); acg.cg_cs.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]++; - d += sblock.fs_frag; } - if (d < dmax - cbase) { - acg.cg_frsum[dmax - cbase - d]++; - for (; d < dmax - cbase; d++) { + if (d < acg.cg_ndblk) { + acg.cg_frsum[acg.cg_ndblk - d]++; + for (; d < acg.cg_ndblk; d++) { setbit(cg_blksfree(&acg), d); acg.cg_cs.cs_nffree++; } @@ -710,61 +634,103 @@ initcg(int cylno, time_t utime) sump[run]++; } } - sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; - sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; - sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; - sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; *cs = acg.cg_cs; - wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), - sblock.fs_bsize, (char *)&acg); + /* + * Write out the duplicate super block, the cylinder group map + * and two blocks worth of inodes in a single write. + */ + start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE; + bcopy((char *)&acg, &iobuf[start], sblock.fs_cgsize); + start += sblock.fs_bsize; + dp1 = (struct ufs1_dinode *)(&iobuf[start]); + dp2 = (struct ufs2_dinode *)(&iobuf[start]); + for (i = 0; i < acg.cg_initediblk; i++) { + if (sblock.fs_magic == FS_UFS1_MAGIC) { + dp1->di_gen = random(); + dp1++; + } else { + dp2->di_gen = random(); + dp2++; + } + } + wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf); + /* + * For the old filesystem, we have to initialize all the inodes. + */ + if (Oflag == 1) { + for (i = 2 * sblock.fs_frag; + i < sblock.fs_ipg / INOPF(&sblock); + i += sblock.fs_frag) { + dp1 = (struct ufs1_dinode *)(&iobuf[start]); + for (j = 0; j < INOPB(&sblock); j++) { + dp1->di_gen = random(); + dp1++; + } + wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), + sblock.fs_bsize, &iobuf[start]); + } + } } /* * initialize the filesystem */ -struct dinode node; - #define PREDEFDIR 2 struct direct root_dir[] = { { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, }; -struct odirect { - u_long d_ino; - u_short d_reclen; - u_short d_namlen; - u_char d_name[MAXNAMLEN + 1]; -} oroot_dir[] = { - { ROOTINO, sizeof(struct direct), 1, "." }, - { ROOTINO, sizeof(struct direct), 2, ".." }, -}; -char buf[MAXBSIZE]; void fsinit(time_t utime) { + union dinode node; - /* - * initialize the node - */ - node.di_atime = utime; - node.di_mtime = utime; - node.di_ctime = utime; - /* - * create the root directory - */ - node.di_mode = IFDIR | UMASK; - node.di_nlink = PREDEFDIR; - node.di_size = makedir(root_dir, PREDEFDIR); - node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode); - node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); - wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf); + memset(&node, 0, sizeof node); + if (sblock.fs_magic == FS_UFS1_MAGIC) { + /* + * initialize the node + */ + node.dp1.di_atime = utime; + node.dp1.di_mtime = utime; + node.dp1.di_ctime = utime; + /* + * create the root directory + */ + node.dp1.di_mode = IFDIR | UMASK; + node.dp1.di_nlink = PREDEFDIR; + node.dp1.di_size = makedir(root_dir, PREDEFDIR); + node.dp1.di_db[0] = alloc(sblock.fs_fsize, node.dp1.di_mode); + node.dp1.di_blocks = + btodb(fragroundup(&sblock, node.dp1.di_size)); + wtfs(fsbtodb(&sblock, node.dp1.di_db[0]), sblock.fs_fsize, + iobuf); + } else { + /* + * initialize the node + */ + node.dp2.di_atime = utime; + node.dp2.di_mtime = utime; + node.dp2.di_ctime = utime; + node.dp2.di_createtime = utime; + /* + * create the root directory + */ + node.dp2.di_mode = IFDIR | UMASK; + node.dp2.di_nlink = PREDEFDIR; + node.dp2.di_size = makedir(root_dir, PREDEFDIR); + node.dp2.di_db[0] = alloc(sblock.fs_fsize, node.dp2.di_mode); + node.dp2.di_blocks = + btodb(fragroundup(&sblock, node.dp2.di_size)); + wtfs(fsbtodb(&sblock, node.dp2.di_db[0]), sblock.fs_fsize, + iobuf); + } iput(&node, ROOTINO); } /* - * construct a set of directory entries in "buf". + * construct a set of directory entries in "iobuf". * return size of directory. */ int @@ -774,7 +740,8 @@ makedir(struct direct *protodir, int entries) int i, spcleft; spcleft = DIRBLKSIZ; - for (cp = buf, i = 0; i < entries - 1; i++) { + memset(iobuf, 0, DIRBLKSIZ); + for (cp = iobuf, i = 0; i < entries - 1; i++) { protodir[i].d_reclen = DIRSIZ(0, &protodir[i]); memmove(cp, &protodir[i], protodir[i].d_reclen); cp += protodir[i].d_reclen; @@ -788,11 +755,10 @@ makedir(struct direct *protodir, int entries) /* * allocate a block or frag */ -daddr_t +ufs2_daddr_t alloc(int size, int mode) { - int i, frag; - daddr_t d, blkno; + int i, d, blkno, frag; rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, (char *)&acg); @@ -822,8 +788,6 @@ goth: sblock.fs_cstotal.cs_ndir++; fscs[0].cs_ndir++; } - cg_blktot(&acg)[cbtocylno(&sblock, d)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; if (size != sblock.fs_bsize) { frag = howmany(size, sblock.fs_fsize); fscs[0].cs_nffree += sblock.fs_frag - frag; @@ -835,54 +799,18 @@ goth: } wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, (char *)&acg); - return (d); -} - -/* - * Calculate number of inodes per group. - */ -long -calcipg(long lcpg, long bpcg, off_t *usedbp) -{ - int i; - long ipg, new_ipg, ncg, ncyl; - off_t usedb; - - /* - * Prepare to scale by fssize / (number of sectors in cylinder groups). - * Note that fssize is still in sectors, not filesystem blocks. - */ - ncyl = howmany(fssize, (u_int)secpercyl); - ncg = howmany(ncyl, lcpg); - /* - * Iterate a few times to allow for ipg depending on itself. - */ - ipg = 0; - for (i = 0; i < 10; i++) { - usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock)) * - NSPF(&sblock) * (off_t)sectorsize; - new_ipg = (lcpg * (quad_t)bpcg - usedb) / density * - fssize / ncg / secpercyl / lcpg; - new_ipg = roundup(new_ipg, INOPB(&sblock)); - if (new_ipg == ipg) - break; - ipg = new_ipg; - } - *usedbp = usedb; - return (ipg); + return ((ufs2_daddr_t)d); } /* * Allocate an inode on the disk */ void -iput(struct dinode *ip, ino_t ino) +iput(union dinode *ip, ino_t ino) { - struct dinode lbuf[MAXINOPB]; - daddr_t d; + ufs2_daddr_t d; int c; - ip->di_gen = random(); c = ino_to_cg(&sblock, ino); rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, (char *)&acg); @@ -896,21 +824,26 @@ iput(struct dinode *ip, ino_t ino) (char *)&acg); sblock.fs_cstotal.cs_nifree--; fscs[0].cs_nifree--; - if (ino >= sblock.fs_ipg * sblock.fs_ncg) { + if (ino >= (unsigned long)sblock.fs_ipg * sblock.fs_ncg) { printf("fsinit: inode value out of range (%d).\n", ino); exit(32); } d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); - rdfs(d, sblock.fs_bsize, (char *)lbuf); - lbuf[ino_to_fsbo(&sblock, ino)] = *ip; - wtfs(d, sblock.fs_bsize, (char *)lbuf); + rdfs(d, sblock.fs_bsize, (char *)iobuf); + if (sblock.fs_magic == FS_UFS1_MAGIC) + ((struct ufs1_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] = + ip->dp1; + else + ((struct ufs2_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] = + ip->dp2; + wtfs(d, sblock.fs_bsize, (char *)iobuf); } /* * read a block from the filesystem */ void -rdfs(daddr_t bno, int size, char *bf) +rdfs(ufs2_daddr_t bno, int size, char *bf) { int n; @@ -927,7 +860,7 @@ rdfs(daddr_t bno, int size, char *bf) } #define WCSIZE (128 * 1024) -daddr_t wc_sect; /* units of sectorsize */ +ufs2_daddr_t wc_sect; /* units of sectorsize */ int wc_end; /* bytes */ static char wc[WCSIZE]; /* bytes */ @@ -956,7 +889,7 @@ wtfsflush() * write a block to the filesystem */ static void -wtfs(daddr_t bno, int size, char *bf) +wtfs(ufs2_daddr_t bno, int size, char *bf) { int done, n; diff --git a/sbin/newfs/newfs.8 b/sbin/newfs/newfs.8 index 9ca6337..c20fe15 100644 --- a/sbin/newfs/newfs.8 +++ b/sbin/newfs/newfs.8 @@ -32,7 +32,7 @@ .\" @(#)newfs.8 8.6 (Berkeley) 5/3/95 .\" $FreeBSD$ .\" -.Dd May 29, 2001 +.Dd May 18, 2002 .Dt NEWFS 8 .Os .Sh NAME @@ -40,12 +40,14 @@ .Nd construct a new filesystem .Sh SYNOPSIS .Nm -.Op Fl NOU +.Op Fl NU +.Op Fl O Ar filesystem-type .Op Fl S Ar sector-size .Op Fl T Ar disktype .Op Fl a Ar maxcontig .Op Fl b Ar block-size -.Op Fl c Ar cylinders +.Op Fl c Ar blocks-per-cylinder-group +.Op Fl d Ar max-extent-size .Op Fl e Ar maxbpg .Op Fl f Ar frag-size .Op Fl g Ar avgfilesize @@ -54,7 +56,6 @@ .Op Fl m Ar free space .Op Fl o Ar optimization .Op Fl s Ar size -.Op Fl u Ar sectors .Ar special .Sh DESCRIPTION .Nm Newfs @@ -82,12 +83,16 @@ For backward compatibility. .It Fl N Cause the filesystem parameters to be printed out without really creating the filesystem. +.It Fl O +Use 1 to specify that a UFS1 format filesystem be built; +use 2 to specify that a UFS2 format filesystem be built. +The default is UFS1 format, but will eventually be changed to UFS2. .It Fl U Enables soft updates on the new filesystem. .It Fl a Ar maxcontig Specify the maximum number of contiguous blocks that will be laid out before forcing a rotational delay. -The default value is 1. +The default value is 16. See .Xr tunefs 8 for more details on how to set this option. @@ -96,12 +101,17 @@ The block size of the filesystem, in bytes. It must be a power of 2. The default size is 16384 bytes, and the smallest allowable size is 4096 bytes. The optimal block:fragment ratio is 8:1. Other ratios are possible, but are not recommended, -and may produce unpredictable results. -.It Fl c Ar #cylinders/group -The number of cylinders per cylinder group in a filesystem. The default +and may produce poor results. +.It Fl c Ar number of blocks per cylinders group +The number of blocks per cylinder group in a filesystem. The default is to compute the maximum allowed by the other parameters. This value is dependent on a number of other parameters, in particular the block size and the number of bytes per inode. +.It Fl d Ar max extent size +The filesystem may choose to store large files using extents. +This parameter specifies the largest extent size that may be used. +It is presently limited to its default value which is 16 times +the filesystem blocksize. .It Fl e Ar maxbpg Indicate the maximum number of blocks any single file can allocate out of a cylinder group before it is forced to begin @@ -178,11 +188,6 @@ to find the alternate superblocks if the standard superblock is lost. .Bl -tag -width indent .It Fl S Ar sector-size The size of a sector in bytes (almost never anything but 512). -.It Fl u Ar sectors/cylinders -The number of sectors per cylinder available for data allocation by the file -system. -The default is 4096. -If zero is specified, the value from the disklabel will be used. .El .Sh EXAMPLES .Dl newfs /dev/ad3s1a @@ -191,13 +196,12 @@ Creates a new ufs filesystem on .Pa ad3s1a . .Nm will use a block size of 16384 bytes, a fragment size of 2048 bytes -and the largest possible number of cylinders per group. +and the largest possible number of blocks per cylinders group. These values tend to produce better performance for most applications than the historical defaults (8192 byte block size and 1024 byte fragment size). -This large fragment size -may lead to large amounts of wasted space -on filesystems that contain a large number of small files. +This large fragment size may lead to much wasted space +on filesystems that contain many small files. .Sh SEE ALSO .Xr fdformat 1 , .Xr disktab 5 , diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c index f6b9e71..6c43a37 100644 --- a/sbin/newfs/newfs.c +++ b/sbin/newfs/newfs.c @@ -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) 1983, 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * @@ -84,19 +96,19 @@ static const char rcsid[] = #define DFL_BLKSIZE 16384 /* - * Cylinder groups may have up to many cylinders. The actual + * Cylinder groups may have up to MAXBLKSPERCG blocks. The actual * number used depends upon how much information can be stored - * on a single cylinder. The default is to use as many as possible - * cylinders per group. + * in a cylinder group map which must fit in a single filesystem + * block. The default is to use as many as possible blocks per group. */ -#define DESCPG 65536 /* desired fs_cpg ("infinity") */ +#define MAXBLKSPERCG 0x7fffffff /* desired fs_fpg ("infinity") */ /* * MAXBLKPG determines the maximum number of data blocks which are * placed in a single cylinder group. The default is one indirect * block worth of data blocks. */ -#define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t)) +#define MAXBLKPG(bsize) ((bsize) / sizeof(ufs2_daddr_t)) /* * Each filesystem has a number of inodes statically allocated. @@ -105,26 +117,17 @@ static const char rcsid[] = */ #define NFPI 4 -/* - * About the same time as the above, we knew what went where on the disks. - * no longer so, so kill the code which finds the different platters too... - * We do this by saying one head, with a lot of sectors on it. - * The number of sectors are used to determine the size of a cyl-group. - * Kirk suggested one or two meg per "cylinder" so we say two. - */ -#define NSECTORS 4096 /* number of sectors */ - int Nflag; /* run without writing filesystem */ +int Oflag = 1; /* filesystem format (1 => UFS1, 2 => UFS2) */ int Rflag; /* regression test */ int Uflag; /* enable soft updates for filesystem */ -u_int fssize; /* filesystem size */ -u_int secpercyl = NSECTORS; /* sectors per cylinder */ -u_int sectorsize; /* bytes/sector */ +quad_t fssize; /* file system size */ +int sectorsize; /* bytes/sector */ int realsectorsize; /* bytes/sector in hardware */ int fsize = 0; /* fragment size */ int bsize = 0; /* block size */ -int cpg = DESCPG; /* cylinders/cylinder group */ -int cpgflg; /* cylinders/cylinder group flag was given */ +int maxbsize = 0; /* maximum clustering */ +int maxblkspercg = MAXBLKSPERCG; /* maximum blocks per cylinder group */ int minfree = MINFREE; /* free space threshold */ int opt = DEFAULTOPT; /* optimization preference (space or time) */ int density; /* number of bytes per inode */ @@ -136,7 +139,6 @@ int fso; /* filedescriptor to device */ static char device[MAXPATHLEN]; static char *disktype; -static int t_or_u_flag; /* user has specified -t or -u */ static int unlabeled; static struct disklabel *getdisklabel(char *s); @@ -151,15 +153,20 @@ main(int argc, char *argv[]) struct partition oldpartition; struct stat st; char *cp, *special; - int ch, n; + int ch; off_t mediasize; while ((ch = getopt(argc, argv, - "NRS:T:Ua:b:c:e:f:g:h:i:m:o:s:u:")) != -1) + "NO:RS:T:Ua:b:c:d:e:f:g:h:i:m:o:s:")) != -1) switch (ch) { case 'N': Nflag = 1; break; + case 'O': + if ((Oflag = atoi(optarg)) < 1 || Oflag > 2) + errx(1, "%s: bad filesystem format value", + optarg); + break; case 'R': Rflag = 1; break; @@ -183,13 +190,17 @@ main(int argc, char *argv[]) errx(1, "%s: bad block size", optarg); break; case 'c': - if ((cpg = atoi(optarg)) <= 0) - errx(1, "%s: bad cylinders/group", optarg); - cpgflg++; + if ((maxblkspercg = atoi(optarg)) <= 0) + errx(1, "%s: bad blocks per cylinder group", + optarg); + break; + case 'd': + if ((maxbsize = atoi(optarg)) < MINBSIZE) + errx(1, "%s: bad extent block size", optarg); break; case 'e': if ((maxbpg = atoi(optarg)) <= 0) - errx(1, "%s: bad blocks per file in a cylinder group", + errx(1, "%s: bad blocks per file in a cylinder group", optarg); break; case 'f': @@ -202,7 +213,7 @@ main(int argc, char *argv[]) break; case 'h': if ((avgfilesperdir = atoi(optarg)) <= 0) - errx(1, "%s: bad average files per dir", optarg); + errx(1, "%s: bad average files per dir", optarg); break; case 'i': if ((density = atoi(optarg)) <= 0) @@ -226,12 +237,6 @@ main(int argc, char *argv[]) if ((fssize = atoi(optarg)) <= 0) errx(1, "%s: bad filesystem size", optarg); break; - case 'u': - t_or_u_flag++; - if ((n = atoi(optarg)) < 0) - errx(1, "%s: bad sectors/track", optarg); - secpercyl = n; - break; case '?': default: usage(); @@ -293,8 +298,6 @@ main(int argc, char *argv[]) if (fssize > pp->p_size) errx(1, "%s: maximum filesystem size %d", special, pp->p_size); - if (secpercyl == 0) - secpercyl = lp->d_nsectors; if (sectorsize == 0) sectorsize = lp->d_secsize; if (fsize == 0) @@ -308,8 +311,8 @@ main(int argc, char *argv[]) fsize = MAX(DFL_FRAGSIZE, sectorsize); if (bsize <= 0) bsize = MIN(DFL_BLKSIZE, 8 * fsize); - if (secpercyl <= 0) - errx(1, "%s: no default #sectors/track", special); + if (maxbsize == 0) + maxbsize = bsize; /* * Maxcontig sets the default for the maximum number of blocks * that may be allocated sequentially. With filesystem clustering @@ -317,7 +320,7 @@ main(int argc, char *argv[]) * transfer size permitted by the controller or buffering. */ if (maxcontig == 0) - maxcontig = MAX(1, MAXPHYS / bsize - 1); + maxcontig = MAX(1, MAXPHYS / bsize); if (density == 0) density = NFPI * fsize; if (minfree < MINFREE && opt != FS_OPTSPACE) { @@ -325,15 +328,6 @@ main(int argc, char *argv[]) fprintf(stderr, "because minfree is less than %d%%\n", MINFREE); opt = FS_OPTSPACE; } - /* - * Only complain if -t or -u have been specified; the default - * case (4096 sectors per cylinder) is intended to disagree - * with the disklabel. - */ - if (t_or_u_flag && lp != NULL && secpercyl != lp->d_secpercyl) - fprintf(stderr, "%s (%d) %s (%lu)\n", - "Warning: calculated sectors per cylinder", secpercyl, - "disagrees with disk label", (u_long)lp->d_secpercyl); if (maxbpg == 0) maxbpg = MAXBLKPG(bsize); realsectorsize = sectorsize; @@ -341,7 +335,6 @@ main(int argc, char *argv[]) int secperblk = sectorsize / DEV_BSIZE; sectorsize = DEV_BSIZE; - secpercyl *= secperblk; fssize *= secperblk; if (pp != NULL); pp->p_size *= secperblk; @@ -349,7 +342,7 @@ main(int argc, char *argv[]) mkfs(pp, special); if (!unlabeled) { if (realsectorsize != DEV_BSIZE) - pp->p_size /= realsectorsize /DEV_BSIZE; + pp->p_size /= realsectorsize / DEV_BSIZE; if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition))) rewritelabel(special, lp); } @@ -357,8 +350,6 @@ main(int argc, char *argv[]) exit(0); } -const char lmsg[] = "%s: can't read disk label; disk type must be specified"; - struct disklabel * getdisklabel(char *s) { @@ -399,13 +390,15 @@ usage() fprintf(stderr, "where fsoptions are:\n"); fprintf(stderr, "\t-N do not create filesystem, just print out parameters\n"); + fprintf(stderr, "\t-O filesystem format: 1 => UFS1, 2 => UFS2\n"); fprintf(stderr, "\t-R regression test, supress random factors\n"); fprintf(stderr, "\t-S sector size\n"); fprintf(stderr, "\t-T disktype\n"); fprintf(stderr, "\t-U enable soft updates\n"); fprintf(stderr, "\t-a maximum contiguous blocks\n"); fprintf(stderr, "\t-b block size\n"); - fprintf(stderr, "\t-c cylinders/group\n"); + fprintf(stderr, "\t-c blocks per cylinders group\n"); + fprintf(stderr, "\t-d maximum extent size\n"); fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); fprintf(stderr, "\t-f frag size\n"); fprintf(stderr, "\t-g average file size\n"); @@ -413,9 +406,6 @@ usage() fprintf(stderr, "\t-i number of bytes per inode\n"); fprintf(stderr, "\t-m minimum free space %%\n"); fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); - fprintf(stderr, "\t-s filesystem size (sectors)\n"); - fprintf(stderr, "\t-u sectors/cylinder\n"); - fprintf(stderr, - "\t-v do not attempt to determine partition name from device name\n"); + fprintf(stderr, "\t-s file systemsize (sectors)\n"); exit(1); } diff --git a/sbin/newfs/newfs.h b/sbin/newfs/newfs.h index d5fec76..636c112 100644 --- a/sbin/newfs/newfs.h +++ b/sbin/newfs/newfs.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, 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -38,16 +50,16 @@ * variables set up by front end. */ extern int Nflag; /* run mkfs without writing filesystem */ +extern int Oflag; /* build UFS1 format filesystem */ extern int Rflag; /* regression test */ extern int Uflag; /* enable soft updates for filesystem */ -extern u_int fssize; /* filesystem size */ -extern u_int secpercyl; /* sectors per cylinder */ -extern u_int sectorsize; /* bytes/sector */ +extern quad_t fssize; /* file system size */ +extern int sectorsize; /* bytes/sector */ extern int realsectorsize; /* bytes/sector in hardware*/ extern int fsize; /* fragment size */ extern int bsize; /* block size */ -extern int cpg; /* cylinders/cylinder group */ -extern int cpgflg; /* cylinders/cylinder group flag was given */ +extern int maxbsize; /* maximum clustering */ +extern int maxblkspercg; /* maximum blocks per cylinder group */ extern int minfree; /* free space threshold */ extern int opt; /* optimization preference (space or time) */ extern int density; /* number of bytes per inode */ diff --git a/sbin/quotacheck/quotacheck.c b/sbin/quotacheck/quotacheck.c index 54339e7..8407676 100644 --- a/sbin/quotacheck/quotacheck.c +++ b/sbin/quotacheck/quotacheck.c @@ -82,6 +82,14 @@ union { long dev_bsize = 1; ino_t maxino; +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) + struct quotaname { long flags; char grpqfname[MAXPATHLEN + 1]; @@ -116,7 +124,7 @@ extern int checkfstab(int, int, void * (*)(struct fstab *), int (*)(char *, char *, struct quotaname *)); int chkquota(char *, char *, struct quotaname *); void freeinodebuf(void); -struct dinode * +union dinode * getnextinode(ino_t); int getquotagid(void); int hasquota(struct fstab *, int, char **); @@ -241,6 +249,11 @@ needchk(fs) } /* + * Possible superblock locations ordered from most to least likely. + */ +static int sblock_try[] = SBLOCKSEARCH; + +/* * Scan the specified filesystem to check quota(s) present on it. */ int @@ -249,7 +262,7 @@ chkquota(fsname, mntpt, qnp) struct quotaname *qnp; { struct fileusage *fup; - struct dinode *dp; + union dinode *dp; int cg, i, mode, errs = 0; ino_t ino; @@ -268,7 +281,20 @@ chkquota(fsname, mntpt, qnp) } sync(); dev_bsize = 1; - bread(SBOFF, (char *)&sblock, (long)SBSIZE); + for (i = 0; sblock_try[i] != -1; i++) { + bread(sblock_try[i], (char *)&sblock, (long)SBLOCKSIZE); + if ((sblock.fs_magic == FS_UFS1_MAGIC || + (sblock.fs_magic == FS_UFS2_MAGIC && + sblock.fs_sblockloc == + numfrags(&sblock, sblock_try[i]))) && + sblock.fs_bsize <= MAXBSIZE && + sblock.fs_bsize >= sizeof(struct fs)) + break; + } + if (sblock_try[i] == -1) { + warn("Cannot find filesystem superblock"); + return (1); + } dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); maxino = sblock.fs_ncg * sblock.fs_ipg; resetinodebuf(); @@ -278,23 +304,23 @@ chkquota(fsname, mntpt, qnp) continue; if ((dp = getnextinode(ino)) == NULL) continue; - if ((mode = dp->di_mode & IFMT) == 0) + if ((mode = DIP(dp, di_mode) & IFMT) == 0) continue; if (qnp->flags & HASGRP) { - fup = addid((u_long)dp->di_gid, GRPQUOTA, + fup = addid((u_long)DIP(dp, di_gid), GRPQUOTA, (char *)0); fup->fu_curinodes++; if (mode == IFREG || mode == IFDIR || mode == IFLNK) - fup->fu_curblocks += dp->di_blocks; + fup->fu_curblocks += DIP(dp, di_blocks); } if (qnp->flags & HASUSR) { - fup = addid((u_long)dp->di_uid, USRQUOTA, + fup = addid((u_long)DIP(dp, di_uid), USRQUOTA, (char *)0); fup->fu_curinodes++; if (mode == IFREG || mode == IFDIR || mode == IFLNK) - fup->fu_curblocks += dp->di_blocks; + fup->fu_curblocks += DIP(dp, di_blocks); } } } @@ -536,20 +562,21 @@ addid(id, type, name) * Special purpose version of ginode used to optimize pass * over all the inodes in numerical order. */ -ino_t nextino, lastinum; -long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; -struct dinode *inodebuf; -#define INOBUFSIZE 56*1024 /* size of buffer to read inodes */ +static ino_t nextino, lastinum, lastvalidinum; +static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; +static caddr_t inodebuf; +#define INOBUFSIZE 56*1024 /* size of buffer to read inodes */ -struct dinode * +union dinode * getnextinode(inumber) ino_t inumber; { long size; - daddr_t dblk; - static struct dinode *dp; + ufs2_daddr_t dblk; + union dinode *dp; + static caddr_t nextinop; - if (inumber != nextino++ || inumber > maxino) + if (inumber != nextino++ || inumber > lastvalidinum) errx(1, "bad inode number %d to nextinode", inumber); if (inumber >= lastinum) { readcnt++; @@ -561,10 +588,19 @@ getnextinode(inumber) size = inobufsize; lastinum += fullcnt; } - bread(dblk, (char *)inodebuf, size); - dp = inodebuf; + /* + * If bread returns an error, it will already have zeroed + * out the buffer, so we do not need to do so here. + */ + bread(dblk, inodebuf, 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); } /* @@ -578,10 +614,12 @@ resetinodebuf() lastinum = 0; readcnt = 0; 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 { diff --git a/sbin/restore/dirs.c b/sbin/restore/dirs.c index 32da860..323e9ff 100644 --- a/sbin/restore/dirs.c +++ b/sbin/restore/dirs.c @@ -120,7 +120,7 @@ struct odirect { char d_name[ODIRSIZ]; }; -static struct inotab *allocinotab(ino_t, struct dinode *, long); +static struct inotab *allocinotab(struct context *, long); static void dcvt(struct odirect *, struct direct *); static void flushent(void); static struct inotab *inotablookup(ino_t); @@ -140,11 +140,9 @@ static struct direct *searchdir(ino_t, char *); void extractdirs(int genmode) { - int i; - struct dinode *ip; struct inotab *itp; struct direct nulldir; - int fd; + int i, fd; const char *tmpdir; vprintf(stdout, "Extract directories from tape\n"); @@ -184,8 +182,7 @@ extractdirs(int genmode) for (;;) { curfile.name = "<directory file - name unknown>"; curfile.action = USING; - ip = curfile.dip; - if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { + if (curfile.mode == 0 || (curfile.mode & IFMT) != IFDIR) { (void) fclose(df); dirp = opendirfile(dirfile); if (dirp == NULL) @@ -198,7 +195,7 @@ extractdirs(int genmode) panic("Root directory is not on tape\n"); return; } - itp = allocinotab(curfile.ino, ip, seekpt); + itp = allocinotab(&curfile, seekpt); getfile(putdir, xtrnull); putent(&nulldir); flushent(); @@ -213,7 +210,7 @@ void skipdirs(void) { - while (curfile.dip && (curfile.dip->di_mode & IFMT) == IFDIR) { + while (curfile.ino && (curfile.mode & IFMT) == IFDIR) { skipfile(); } } @@ -343,53 +340,34 @@ putdir(char *buf, long size) struct direct *dp; long loc, i; - if (cvtflag) { - eodp = (struct odirect *)&buf[size]; - for (odp = (struct odirect *)buf; odp < eodp; odp++) - if (odp->d_ino != 0) { - dcvt(odp, &cvtbuf); - putent(&cvtbuf); - } - } else { - for (loc = 0; loc < size; ) { - dp = (struct direct *)(buf + loc); - if (Bcvt) - swabst((u_char *)"ls", (u_char *) dp); - if (oldinofmt && dp->d_ino != 0) { -# if BYTE_ORDER == BIG_ENDIAN - if (Bcvt) - dp->d_namlen = dp->d_type; -# else - if (!Bcvt) - dp->d_namlen = dp->d_type; -# endif - dp->d_type = DT_UNKNOWN; - } - i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); - if ((dp->d_reclen & 0x3) != 0 || - dp->d_reclen > i || - dp->d_reclen < DIRSIZ(0, dp) || - dp->d_namlen > NAME_MAX) { - vprintf(stdout, "Mangled directory: "); - if ((dp->d_reclen & 0x3) != 0) - vprintf(stdout, - "reclen not multiple of 4 "); - if (dp->d_reclen < DIRSIZ(0, dp)) - vprintf(stdout, - "reclen less than DIRSIZ (%d < %d) ", - dp->d_reclen, DIRSIZ(0, dp)); - if (dp->d_namlen > NAME_MAX) - vprintf(stdout, - "reclen name too big (%d > %d) ", - dp->d_namlen, NAME_MAX); - vprintf(stdout, "\n"); - loc += i; - continue; - } - loc += dp->d_reclen; - if (dp->d_ino != 0) { - putent(dp); - } + for (loc = 0; loc < size; ) { + dp = (struct direct *)(buf + loc); + if (Bcvt) + swabst((u_char *)"ls", (u_char *) dp); + i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); + if ((dp->d_reclen & 0x3) != 0 || + dp->d_reclen > i || + dp->d_reclen < DIRSIZ(0, dp) || + dp->d_namlen > NAME_MAX) { + vprintf(stdout, "Mangled directory: "); + if ((dp->d_reclen & 0x3) != 0) + vprintf(stdout, + "reclen not multiple of 4 "); + if (dp->d_reclen < DIRSIZ(0, dp)) + vprintf(stdout, + "reclen less than DIRSIZ (%d < %d) ", + dp->d_reclen, DIRSIZ(0, dp)); + if (dp->d_namlen > NAME_MAX) + vprintf(stdout, + "reclen name too big (%d > %d) ", + dp->d_namlen, NAME_MAX); + vprintf(stdout, "\n"); + loc += i; + continue; + } + loc += dp->d_reclen; + if (dp->d_ino != 0) { + putent(dp); } } } @@ -692,7 +670,7 @@ inodetype(ino_t ino) * If requested, save its pertinent mode, owner, and time info. */ static struct inotab * -allocinotab(ino_t ino, struct dinode *dip, long seekpt) +allocinotab(struct context *ctxp, long seekpt) { struct inotab *itp; struct modeinfo node; @@ -700,21 +678,21 @@ allocinotab(ino_t ino, struct dinode *dip, long seekpt) itp = calloc(1, sizeof(struct inotab)); if (itp == NULL) panic("no memory directory table\n"); - itp->t_next = inotab[INOHASH(ino)]; - inotab[INOHASH(ino)] = itp; - itp->t_ino = ino; + itp->t_next = inotab[INOHASH(ctxp->ino)]; + inotab[INOHASH(ctxp->ino)] = itp; + itp->t_ino = ctxp->ino; itp->t_seekpt = seekpt; if (mf == NULL) return (itp); - node.ino = ino; - node.timep[0].tv_sec = dip->di_atime; - node.timep[0].tv_usec = dip->di_atimensec / 1000; - node.timep[1].tv_sec = dip->di_mtime; - node.timep[1].tv_usec = dip->di_mtimensec / 1000; - node.mode = dip->di_mode; - node.flags = dip->di_flags; - node.uid = dip->di_uid; - node.gid = dip->di_gid; + node.ino = ctxp->ino; + node.timep[0].tv_sec = ctxp->atime_sec; + node.timep[0].tv_usec = ctxp->atime_nsec / 1000; + node.timep[1].tv_sec = ctxp->mtime_sec; + node.timep[1].tv_usec = ctxp->mtime_nsec / 1000; + node.mode = ctxp->mode; + node.flags = ctxp->file_flags; + node.uid = ctxp->uid; + node.gid = ctxp->gid; (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); return (itp); } diff --git a/sbin/restore/main.c b/sbin/restore/main.c index 0c7b363..ef3df7a 100644 --- a/sbin/restore/main.c +++ b/sbin/restore/main.c @@ -98,9 +98,9 @@ main(int argc, char *argv[]) inputdev = _PATH_DEFTAPE; obsolete(&argc, &argv); #ifdef KERBEROS -#define optlist "b:cdf:hikmNRrs:tuvxy" +#define optlist "b:df:hikmNRrs:tuvxy" #else -#define optlist "b:cdf:himNRrs:tuvxy" +#define optlist "b:df:himNRrs:tuvxy" #endif while ((ch = getopt(argc, argv, optlist)) != -1) switch(ch) { @@ -113,9 +113,6 @@ main(int argc, char *argv[]) if (ntrec <= 0) errx(1, "block size must be greater than 0"); break; - case 'c': - cvtflag = 1; - break; case 'd': dflag = 1; break; diff --git a/sbin/restore/restore.c b/sbin/restore/restore.c index 46e208b..0a3647d 100644 --- a/sbin/restore/restore.c +++ b/sbin/restore/restore.c @@ -41,11 +41,11 @@ static const char rcsid[] = #include <sys/types.h> -#include <ufs/ufs/dinode.h> - #include <stdio.h> #include <string.h> +#include <ufs/ufs/dinode.h> + #include "restore.h" #include "extern.h" diff --git a/sbin/restore/restore.h b/sbin/restore/restore.h index 1e71330..cb10d81 100644 --- a/sbin/restore/restore.h +++ b/sbin/restore/restore.h @@ -42,7 +42,6 @@ /* * Flags */ -extern int cvtflag; /* convert from old to new tape format */ extern int bflag; /* set input block size */ extern int dflag; /* print out debugging info */ extern int hflag; /* restore heirarchies */ @@ -64,7 +63,6 @@ extern time_t dumptime; /* time that this dump begins */ extern time_t dumpdate; /* time that this dump was made */ extern char command; /* opration being performed */ extern FILE *terminal; /* file descriptor for the terminal input */ -extern int oldinofmt; /* reading tape with old format inodes */ extern int Bcvt; /* need byte swapping on inodes and dirs */ /* @@ -106,10 +104,19 @@ struct entry { * The entry describes the next file available on the tape */ struct context { - char *name; /* name of file */ + short action; /* action being taken on this file */ + mode_t mode; /* mode of file */ ino_t ino; /* inumber of file */ - struct dinode *dip; /* pointer to inode */ - char action; /* action being taken on this file */ + uid_t uid; /* file owner */ + gid_t gid; /* file group */ + int file_flags; /* status flags (chflags) */ + int rdev; /* device number of file */ + time_t atime_sec; /* access time seconds */ + time_t mtime_sec; /* modified time seconds */ + int atime_nsec; /* access time nanoseconds */ + int mtime_nsec; /* modified time nanoseconds */ + off_t size; /* size of file */ + char *name; /* name of file */ } curfile; /* actions */ #define USING 1 /* extracting from the tape */ diff --git a/sbin/restore/tape.c b/sbin/restore/tape.c index c40c7a9..2b2ab91 100644 --- a/sbin/restore/tape.c +++ b/sbin/restore/tape.c @@ -74,20 +74,19 @@ static int numtrec; static char *tapebuf; static union u_spcl endoftapemark; static long blksread; /* blocks read since last header */ -static long tapeaddr = 0; /* current TP_BSIZE tape record */ +static int64_t tapeaddr = 0; /* current TP_BSIZE tape record */ static long tapesread; static jmp_buf restart; static int gettingfile = 0; /* restart has a valid frame */ static char *host = NULL; +static int readmapflag; static int ofile; static char *map; static char lnkbuf[MAXPATHLEN + 1]; static int pathlen; -int oldinofmt; /* old inode format conversion required */ -int Bcvt; /* Swap Bytes (for CCI or sun) */ -static int Qcvt; /* Swap quads (for sun) */ +int Bcvt; /* Swap Bytes */ #define FLUSHTAPEBUF() blkcnt = ntrec + 1 @@ -109,8 +108,6 @@ static void xtrmap(char *, long); static void xtrmapskip(char *, long); static void xtrskip(char *, long); -static int readmapflag; - /* * Set up an input source */ @@ -207,17 +204,11 @@ setup(void) if (!pipein && !bflag) findtapeblksize(); if (gethead(&spcl) == FAIL) { - blkcnt--; /* push back this block */ - blksread--; - cvtflag++; - if (gethead(&spcl) == FAIL) { - fprintf(stderr, "Tape is not a dump tape\n"); - done(1); - } - fprintf(stderr, "Converting to new filesystem format.\n"); + fprintf(stderr, "Tape is not a dump tape\n"); + done(1); } if (pipein) { - endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; + endoftapemark.s_spcl.c_magic = FS_UFS2_MAGIC; endoftapemark.s_spcl.c_type = TS_END; ip = (int *)&endoftapemark; j = sizeof(union u_spcl) / sizeof(int); @@ -229,8 +220,8 @@ setup(void) } if (vflag || command == 't') printdumpinfo(); - dumptime = _time32_to_time(spcl.c_ddate); - dumpdate = _time32_to_time(spcl.c_date); + dumptime = _time64_to_time(spcl.c_ddate); + dumpdate = _time64_to_time(spcl.c_date); if (stat(".", &stbuf) < 0) { fprintf(stderr, "cannot stat .: %s\n", strerror(errno)); done(1); @@ -279,8 +270,7 @@ setup(void) * whiteout inode exists, so that the whiteout entries can be * extracted. */ - if (oldinofmt == 0) - SETINO(WINO, dumpmap); + SETINO(WINO, dumpmap); /* 'r' restores don't call getvol() for tape 1, so mark it as read. */ if (command == 'r') tapesread = 1; @@ -296,7 +286,8 @@ setup(void) void getvol(long nextvol) { - long newvol, prevtapea, savecnt, i; + int64_t prevtapea; + long i, newvol, savecnt; union u_spcl tmpspcl; # define tmpbuf tmpspcl.s_spcl char buf[TP_BSIZE]; @@ -403,9 +394,9 @@ gethdr: volno = 0; goto again; } - if (_time32_to_time(tmpbuf.c_date) != dumpdate || - _time32_to_time(tmpbuf.c_ddate) != dumptime) { - time_t t = _time32_to_time(tmpbuf.c_date); + if (_time64_to_time(tmpbuf.c_date) != dumpdate || + _time64_to_time(tmpbuf.c_ddate) != dumptime) { + time_t t = _time64_to_time(tmpbuf.c_date); fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t)); fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); volno = 0; @@ -420,9 +411,9 @@ gethdr: * If coming to this volume at random, skip to the beginning * of the next record. */ - dprintf(stdout, "last rec %ld, tape starts with %ld\n", prevtapea, + dprintf(stdout, "last rec %qd, tape starts with %qd\n", prevtapea, tmpbuf.c_tapea); - if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) { + if (tmpbuf.c_type == TS_TAPE) { if (curfile.action != USING) { /* * XXX Dump incorrectly sets c_count to 1 in the @@ -475,7 +466,7 @@ terminateinput(void) } curfile.name = "<name unknown>"; curfile.action = UNKNOWN; - curfile.dip = NULL; + curfile.mode = 0; curfile.ino = maxino; if (gettingfile) { gettingfile = 0; @@ -513,9 +504,9 @@ void printdumpinfo(void) { time_t t; - t = _time32_to_time(spcl.c_date); + t = _time64_to_time(spcl.c_date); fprintf(stdout, "Dump date: %s", ctime(&t)); - t = _time32_to_time(spcl.c_ddate); + t = _time64_to_time(spcl.c_ddate); fprintf(stdout, "Dumped from: %s", (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&t)); if (spcl.c_host[0] == '\0') @@ -529,22 +520,18 @@ int extractfile(char *name) { int flags; - uid_t uid; - gid_t gid; mode_t mode; struct timeval timep[2]; struct entry *ep; curfile.name = name; curfile.action = USING; - timep[0].tv_sec = curfile.dip->di_atime; - timep[0].tv_usec = curfile.dip->di_atimensec / 1000; - timep[1].tv_sec = curfile.dip->di_mtime; - timep[1].tv_usec = curfile.dip->di_mtimensec / 1000; - uid = curfile.dip->di_uid; - gid = curfile.dip->di_gid; - mode = curfile.dip->di_mode; - flags = curfile.dip->di_flags; + timep[0].tv_sec = curfile.atime_sec; + timep[0].tv_usec = curfile.atime_nsec / 1000; + timep[1].tv_sec = curfile.mtime_sec; + timep[1].tv_usec = curfile.mtime_nsec / 1000; + mode = curfile.mode; + flags = curfile.file_flags; switch (mode & IFMT) { default: @@ -578,7 +565,7 @@ extractfile(char *name) return (GOOD); } if (linkit(lnkbuf, name, SYMLINK) == GOOD) { - (void) lchown(name, uid, gid); + (void) lchown(name, curfile.uid, curfile.gid); (void) lchmod(name, mode); (void) lutimes(name, timep); return (GOOD); @@ -599,7 +586,7 @@ extractfile(char *name) skipfile(); return (FAIL); } - (void) chown(name, uid, gid); + (void) chown(name, curfile.uid, curfile.gid); (void) chmod(name, mode); (void) utimes(name, timep); (void) chflags(name, flags); @@ -615,13 +602,13 @@ extractfile(char *name) } if (uflag) (void)unlink(name); - if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) { + if (mknod(name, mode, (int)curfile.rdev) < 0) { fprintf(stderr, "%s: cannot create special file: %s\n", name, strerror(errno)); skipfile(); return (FAIL); } - (void) chown(name, uid, gid); + (void) chown(name, curfile.uid, curfile.gid); (void) chmod(name, mode); (void) utimes(name, timep); (void) chflags(name, flags); @@ -643,7 +630,7 @@ extractfile(char *name) skipfile(); return (FAIL); } - (void) fchown(ofile, uid, gid); + (void) fchown(ofile, curfile.uid, curfile.gid); (void) fchmod(ofile, mode); getfile(xtrfile, xtrskip); (void) close(ofile); @@ -687,14 +674,14 @@ getfile(void (*fill)(char *, long), void (*skip)(char *, long)) { int i; int curblk = 0; - quad_t size = spcl.c_dinode.di_size; + quad_t size = spcl.c_size; static char clearedbuf[MAXBSIZE]; char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; char junk[TP_BSIZE]; if (spcl.c_type == TS_END) panic("ran off end of tape\n"); - if (spcl.c_magic != NFS_MAGIC) + if (spcl.c_magic != FS_UFS2_MAGIC) panic("not at beginning of a file\n"); if (!gettingfile && setjmp(restart) != 0) return; @@ -1000,106 +987,43 @@ closemt(void) /* * Read the next block from the tape. - * Check to see if it is one of several vintage headers. - * If it is an old style header, convert it to a new style header. * If it is not any valid header, return an error. */ static int gethead(struct s_spcl *buf) { long i; - union { - quad_t qval; - int32_t val[2]; - } qcvt; - union u_ospcl { - char dummy[TP_BSIZE]; - struct s_ospcl { - int32_t c_type; - int32_t c_date; - int32_t c_ddate; - int32_t c_volume; - int32_t c_tapea; - u_short c_inumber; - int32_t c_magic; - int32_t c_checksum; - struct odinode { - unsigned short odi_mode; - u_short odi_nlink; - u_short odi_uid; - u_short odi_gid; - int32_t odi_size; - int32_t odi_rdev; - char odi_addr[36]; - int32_t odi_atime; - int32_t odi_mtime; - int32_t odi_ctime; - } c_dinode; - int32_t c_count; - char c_addr[256]; - } s_ospcl; - } u_ospcl; - - if (!cvtflag) { - readtape((char *)buf); - if (buf->c_magic != NFS_MAGIC) { - if (swabl(buf->c_magic) != NFS_MAGIC) - return (FAIL); - if (!Bcvt) { - vprintf(stdout, "Note: Doing Byte swapping\n"); - Bcvt = 1; - } + + readtape((char *)buf); + if (buf->c_magic != FS_UFS2_MAGIC && buf->c_magic != NFS_MAGIC) { + if (buf->c_magic == OFS_MAGIC) { + fprintf(stderr, + "Format of dump tape is too old. Must use\n"); + fprintf(stderr, + "a version of restore from before 2002.\n"); + return (FAIL); } - if (checksum((int *)buf) == FAIL) + if (swabl(buf->c_magic) != FS_UFS2_MAGIC && + buf->c_magic != NFS_MAGIC) { + if (buf->c_magic == OFS_MAGIC) { + fprintf(stderr, + "Format of dump tape is too old. Must use\n"); + fprintf(stderr, + "a version of restore from before 2002.\n"); + } return (FAIL); - if (Bcvt) { - swabst((u_char *)"8l4s31l", (u_char *)buf); - swabst((u_char *)"l",(u_char *) &buf->c_level); - swabst((u_char *)"2l",(u_char *) &buf->c_flags); } - goto good; - } - readtape((char *)(&u_ospcl.s_ospcl)); - memset(buf, 0, (long)TP_BSIZE); - buf->c_type = u_ospcl.s_ospcl.c_type; - buf->c_date = u_ospcl.s_ospcl.c_date; - buf->c_ddate = u_ospcl.s_ospcl.c_ddate; - buf->c_volume = u_ospcl.s_ospcl.c_volume; - buf->c_tapea = u_ospcl.s_ospcl.c_tapea; - buf->c_inumber = u_ospcl.s_ospcl.c_inumber; - buf->c_checksum = u_ospcl.s_ospcl.c_checksum; - buf->c_magic = u_ospcl.s_ospcl.c_magic; - buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; - buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; - buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; - buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; - buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; - buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; - buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; - buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; - buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; - buf->c_count = u_ospcl.s_ospcl.c_count; - memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256); - if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || - checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) - return(FAIL); - buf->c_magic = NFS_MAGIC; - -good: - if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) && - (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) { - qcvt.qval = buf->c_dinode.di_size; - if (qcvt.val[0] || qcvt.val[1]) { - printf("Note: Doing Quad swapping\n"); - Qcvt = 1; + if (!Bcvt) { + vprintf(stdout, "Note: Doing Byte swapping\n"); + Bcvt = 1; } } - if (Qcvt) { - qcvt.qval = buf->c_dinode.di_size; - i = qcvt.val[1]; - qcvt.val[1] = qcvt.val[0]; - qcvt.val[0] = i; - buf->c_dinode.di_size = qcvt.qval; + if (checksum((int *)buf) == FAIL) + return (FAIL); + if (Bcvt) { + swabst((u_char *)"8l4s1q8l2q17l", (u_char *)buf); + swabst((u_char *)"l",(u_char *) &buf->c_level); + swabst((u_char *)"2l4q",(u_char *) &buf->c_flags); } readmapflag = 0; @@ -1111,7 +1035,7 @@ good: * Have to patch up missing information in bit map headers */ buf->c_inumber = 0; - buf->c_dinode.di_size = buf->c_count * TP_BSIZE; + buf->c_size = buf->c_count * TP_BSIZE; if (buf->c_count > TP_NINDIR) readmapflag = 1; else @@ -1120,14 +1044,25 @@ good: break; case TS_TAPE: - if ((buf->c_flags & DR_NEWINODEFMT) == 0) - oldinofmt = 1; - /* fall through */ case TS_END: buf->c_inumber = 0; break; case TS_INODE: + /* + * For old dump tapes, have to copy up old fields to + * new locations. + */ + if (buf->c_magic == NFS_MAGIC) { + buf->c_tapea = buf->c_old_tapea; + buf->c_firstrec = buf->c_old_firstrec; + buf->c_date = _time32_to_time(buf->c_old_date); + buf->c_ddate = _time32_to_time(buf->c_old_ddate); + buf->c_atime = _time32_to_time(buf->c_old_atime); + buf->c_mtime = _time32_to_time(buf->c_old_mtime); + } + break; + case TS_ADDR: break; @@ -1135,14 +1070,7 @@ good: panic("gethead: unknown inode type %d\n", buf->c_type); break; } - /* - * If we are restoring a filesystem with old format inodes, - * copy the uid/gid to the new location. - */ - if (oldinofmt) { - buf->c_dinode.di_uid = buf->c_dinode.di_ouid; - buf->c_dinode.di_gid = buf->c_dinode.di_ogid; - } + buf->c_magic = FS_UFS2_MAGIC; tapeaddr = buf->c_tapea; if (dflag) accthdr(buf); @@ -1161,10 +1089,9 @@ accthdr(struct s_spcl *header) long blks, i; if (header->c_type == TS_TAPE) { - fprintf(stderr, "Volume header (%s inode format) ", - oldinofmt ? "old" : "new"); + fprintf(stderr, "Volume header "); if (header->c_firstrec) - fprintf(stderr, "begins with record %ld", + fprintf(stderr, "begins with record %qd", header->c_firstrec); fprintf(stderr, "\n"); previno = 0x7fffffff; @@ -1219,15 +1146,9 @@ findinode(struct s_spcl *header) curfile.name = "<name unknown>"; curfile.action = UNKNOWN; - curfile.dip = NULL; + curfile.mode = 0; curfile.ino = 0; do { - if (header->c_magic != NFS_MAGIC) { - skipcnt++; - while (gethead(header) == FAIL || - _time32_to_time(header->c_date) != dumpdate) - skipcnt++; - } htype = header->c_type; switch (htype) { @@ -1239,12 +1160,21 @@ findinode(struct s_spcl *header) if (header->c_addr[i]) readtape(buf); while (gethead(header) == FAIL || - _time32_to_time(header->c_date) != dumpdate) + _time64_to_time(header->c_date) != dumpdate) skipcnt++; break; case TS_INODE: - curfile.dip = &header->c_dinode; + curfile.mode = header->c_mode; + curfile.uid = header->c_uid; + curfile.gid = header->c_gid; + curfile.file_flags = header->c_file_flags; + curfile.rdev = header->c_rdev; + curfile.atime_sec = header->c_atime; + curfile.atime_nsec = header->c_atimensec; + curfile.mtime_sec = header->c_mtime; + curfile.mtime_nsec = header->c_mtimensec; + curfile.size = header->c_size; curfile.ino = header->c_inumber; break; @@ -1288,7 +1218,7 @@ checksum(int *buf) j = sizeof(union u_spcl) / sizeof(int); i = 0; - if(!Bcvt) { + if (!Bcvt) { do i += *buf++; while (--j); @@ -1346,6 +1276,21 @@ swablong(u_char *sp, int n) return (sp); } +static u_char * +swabquad(u_char *sp, int n) +{ + char c; + + while (--n >= 0) { + c = sp[0]; sp[0] = sp[7]; sp[7] = c; + c = sp[1]; sp[1] = sp[6]; sp[6] = c; + c = sp[2]; sp[2] = sp[5]; sp[5] = c; + c = sp[3]; sp[3] = sp[4]; sp[4] = c; + sp += 8; + } + return (sp); +} + void swabst(u_char *cp, u_char *sp) { @@ -1370,11 +1315,23 @@ swabst(u_char *cp, u_char *sp) sp = swablong(sp, n); break; - default: /* Any other character, like 'b' counts as byte. */ + case 'q': + if (n == 0) + n = 1; + sp = swabquad(sp, n); + break; + + case 'b': if (n == 0) n = 1; sp += n; break; + + default: + fprintf(stderr, "Unknown conversion character: %c\n", + *cp); + done(0); + break; } cp++; n = 0; diff --git a/sbin/tunefs/tunefs.8 b/sbin/tunefs/tunefs.8 index 3480397..424e209 100644 --- a/sbin/tunefs/tunefs.8 +++ b/sbin/tunefs/tunefs.8 @@ -32,7 +32,7 @@ .\" @(#)tunefs.8 8.2 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" -.Dd December 11, 1993 +.Dd May 18, 2002 .Dt TUNEFS 8 .Os .Sh NAME @@ -42,7 +42,6 @@ .Nm .Op Fl A .Op Fl a Ar maxcontig -.Op Fl d Ar rotdelay .Op Fl e Ar maxbpg .Op Fl f Ar avgfilesize .Op Fl m Ar minfree @@ -57,6 +56,13 @@ .Nm Tunefs is designed to change the dynamic parameters of a filesystem which affect the layout policies. +The +.Nm +program cannot be run on an active filesystem. +To change an active filesystem, +you must either downgrade the filesystem to read-only +or unmount it. +.Pp The parameters which are to be changed are indicated by the flags given below: .Bl -tag -width indent @@ -66,19 +72,8 @@ this option will cause all backups to be modified as well as the primary super-block. This is potentially dangerous - use with caution. .It Fl a Ar maxcontig Specify the maximum number of contiguous blocks that will -be laid out before forcing a rotational delay (see -.Fl d -below). -The default value is one, since most device drivers require -an interrupt per disk transfer. -Device drivers that can chain several buffers together in a single -transfer should set this to the maximum chain length. -.It Fl d Ar rotdelay -Specify the expected time (in milliseconds) -to service a transfer completion -interrupt and initiate a new transfer on the same disk. -It is used to decide how much rotational spacing to place between -successive blocks in a file. +be laid out before allowing a rotational delay. +The default value is 16. .It Fl e Ar maxbpg Indicate the maximum number of blocks any single file can allocate out of a cylinder group before it is forced to begin @@ -131,9 +126,11 @@ the percent fragmentation changes on the filesystem. .It Fl p Show a summary of what the current tunable settings are on the selected filesystem. More detailed information can be -obtained in the +obtained from the .Xr dumpfs 8 -manual page. +or +.Xr ffsinfo 8 +programs. .It Fl s Ar avgfpdir Specify the expected number of files per directory. .El @@ -148,6 +145,7 @@ specified mount point. .Sh SEE ALSO .Xr fs 5 , .Xr dumpfs 8 , +.Xr ffsinfo 8 , .Xr newfs 8 .Rs .%A M. McKusick @@ -162,13 +160,8 @@ specified mount point. .%O "(reprinted in the BSD System Manager's Manual, SMM:5)" .Re .Sh BUGS -This program should work on mounted and active filesystems. -Because the super-block is not kept in the buffer cache, -the changes will only take effect if the program -is run on dismounted filesystems. -To change the root filesystem, the system must be rebooted -after the filesystem is tuned. -.\" Take this out and a Unix Demon will dog your steps from now until +This program should work on active filesystems. +.\" Take this out and a Unix Daemon will dog your steps from now until .\" the time_t's wrap around. .Pp You can tune a filesystem, but you can't tune a fish. diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c index b40c8cb..e272446 100644 --- a/sbin/tunefs/tunefs.c +++ b/sbin/tunefs/tunefs.c @@ -53,8 +53,9 @@ static const char rcsid[] = #include <sys/disklabel.h> #include <sys/stat.h> -#include <ufs/ffs/fs.h> #include <ufs/ufs/ufsmount.h> +#include <ufs/ufs/dinode.h> +#include <ufs/ffs/fs.h> #include <err.h> #include <fcntl.h> @@ -77,8 +78,8 @@ union { int fi; long dev_bsize = 1; -void bwrite(daddr_t, const char *, int); -int bread(daddr_t, char *, int); +void bwrite(ufs2_daddr_t, const char *, int); +int bread(ufs2_daddr_t, char *, int); void getsb(struct fs *, const char *); void putsb(struct fs *, const char *, int); void usage(void); @@ -93,9 +94,9 @@ main(argc, argv) const char *name; struct stat st; int Aflag = 0, active = 0; - int aflag = 0, dflag = 0, eflag = 0, fflag = 0, mflag = 0; + int aflag = 0, eflag = 0, fflag = 0, mflag = 0; int nflag = 0, oflag = 0, pflag = 0, sflag = 0; - int avalue = 0, dvalue = 0, evalue = 0, fvalue = 0; + int avalue = 0, evalue = 0, fvalue = 0; int mvalue = 0, ovalue = 0, svalue = 0; char *nvalue = NULL; struct fstab *fs; @@ -108,7 +109,7 @@ main(argc, argv) if (argc < 3) usage(); found_arg = 0; /* at least one arg is required */ - while ((ch = getopt(argc, argv, "Aa:d:e:f:m:n:o:ps:")) != -1) + while ((ch = getopt(argc, argv, "Aa:e:f:m:n:o:ps:")) != -1) switch (ch) { case 'A': found_arg = 1; @@ -122,12 +123,6 @@ main(argc, argv) errx(10, "%s must be >= 1 (was %s)", name, optarg); aflag = 1; break; - case 'd': - found_arg = 1; - name = "rotational delay between contiguous blocks"; - dvalue = atoi(optarg); - dflag = 1; - break; case 'e': found_arg = 1; name = "maximum blocks per file in a cylinder group"; @@ -237,17 +232,6 @@ again: sblock.fs_maxcontig = avalue; } } - if (dflag) { - name = "rotational delay between contiguous blocks"; - if (sblock.fs_rotdelay == dvalue) { - warnx("%s remains unchanged as %dms", name, dvalue); - } - else { - warnx("%s changes from %dms to %dms", - name, sblock.fs_rotdelay, dvalue); - sblock.fs_rotdelay = dvalue; - } - } if (eflag) { name = "maximum blocks per file in a cylinder group"; if (sblock.fs_maxbpg == evalue) { @@ -358,20 +342,36 @@ usage() exit(2); } +/* + * Possible superblock locations ordered from most to least likely. + */ +static int sblock_try[] = SBLOCKSEARCH; +static ufs2_daddr_t sblockloc; + void getsb(fs, file) struct fs *fs; const char *file; { + int i; fi = open(file, O_RDONLY); if (fi < 0) err(3, "cannot open %s", file); - if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) - err(4, "%s: bad super block", file); - if (fs->fs_magic != FS_MAGIC) - errx(5, "%s: bad magic number", file); + for (i = 0; sblock_try[i] != -1; i++) { + if (bread(sblock_try[i], (char *)fs, SBLOCKSIZE)) + err(4, "%s: bad super block", file); + if ((fs->fs_magic == FS_UFS1_MAGIC || + (fs->fs_magic == FS_UFS2_MAGIC && + fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) && + fs->fs_bsize <= MAXBSIZE && + fs->fs_bsize >= sizeof(struct fs)) + break; + } + if (sblock_try[i] == -1) + err(5, "Cannot find filesystem superblock"); dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); + sblockloc = sblock_try[i] / dev_bsize; } void @@ -392,11 +392,11 @@ putsb(fs, file, all) close(i); if (fi < 0) err(3, "cannot open %s", file); - bwrite((daddr_t)SBOFF / dev_bsize, (const char *)fs, SBSIZE); + bwrite(sblockloc, (const char *)fs, SBLOCKSIZE); if (all) for (i = 0; i < fs->fs_ncg; i++) bwrite(fsbtodb(fs, cgsblock(fs, i)), - (const char *)fs, SBSIZE); + (const char *)fs, SBLOCKSIZE); close(fi); } @@ -407,8 +407,6 @@ printfs() (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); warnx("maximum contiguous block count: (-a) %d", sblock.fs_maxcontig); - warnx("rotational delay between contiguous blocks: (-d) %d ms", - sblock.fs_rotdelay); warnx("maximum blocks per file in a cylinder group: (-e) %d", sblock.fs_maxbpg); warnx("average file size: (-f) %d", @@ -429,7 +427,7 @@ printfs() void bwrite(blk, buf, size) - daddr_t blk; + ufs2_daddr_t blk; const char *buf; int size; { @@ -442,7 +440,7 @@ bwrite(blk, buf, size) int bread(bno, buf, cnt) - daddr_t bno; + ufs2_daddr_t bno; char *buf; int cnt; { |