From dffce2150eeac1c7f424324a5cade7a97b308979 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Fri, 26 Jan 2018 00:58:32 +0000 Subject: Refactoring of reading and writing of the UFS/FFS superblock. Specifically reading is done if ffs_sbget() and writing is done in ffs_sbput(). These functions are exported to libufs via the sbget() and sbput() functions which then used in the various filesystem utilities. This work is in preparation for adding subperblock check hashes. No functional change intended. Reviewed by: kib --- sbin/clri/Makefile | 1 + sbin/clri/clri.c | 63 ++++++++++------------ sbin/dump/Makefile | 1 + sbin/dump/dump.h | 1 - sbin/dump/main.c | 29 ++++------ sbin/fsck_ffs/fsck.h | 2 +- sbin/fsck_ffs/fsutil.c | 13 ++--- sbin/fsck_ffs/globs.c | 2 +- sbin/fsck_ffs/setup.c | 72 +++++++++---------------- sbin/fsirand/Makefile | 1 + sbin/fsirand/fsirand.c | 93 ++++---------------------------- sbin/growfs/growfs.c | 123 ++++++++++++++++++------------------------- sbin/newfs/mkfs.c | 75 ++++++++++++-------------- sbin/quotacheck/Makefile | 2 +- sbin/quotacheck/quotacheck.c | 45 +++++++--------- 15 files changed, 188 insertions(+), 335 deletions(-) (limited to 'sbin') diff --git a/sbin/clri/Makefile b/sbin/clri/Makefile index 114f56382a18..5f8777f30391 100644 --- a/sbin/clri/Makefile +++ b/sbin/clri/Makefile @@ -4,6 +4,7 @@ PACKAGE=runtime PROG= clri MAN= clri.8 +LIBADD= ufs WARNS?= 2 .include diff --git a/sbin/clri/clri.c b/sbin/clri/clri.c index 7745aa56d18f..3407297ceb6f 100644 --- a/sbin/clri/clri.c +++ b/sbin/clri/clri.c @@ -54,17 +54,14 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include +#include #include #include #include #include -/* - * Possible superblock locations ordered from most to least likely. - */ -static int sblock_try[] = SBLOCKSEARCH; - static void usage(void) { @@ -75,41 +72,35 @@ usage(void) int main(int argc, char *argv[]) { - struct fs *sbp; + struct fs *fs; struct ufs1_dinode *dp1; struct ufs2_dinode *dp2; char *ibuf[MAXBSIZE]; long generation, bsize; off_t offset; - int i, fd, inonum; - char *fs, sblock[SBLOCKSIZE]; + int fd, ret, inonum; + char *fsname; void *v = ibuf; if (argc < 3) usage(); - fs = *++argv; - sbp = NULL; + fsname = *++argv; /* get the superblock. */ - if ((fd = open(fs, O_RDWR, 0)) < 0) - err(1, "%s", fs); - 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 == sblock_try[i])) && - sbp->fs_bsize <= MAXBSIZE && - sbp->fs_bsize >= (int)sizeof(struct fs)) - break; + if ((fd = open(fsname, O_RDWR, 0)) < 0) + err(1, "%s", fsname); + if ((ret = sbget(fd, &fs, -1)) != 0) { + switch (ret) { + case ENOENT: + warn("Cannot find file system superblock"); + return (1); + default: + warn("Unable to read file system superblock"); + return (1); + } } - if (sblock_try[i] == -1) - errx(2, "cannot find file system superblock"); - bsize = sbp->fs_bsize; + bsize = fs->fs_bsize; /* remaining arguments are inode numbers. */ while (*++argv) { @@ -119,20 +110,20 @@ main(int argc, char *argv[]) (void)printf("clearing %d\n", inonum); /* read in the appropriate block. */ - offset = ino_to_fsba(sbp, inonum); /* inode to fs blk */ - offset = fsbtodb(sbp, offset); /* fs blk disk blk */ + offset = ino_to_fsba(fs, inonum); /* inode to fs blk */ + offset = fsbtodb(fs, offset); /* fs blk disk blk */ offset *= DEV_BSIZE; /* disk blk to bytes */ /* seek and read the block */ if (lseek(fd, offset, SEEK_SET) < 0) - err(1, "%s", fs); + err(1, "%s", fsname); if (read(fd, ibuf, bsize) != bsize) - err(1, "%s", fs); + err(1, "%s", fsname); - if (sbp->fs_magic == FS_UFS2_MAGIC) { + if (fs->fs_magic == FS_UFS2_MAGIC) { /* get the inode within the block. */ dp2 = &(((struct ufs2_dinode *)v) - [ino_to_fsbo(sbp, inonum)]); + [ino_to_fsbo(fs, inonum)]); /* clear the inode, and bump the generation count. */ generation = dp2->di_gen + 1; @@ -141,7 +132,7 @@ main(int argc, char *argv[]) } else { /* get the inode within the block. */ dp1 = &(((struct ufs1_dinode *)v) - [ino_to_fsbo(sbp, inonum)]); + [ino_to_fsbo(fs, inonum)]); /* clear the inode, and bump the generation count. */ generation = dp1->di_gen + 1; @@ -151,9 +142,9 @@ main(int argc, char *argv[]) /* backup and write the block */ if (lseek(fd, (off_t)-bsize, SEEK_CUR) < 0) - err(1, "%s", fs); + err(1, "%s", fsname); if (write(fd, ibuf, bsize) != bsize) - err(1, "%s", fs); + err(1, "%s", fsname); (void)fsync(fd); } (void)close(fd); diff --git a/sbin/dump/Makefile b/sbin/dump/Makefile index 7c89570292db..c7feae765ebb 100644 --- a/sbin/dump/Makefile +++ b/sbin/dump/Makefile @@ -19,6 +19,7 @@ LINKS= ${BINDIR}/dump ${BINDIR}/rdump CFLAGS+=-DRDUMP SRCS= itime.c main.c optr.c dumprmt.c tape.c traverse.c unctime.c cache.c MAN= dump.8 +LIBADD= ufs MLINKS= dump.8 rdump.8 WARNS?= 2 diff --git a/sbin/dump/dump.h b/sbin/dump/dump.h index 7aeb3a90d73f..7119df41b42b 100644 --- a/sbin/dump/dump.h +++ b/sbin/dump/dump.h @@ -86,7 +86,6 @@ time_t tstart_writing; /* when started writing the first tape block */ time_t tend_writing; /* after writing the last tape block */ int passno; /* current dump pass number */ struct fs *sblock; /* the file system super block */ -char sblock_buf[MAXBSIZE]; long dev_bsize; /* block size of underlying disk device */ int dev_bshift; /* log2(dev_bsize) */ int tp_bshift; /* log2(TP_BSIZE) */ diff --git a/sbin/dump/main.c b/sbin/dump/main.c index 167812bce7d5..127b5ca33f97 100644 --- a/sbin/dump/main.c +++ b/sbin/dump/main.c @@ -59,6 +59,7 @@ static const char rcsid[] = #include #include #include +#include #include #include #include @@ -84,11 +85,6 @@ 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 char *getmntpt(char *, int *); static long numarg(const char *, long, long); static void obsolete(int *, char **[]); @@ -104,7 +100,7 @@ main(int argc, char *argv[]) struct fstab *dt; char *map, *mntpt; int ch, mode, mntflags; - int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1; + int i, ret, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1; int just_estimate = 0; ino_t maxino; char *tmsg; @@ -437,19 +433,16 @@ main(int argc, char *argv[]) msgtail("to %s\n", tape); sync(); - sblock = (struct fs *)sblock_buf; - for (i = 0; sblock_try[i] != -1; i++) { - sblock->fs_fsize = SBLOCKSIZE; /* needed in blkread */ - blkread(sblock_try[i]>>dev_bshift, (char *) sblock, SBLOCKSIZE); - if ((sblock->fs_magic == FS_UFS1_MAGIC || - (sblock->fs_magic == FS_UFS2_MAGIC && - sblock->fs_sblockloc == sblock_try[i])) && - sblock->fs_bsize <= MAXBSIZE && - sblock->fs_bsize >= sizeof(struct fs)) - break; + if ((ret = sbget(diskfd, &sblock, -1)) != 0) { + switch (ret) { + case ENOENT: + warn("Cannot find file system superblock"); + return (1); + default: + warn("Unable to read file system superblock"); + return (1); + } } - if (sblock_try[i] == -1) - quit("Cannot find file system superblock\n"); dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1); dev_bshift = ffs(dev_bsize) - 1; if (dev_bsize != (1 << dev_bshift)) diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 83c559aa16a1..56f01501022a 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -308,7 +308,7 @@ extern u_int real_dev_bsize; /* actual disk sector size, not overridden */ extern char nflag; /* assume a no response */ extern char yflag; /* assume a yes response */ extern int bkgrdflag; /* use a snapshot to run on an active system */ -extern ufs2_daddr_t bflag; /* location of alternate super block */ +extern off_t bflag; /* location of alternate super block */ extern int debug; /* output debugging info */ extern int Eflag; /* delete empty data blocks */ extern int Zflag; /* zero empty data blocks */ diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index 69c92d7f35c9..d4a5f81bbfa7 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -348,7 +348,6 @@ getblk(struct bufarea *bp, ufs2_daddr_t blk, long size) void flush(int fd, struct bufarea *bp) { - int i, j; if (!bp->b_dirty) return; @@ -370,14 +369,8 @@ flush(int fd, struct bufarea *bp) if (bp != &sblk) pfatal("BUFFER %p DOES NOT MATCH SBLK %p\n", bp, &sblk); - blwrite(fd, bp->b_un.b_buf, bp->b_bno, bp->b_size); - for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, - j++) { - blwrite(fswritefd, (char *)sblock.fs_csp + i, - fsbtodb(&sblock, - sblock.fs_csaddr + j * sblock.fs_frag), - MIN(sblock.fs_cssize - i, sblock.fs_bsize)); - } + if (sbput(fd, (struct fs *)bp->b_un.b_buf, 0) == 0) + fsmodified = 1; break; case BT_CYLGRP: if (cgput(&disk, (struct cg *)bp->b_un.b_buf) == 0) @@ -439,6 +432,8 @@ ckfini(int markclean) if (havesb && cursnapshot == 0 && sblock.fs_magic == FS_UFS2_MAGIC && sblk.b_bno != sblock.fs_sblockloc / dev_bsize && !preen && reply("UPDATE STANDARD SUPERBLOCK")) { + /* Change the write destination to standard superblock */ + sblock.fs_sblockactualloc = sblock.fs_sblockloc; sblk.b_bno = sblock.fs_sblockloc / dev_bsize; sbdirty(); flush(fswritefd, &sblk); diff --git a/sbin/fsck_ffs/globs.c b/sbin/fsck_ffs/globs.c index f3522973404e..6ce7dfd032c4 100644 --- a/sbin/fsck_ffs/globs.c +++ b/sbin/fsck_ffs/globs.c @@ -80,7 +80,7 @@ u_int real_dev_bsize; /* actual disk sector size, not overridden */ char nflag; /* assume a no response */ char yflag; /* assume a yes response */ int bkgrdflag; /* use a snapshot to run on an active system */ -ufs2_daddr_t bflag; /* location of alternate super block */ +off_t bflag; /* location of alternate super block */ int debug; /* output debugging info */ int Eflag; /* delete empty data blocks */ int Zflag; /* zero empty data blocks */ diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c index c1e8d45e21db..0cc943797c10 100644 --- a/sbin/fsck_ffs/setup.c +++ b/sbin/fsck_ffs/setup.c @@ -310,71 +310,49 @@ badsb: return (0); } -/* - * Possible superblock locations ordered from most to least likely. - */ -static int sblock_try[] = SBLOCKSEARCH; - -#define BAD_MAGIC_MSG \ -"The previous newfs operation on this volume did not complete.\n" \ -"You must complete newfs before mounting this volume.\n" - /* * Read in the super block and its summary info. */ int readsb(int listerr) { - ufs2_daddr_t super; - int i, bad; + off_t super; + int bad, ret; + struct fs *fs; - if (bflag) { - super = bflag; - readcnt[sblk.b_type]++; - if ((blread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE))) - return (0); - if (sblock.fs_magic == FS_BAD_MAGIC) { - fprintf(stderr, BAD_MAGIC_MSG); + super = bflag ? bflag * dev_bsize : -1; + readcnt[sblk.b_type]++; + if ((ret = sbget(fsreadfd, &fs, super)) != 0) { + switch (ret) { + case EINVAL: + fprintf(stderr, "The previous newfs operation " + "on this volume did not complete.\nYou must " + "complete newfs before using this volume.\n"); exit(11); - } - if (sblock.fs_magic != FS_UFS1_MAGIC && - sblock.fs_magic != FS_UFS2_MAGIC) { - fprintf(stderr, "%jd is not a file system superblock\n", - bflag); + case ENOENT: + if (bflag) + fprintf(stderr, "%jd is not a file system " + "superblock\n", super / dev_bsize); + else + fprintf(stderr, "Cannot find file system " + "superblock\n"); return (0); - } - } else { - for (i = 0; sblock_try[i] != -1; i++) { - super = sblock_try[i] / dev_bsize; - readcnt[sblk.b_type]++; - if ((blread(fsreadfd, (char *)&sblock, super, - (long)SBLOCKSIZE))) - return (0); - if (sblock.fs_magic == FS_BAD_MAGIC) { - fprintf(stderr, BAD_MAGIC_MSG); - exit(11); - } - if ((sblock.fs_magic == FS_UFS1_MAGIC || - (sblock.fs_magic == FS_UFS2_MAGIC && - sblock.fs_sblockloc == sblock_try[i])) && - sblock.fs_ncg >= 1 && - sblock.fs_bsize >= MINBSIZE && - sblock.fs_sbsize >= roundup(sizeof(struct fs), dev_bsize)) - break; - } - if (sblock_try[i] == -1) { - fprintf(stderr, "Cannot find file system superblock\n"); + case EIO: + default: + fprintf(stderr, "I/O error reading %jd\n", + super / dev_bsize); return (0); } } + memcpy(&sblock, fs, fs->fs_sbsize); + free(fs); /* * Compute block size that the file system is based on, * according to fsbtodb, and adjust superblock block number * so we can tell if this is an alternate later. */ - super *= dev_bsize; dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); - sblk.b_bno = super / dev_bsize; + sblk.b_bno = sblock.fs_sblockactualloc / dev_bsize; sblk.b_size = SBLOCKSIZE; /* * Compare all fields that should not differ in alternate super block. diff --git a/sbin/fsirand/Makefile b/sbin/fsirand/Makefile index c415b11983f1..1fc54ff44687 100644 --- a/sbin/fsirand/Makefile +++ b/sbin/fsirand/Makefile @@ -4,6 +4,7 @@ PACKAGE=runtime PROG= fsirand MAN= fsirand.8 +LIBADD= ufs WARNS?= 3 .include diff --git a/sbin/fsirand/fsirand.c b/sbin/fsirand/fsirand.c index 6b1b1371e17b..bb0f27a59301 100644 --- a/sbin/fsirand/fsirand.c +++ b/sbin/fsirand/fsirand.c @@ -46,6 +46,7 @@ static const char rcsid[] = #include #include #include +#include #include #include #include @@ -56,11 +57,6 @@ 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; - static int printonly = 0, force = 0, ignorelabel = 0; int @@ -117,9 +113,8 @@ fsirand(char *device) ssize_t ibufsize; struct fs *sblock; ino_t inumber; - ufs2_daddr_t sblockloc, dblk; - char sbuf[SBLOCKSIZE], sbuftmp[SBLOCKSIZE]; - int i, devfd, n, cg; + ufs2_daddr_t dblk; + int devfd, n, cg, ret; u_int32_t bsize = DEV_BSIZE; if ((devfd = open(device, printonly ? O_RDONLY : O_RDWR)) < 0) { @@ -131,30 +126,15 @@ fsirand(char *device) dp2 = NULL; /* Read in master superblock */ - (void)memset(&sbuf, 0, sizeof(sbuf)); - sblock = (struct fs *)&sbuf; - 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 (%jd) on %s", - (intmax_t)sblockloc, device); + if ((ret = sbget(devfd, &sblock, -1)) != 0) { + switch (ret) { + case ENOENT: + warn("Cannot find file system superblock"); 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)); + default: + warn("Unable to read file system superblock"); return (1); } - if ((sblock->fs_magic == FS_UFS1_MAGIC || - (sblock->fs_magic == FS_UFS2_MAGIC && - sblock->fs_sblockloc == sblock_try[i])) && - sblock->fs_bsize <= MAXBSIZE && - sblock->fs_bsize >= (ssize_t)sizeof(struct fs)) - break; - } - if (sblock_try[i] == -1) { - fprintf(stderr, "Cannot find file system superblock\n"); - return (1); } if (sblock->fs_magic == FS_UFS1_MAGIC && @@ -167,33 +147,6 @@ fsirand(char *device) return (1); } - /* Make sure backup superblocks are sane. */ - sblock = (struct fs *)&sbuftmp; - for (cg = 0; cg < (int)sblock->fs_ncg; cg++) { - dblk = fsbtodb(sblock, cgsblock(sblock, cg)); - if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) { - warn("can't seek to %jd", (intmax_t)dblk * bsize); - return (1); - } else if ((n = write(devfd, (void *)sblock, SBLOCKSIZE)) != SBLOCKSIZE) { - warn("can't read backup superblock %d on %s: %s", - cg + 1, device, (n < SBLOCKSIZE) ? "short write" - : strerror(errno)); - return (1); - } - 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 > SBLOCKSIZE) { - warnx("size of backup superblock %d on %s is preposterous", - cg + 1, device); - return (1); - } - } - sblock = (struct fs *)&sbuf; - /* XXX - should really cap buffer at 512kb or so */ if (sblock->fs_magic == FS_UFS1_MAGIC) ibufsize = sizeof(struct ufs1_dinode) * sblock->fs_ipg; @@ -215,38 +168,14 @@ fsirand(char *device) /* 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, sblockloc, SEEK_SET) == -1) { - warn("can't seek to superblock (%jd) on %s", - (intmax_t)sblockloc, device); - return (1); - } - if ((n = write(devfd, (void *)sblock, SBLOCKSIZE)) != - SBLOCKSIZE) { - warn("can't write superblock on %s: %s", device, - (n < SBLOCKSIZE) ? "short write" : strerror(errno)); + if (sbput(devfd, sblock, sblock->fs_ncg) != 0) { + warn("could not write updated superblock"); return (1); } } /* For each cylinder group, randomize inodes and update backup sblock */ for (cg = 0, inumber = 0; cg < (int)sblock->fs_ncg; cg++) { - /* Update superblock if appropriate */ - if (!printonly) { - dblk = fsbtodb(sblock, cgsblock(sblock, cg)); - if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) { - warn("can't seek to %jd", - (intmax_t)dblk * bsize); - return (1); - } 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); - } - } - /* Read in inodes, then print or randomize generation nums */ dblk = fsbtodb(sblock, ino_to_fsba(sblock, inumber)); if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) { diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c index 7670317caae7..61f90de7ea68 100644 --- a/sbin/growfs/growfs.c +++ b/sbin/growfs/growfs.c @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -95,12 +96,6 @@ static union { #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]; @@ -156,11 +151,10 @@ growfs(int fsi, int fso, unsigned int Nflag) fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize); if (fscs == NULL) errx(1, "calloc failed"); - for (i = 0; i < osblock.fs_cssize; i += osblock.fs_bsize) { - rdfs(fsbtodb(&osblock, osblock.fs_csaddr + - numfrags(&osblock, i)), (size_t)MIN(osblock.fs_cssize - i, - osblock.fs_bsize), (void *)(((char *)fscs) + i), fsi); - } + memcpy(fscs, osblock.fs_csp, osblock.fs_cssize); + free(osblock.fs_csp); + osblock.fs_csp = NULL; + sblock.fs_csp = fscs; #ifdef FS_DEBUG { @@ -234,50 +228,8 @@ growfs(int fsi, int fso, unsigned int Nflag) updcsloc(modtime, fsi, fso, Nflag); /* - * Now write the cylinder summary back to disk. - */ - for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) { - wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), - (size_t)MIN(sblock.fs_cssize - i, sblock.fs_bsize), - (void *)(((char *)fscs) + i), fso, Nflag); - } - DBG_PRINT0("fscs written\n"); - -#ifdef FS_DEBUG - { - struct csum *dbg_csp; - u_int32_t dbg_csc; - char dbg_line[80]; - - dbg_csp = fscs; - for (dbg_csc = 0; dbg_csc < sblock.fs_ncg; dbg_csc++) { - snprintf(dbg_line, sizeof(dbg_line), - "%d. new csum in new location", dbg_csc); - DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++); - } - } -#endif /* FS_DEBUG */ - - /* - * Now write the new superblock back to disk. - */ - sblock.fs_time = modtime; - wtfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag); - DBG_PRINT0("sblock written\n"); - DBG_DUMP_FS(&sblock, "new initial sblock"); - - /* - * Clean up the dynamic fields in our superblock copies. - */ - sblock.fs_fmod = 0; - sblock.fs_clean = 1; - sblock.fs_ronly = 0; - sblock.fs_cgrotor = 0; - sblock.fs_state = 0; - memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt)); - sblock.fs_flags &= FS_DOSOFTDEP; - - /* + * Clean up the dynamic fields in our superblock. + * * XXX * The following fields are currently distributed from the superblock * to the copies: @@ -287,7 +239,7 @@ growfs(int fsi, int fso, unsigned int Nflag) * fs_maxbpg * fs_minfree, * fs_optim - * fs_flags regarding SOFTPDATES + * fs_flags * * We probably should rather change the summary for the cylinder group * statistics here to the value of what would be in there, if the file @@ -297,14 +249,40 @@ growfs(int fsi, int fso, unsigned int Nflag) * "diffed" stats between the old and new superblock by still copying * certain parameters onto that. */ + sblock.fs_time = modtime; + sblock.fs_fmod = 0; + sblock.fs_clean = 1; + sblock.fs_ronly = 0; + sblock.fs_cgrotor = 0; + sblock.fs_state = 0; + memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt)); /* - * Write out the duplicate super blocks. + * Now write the new superblock, its summary information, + * and all the alternates back to disk. */ - for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { - wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), - (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag); + if (!Nflag && sbput(fso, &sblock, sblock.fs_ncg) != 0) + errc(2, EIO, "could not write updated superblock"); + DBG_PRINT0("fscs written\n"); + +#ifdef FS_DEBUG + { + struct csum *dbg_csp; + u_int32_t dbg_csc; + char dbg_line[80]; + + dbg_csp = fscs; + for (dbg_csc = 0; dbg_csc < sblock.fs_ncg; dbg_csc++) { + snprintf(dbg_line, sizeof(dbg_line), + "%d. new csum in new location", dbg_csc); + DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++); + } } +#endif /* FS_DEBUG */ + + DBG_PRINT0("sblock written\n"); + DBG_DUMP_FS(&sblock, "new initial sblock"); + DBG_PRINT0("sblock copies written\n"); DBG_DUMP_FS(&sblock, "new other sblocks"); @@ -1374,11 +1352,12 @@ int main(int argc, char **argv) { DBG_FUNC("main") + struct fs *fs; const char *device; const struct statfs *statfsp; uint64_t size = 0; off_t mediasize; - int error, i, j, fsi, fso, ch, Nflag = 0, yflag = 0; + int error, j, fsi, fso, ch, ret, Nflag = 0, yflag = 0; char *p, reply[5], oldsizebuf[6], newsizebuf[6]; void *testbuf; @@ -1452,19 +1431,17 @@ main(int argc, char **argv) /* * Read the current superblock, and take a backup. */ - 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 == sblock_try[i])) && - osblock.fs_bsize <= MAXBSIZE && - osblock.fs_bsize >= (int32_t) sizeof(struct fs)) - break; + if ((ret = sbget(fsi, &fs, -1)) != 0) { + switch (ret) { + case ENOENT: + errx(1, "superblock not recognized"); + default: + errc(1, ret, "unable to read superblock"); + } } - if (sblock_try[i] == -1) - errx(1, "superblock not recognized"); - memcpy((void *)&fsun1, (void *)&fsun2, sizeof(fsun2)); + memcpy(&osblock, fs, fs->fs_sbsize); + free(fs); + memcpy((void *)&fsun1, (void *)&fsun2, osblock.fs_sbsize); DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */ DBG_DUMP_FS(&sblock, "old sblock"); diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c index e6aab91c2fd1..c381134bee6d 100644 --- a/sbin/newfs/mkfs.c +++ b/sbin/newfs/mkfs.c @@ -104,15 +104,6 @@ static void wtfs(ufs2_daddr_t, int, char *); static void cgckhash(struct cg *); static u_int32_t newfs_random(void); -static int -do_sbwrite(struct uufsd *disk) -{ - if (!disk->d_sblock) - disk->d_sblock = disk->d_fs.fs_sblockloc / disk->d_bsize; - return (pwrite(disk->d_fd, &disk->d_fs, SBLOCKSIZE, (off_t)((part_ofs + - disk->d_sblock) * disk->d_bsize))); -} - void mkfs(struct partition *pp, char *fsys) { @@ -277,6 +268,7 @@ restart: if (Oflag == 1) { sblock.fs_sblockloc = SBLOCK_UFS1; + sblock.fs_sblockactualloc = 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 = ((UFS_NDADDR + UFS_NIADDR) * @@ -296,6 +288,7 @@ restart: sblock.fs_old_nrpos = 1; } else { sblock.fs_sblockloc = SBLOCK_UFS2; + sblock.fs_sblockactualloc = 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 = ((UFS_NDADDR + UFS_NIADDR) * @@ -544,7 +537,7 @@ restart: } } if (!Nflag) - do_sbwrite(&disk); + sbput(disk.d_fd, &disk.d_fs, 0); if (Xflag == 1) { printf("** Exiting on Xflag 1\n"); exit(0); @@ -562,24 +555,20 @@ restart: i = 0; width = charsperline(); /* - * allocate space for superblock, cylinder group map, and + * Allocate space for cylinder group map and * two sets of inode blocks. */ - if (sblock.fs_bsize < SBLOCKSIZE) - iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize; - else - iobufsize = 4 * sblock.fs_bsize; + iobufsize = 3 * sblock.fs_bsize; if ((iobuf = calloc(1, iobufsize)) == 0) { printf("Cannot allocate I/O buffer\n"); exit(38); } /* - * Make a copy of the superblock into the buffer that we will be - * writing out in each cylinder group. + * Write out all the cylinder groups and backup superblocks. */ - bcopy((char *)&sblock, iobuf, SBLOCKSIZE); for (cg = 0; cg < sblock.fs_ncg; cg++) { - initcg(cg, utime); + if (!Nflag) + initcg(cg, utime); j = snprintf(tmpbuf, sizeof(tmpbuf), " %jd%s", (intmax_t)fsbtodb(&sblock, cgsblock(&sblock, cg)), cg < (sblock.fs_ncg-1) ? "," : ""); @@ -611,24 +600,22 @@ restart: printf("** Exiting on Xflag 3\n"); exit(0); } - if (!Nflag) { - do_sbwrite(&disk); - /* - * For UFS1 filesystems with a blocksize of 64K, the first - * alternate superblock resides at the location used for - * the default UFS2 superblock. As there is a valid - * superblock at this location, the boot code will use - * it as its first choice. Thus we have to ensure that - * all of its statistcs on usage are correct. - */ - if (Oflag == 1 && sblock.fs_bsize == 65536) - wtfs(fsbtodb(&sblock, cgsblock(&sblock, 0)), - sblock.fs_bsize, (char *)&sblock); - } - for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) - wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), - MIN(sblock.fs_cssize - i, sblock.fs_bsize), - ((char *)fscs) + i); + /* + * Reference the summary information so it will also be written. + */ + sblock.fs_csp = fscs; + sbput(disk.d_fd, &disk.d_fs, 0); + /* + * For UFS1 filesystems with a blocksize of 64K, the first + * alternate superblock resides at the location used for + * the default UFS2 superblock. As there is a valid + * superblock at this location, the boot code will use + * it as its first choice. Thus we have to ensure that + * all of its statistcs on usage are correct. + */ + if (Oflag == 1 && sblock.fs_bsize == 65536) + wtfs(fsbtodb(&sblock, cgsblock(&sblock, 0)), + sblock.fs_bsize, (char *)&sblock); /* * Read the last sector of the boot block, replace the last * 20 bytes with the recovery information, then write it back. @@ -669,6 +656,7 @@ void initcg(int cylno, time_t utime) { long blkno, start; + off_t savedactualloc; uint i, j, d, dlower, dupper; ufs2_daddr_t cbase, dmax; struct ufs1_dinode *dp1; @@ -802,10 +790,15 @@ initcg(int cylno, time_t utime) *cs = acg.cg_cs; cgckhash(&acg); /* - * Write out the duplicate super block, the cylinder group map - * and two blocks worth of inodes in a single write. + * Write out the duplicate super block. Then write the cylinder + * group map and two blocks worth of inodes in a single write. */ - start = MAX(sblock.fs_bsize, SBLOCKSIZE); + savedactualloc = sblock.fs_sblockactualloc; + sblock.fs_sblockactualloc = + dbtob(fsbtodb(&sblock, cgsblock(&sblock, cylno))); + sbput(disk.d_fd, &disk.d_fs, 0); + sblock.fs_sblockactualloc = savedactualloc; + start = 0; bcopy((char *)&acg, &iobuf[start], sblock.fs_cgsize); start += sblock.fs_bsize; dp1 = (struct ufs1_dinode *)(&iobuf[start]); @@ -819,7 +812,7 @@ initcg(int cylno, time_t utime) dp2++; } } - wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf); + wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), iobufsize, iobuf); /* * For the old file system, we have to initialize all the inodes. */ diff --git a/sbin/quotacheck/Makefile b/sbin/quotacheck/Makefile index 6adcf7a5f572..1e02b4486f9d 100644 --- a/sbin/quotacheck/Makefile +++ b/sbin/quotacheck/Makefile @@ -6,7 +6,7 @@ PROG= quotacheck SRCS= quotacheck.c preen.c fsutil.c utilities.c WARNS?= 2 MAN= quotacheck.8 -LIBADD= util +LIBADD= util ufs .PATH: ${.CURDIR:H}/fsck ${.CURDIR:H}/fsck_ffs diff --git a/sbin/quotacheck/quotacheck.c b/sbin/quotacheck/quotacheck.c index c7582b09dc53..7071aaf9dea5 100644 --- a/sbin/quotacheck/quotacheck.c +++ b/sbin/quotacheck/quotacheck.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -121,7 +122,7 @@ int fi; /* open disk file descriptor */ struct fileusage * addid(u_long, int, char *, const char *); -void bread(ufs2_daddr_t, char *, long); +void blkread(ufs2_daddr_t, char *, long); void freeinodebuf(void); union dinode * getnextinode(ino_t); @@ -243,11 +244,6 @@ usage(void) exit(1); } -/* - * Possible superblock locations ordered from most to least likely. - */ -static int sblock_try[] = SBLOCKSEARCH; - /* * Scan the specified file system to check quota(s) present on it. */ @@ -256,7 +252,8 @@ chkquota(char *specname, struct quotafile *qfu, struct quotafile *qfg) { struct fileusage *fup; union dinode *dp; - int cg, i, mode, errs = 0; + struct fs *fs; + int cg, i, ret, mode, errs = 0; ino_t ino, inosused, userino = 0, groupino = 0; dev_t dev, userdev = 0, groupdev = 0; struct stat sb; @@ -323,26 +320,24 @@ chkquota(char *specname, struct quotafile *qfu, struct quotafile *qfg) } } sync(); - dev_bsize = 1; - 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 == sblock_try[i])) && - sblock.fs_bsize <= MAXBSIZE && - sblock.fs_bsize >= sizeof(struct fs)) - break; - } - if (sblock_try[i] == -1) { - warn("Cannot find file system superblock"); - return (1); + if ((ret = sbget(fi, &fs, -1)) != 0) { + switch (ret) { + case ENOENT: + warn("Cannot find file system superblock"); + return (1); + default: + warn("Unable to read file system superblock"); + return (1); + } } + bcopy(fs, &sblock, fs->fs_sbsize); + free(fs); dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); maxino = sblock.fs_ncg * sblock.fs_ipg; for (cg = 0; cg < sblock.fs_ncg; cg++) { ino = cg * sblock.fs_ipg; setinodebuf(ino); - bread(fsbtodb(&sblock, cgtod(&sblock, cg)), (char *)(&cgblk), + blkread(fsbtodb(&sblock, cgtod(&sblock, cg)), (char *)(&cgblk), sblock.fs_cgsize); if (sblock.fs_magic == FS_UFS2_MAGIC) inosused = cgblk.cg_initediblk; @@ -618,10 +613,10 @@ getnextinode(ino_t inumber) lastinum += fullcnt; } /* - * If bread returns an error, it will already have zeroed + * If blkread returns an error, it will already have zeroed * out the buffer, so we do not need to do so here. */ - bread(dblk, inodebuf, size); + blkread(dblk, inodebuf, size); nextinop = inodebuf; } dp = (union dinode *)nextinop; @@ -680,12 +675,12 @@ freeinodebuf(void) * Read specified disk blocks. */ void -bread(ufs2_daddr_t bno, char *buf, long cnt) +blkread(ufs2_daddr_t bno, char *buf, long cnt) { if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0 || read(fi, buf, cnt) != cnt) - errx(1, "bread failed on block %ld", (long)bno); + errx(1, "blkread failed on block %ld", (long)bno); } /* -- cgit v1.2.3