aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libufs/Makefile2
-rw-r--r--lib/libufs/libufs.h27
-rw-r--r--lib/libufs/sblock.c211
-rw-r--r--lib/libufs/sbread.388
-rw-r--r--sbin/clri/Makefile1
-rw-r--r--sbin/clri/clri.c63
-rw-r--r--sbin/dump/Makefile1
-rw-r--r--sbin/dump/dump.h1
-rw-r--r--sbin/dump/main.c29
-rw-r--r--sbin/fsck_ffs/fsck.h2
-rw-r--r--sbin/fsck_ffs/fsutil.c13
-rw-r--r--sbin/fsck_ffs/globs.c2
-rw-r--r--sbin/fsck_ffs/setup.c72
-rw-r--r--sbin/fsirand/Makefile1
-rw-r--r--sbin/fsirand/fsirand.c93
-rw-r--r--sbin/growfs/growfs.c123
-rw-r--r--sbin/newfs/mkfs.c75
-rw-r--r--sbin/quotacheck/Makefile2
-rw-r--r--sbin/quotacheck/quotacheck.c45
-rw-r--r--stand/libsa/Makefile4
-rw-r--r--stand/libsa/ufs.c55
-rw-r--r--sys/geom/geom.h2
-rw-r--r--sys/geom/geom_io.c33
-rw-r--r--sys/geom/journal/g_journal_ufs.c44
-rw-r--r--sys/geom/label/g_label_ufs.c126
-rw-r--r--sys/ufs/ffs/ffs_extern.h11
-rw-r--r--sys/ufs/ffs/ffs_subr.c186
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c215
-rw-r--r--sys/ufs/ffs/fs.h3
-rw-r--r--usr.sbin/fstyp/Makefile2
-rw-r--r--usr.sbin/fstyp/ufs.c71
-rw-r--r--usr.sbin/quot/Makefile1
-rw-r--r--usr.sbin/quot/quot.c37
33 files changed, 851 insertions, 790 deletions
diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile
index d24526e829c1..16487bebc957 100644
--- a/lib/libufs/Makefile
+++ b/lib/libufs/Makefile
@@ -17,6 +17,8 @@ MLINKS+= cgread.3 cgwrite.3
MLINKS+= cgread.3 cgwrite1.3
MLINKS+= cgread.3 cgput.3
MLINKS+= sbread.3 sbwrite.3
+MLINKS+= sbread.3 sbget.3
+MLINKS+= sbread.3 sbput.3
MLINKS+= ufs_disk_close.3 ufs_disk_fillout.3
MLINKS+= ufs_disk_close.3 ufs_disk_fillout_blank.3
MLINKS+= ufs_disk_close.3 ufs_disk_write.3
diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h
index 400704596148..4598a9999ce2 100644
--- a/lib/libufs/libufs.h
+++ b/lib/libufs/libufs.h
@@ -99,6 +99,20 @@ __BEGIN_DECLS
*/
/*
+ * ffs_subr.c
+ */
+void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t);
+void ffs_clusteracct(struct fs *, struct cg *, ufs1_daddr_t, int);
+void ffs_fragacct(struct fs *, int, int32_t [], int);
+int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
+int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
+void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
+int ffs_sbget(void *, struct fs **, off_t, char *,
+ int (*)(void *, off_t, void **, int));
+int ffs_sbput(void *, struct fs *, off_t,
+ int (*)(void *, off_t, void *, int));
+
+/*
* block.c
*/
ssize_t bread(struct uufsd *, ufs2_daddr_t, void *, size_t);
@@ -129,6 +143,9 @@ int putino(struct uufsd *);
*/
int sbread(struct uufsd *);
int sbwrite(struct uufsd *, int);
+/* low level superblock read/write functions */
+int sbget(int, struct fs **, off_t);
+int sbput(int, struct fs *, int);
/*
* type.c
@@ -139,16 +156,6 @@ int ufs_disk_fillout_blank(struct uufsd *, const char *);
int ufs_disk_write(struct uufsd *);
/*
- * ffs_subr.c
- */
-void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t);
-void ffs_clusteracct(struct fs *, struct cg *, ufs1_daddr_t, int);
-void ffs_fragacct(struct fs *, int, int32_t [], int);
-int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
-int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
-void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
-
-/*
* crc32c.c
*/
uint32_t calculate_crc32c(uint32_t, const void *, size_t);
diff --git a/lib/libufs/sblock.c b/lib/libufs/sblock.c
index 06cf97d51581..5242a6db88db 100644
--- a/lib/libufs/sblock.c
+++ b/lib/libufs/sblock.c
@@ -47,79 +47,48 @@ __FBSDID("$FreeBSD$");
#include <libufs.h>
-static int superblocks[] = SBLOCKSEARCH;
-
int
sbread(struct uufsd *disk)
{
- uint8_t block[MAXBSIZE];
struct fs *fs;
- int sb, superblock;
- int i, size, blks;
- uint8_t *space;
ERROR(disk, NULL);
- fs = &disk->d_fs;
- superblock = superblocks[0];
-
- for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) {
- if (bread(disk, superblock, disk->d_sb, SBLOCKSIZE) == -1) {
+ if ((errno = sbget(disk->d_fd, &fs, -1)) != 0) {
+ switch (errno) {
+ case EIO:
ERROR(disk, "non-existent or truncated superblock");
- return (-1);
- }
- if (fs->fs_magic == FS_UFS1_MAGIC)
- disk->d_ufs = 1;
- if (fs->fs_magic == FS_UFS2_MAGIC &&
- fs->fs_sblockloc == superblock)
- disk->d_ufs = 2;
- if (fs->fs_bsize <= MAXBSIZE &&
- (size_t)fs->fs_bsize >= sizeof(*fs)) {
- if (disk->d_ufs)
- break;
+ break;
+ case ENOENT:
+ ERROR(disk, "no usable known superblock found");
+ break;
+ case ENOSPC:
+ ERROR(disk, "failed to allocate space for superblock "
+ "information");
+ break;
+ case EINVAL:
+ ERROR(disk, "The previous newfs operation on this "
+ "volume did not complete.\nYou must complete "
+ "newfs before using this volume.");
+ break;
+ default:
+ ERROR(disk, "unknown superblock read error");
+ errno = EIO;
+ break;
}
disk->d_ufs = 0;
- }
- if (superblock == -1 || disk->d_ufs == 0) {
- /*
- * Other error cases will result in errno being set, here we
- * must set it to indicate no superblock could be found with
- * which to associate this disk/filesystem.
- */
- ERROR(disk, "no usable known superblock found");
- errno = ENOENT;
return (-1);
}
+ memcpy(&disk->d_fs, fs, fs->fs_sbsize);
+ free(fs);
+ fs = &disk->d_fs;
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ disk->d_ufs = 1;
+ if (fs->fs_magic == FS_UFS2_MAGIC)
+ disk->d_ufs = 2;
disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1);
- disk->d_sblock = superblock / disk->d_bsize;
- /*
- * Read in the superblock summary information.
- */
- size = fs->fs_cssize;
- blks = howmany(size, fs->fs_fsize);
- size += fs->fs_ncg * sizeof(int32_t);
- space = malloc(size);
- if (space == NULL) {
- ERROR(disk, "failed to allocate space for summary information");
- return (-1);
- }
- fs->fs_csp = (struct csum *)space;
- for (i = 0; i < blks; i += fs->fs_frag) {
- size = fs->fs_bsize;
- if (i + fs->fs_frag > blks)
- size = (blks - i) * fs->fs_fsize;
- if (bread(disk, fsbtodb(fs, fs->fs_csaddr + i), block, size)
- == -1) {
- ERROR(disk, "Failed to read sb summary information");
- free(fs->fs_csp);
- return (-1);
- }
- bcopy(block, space, size);
- space += size;
- }
- fs->fs_maxcluster = (uint32_t *)space;
+ disk->d_sblock = fs->fs_sblockloc / disk->d_bsize;
disk->d_sbcsum = fs->fs_csp;
-
return (0);
}
@@ -127,45 +96,107 @@ int
sbwrite(struct uufsd *disk, int all)
{
struct fs *fs;
- int blks, size;
- uint8_t *space;
- unsigned i;
ERROR(disk, NULL);
fs = &disk->d_fs;
-
- if (!disk->d_sblock) {
- disk->d_sblock = disk->d_fs.fs_sblockloc / disk->d_bsize;
- }
-
- if (bwrite(disk, disk->d_sblock, fs, SBLOCKSIZE) == -1) {
- ERROR(disk, "failed to write superblock");
+ if ((errno = sbput(disk->d_fd, fs, all ? fs->fs_ncg : 0)) != 0) {
+ switch (errno) {
+ case EIO:
+ ERROR(disk, "failed to write superblock");
+ break;
+ default:
+ ERROR(disk, "unknown superblock write error");
+ errno = EIO;
+ break;
+ }
return (-1);
}
- /*
- * Write superblock summary information.
- */
- blks = howmany(fs->fs_cssize, fs->fs_fsize);
- space = (uint8_t *)disk->d_sbcsum;
- for (i = 0; i < blks; i += fs->fs_frag) {
- size = fs->fs_bsize;
- if (i + fs->fs_frag > blks)
- size = (blks - i) * fs->fs_fsize;
- if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + i), space, size)
- == -1) {
- ERROR(disk, "Failed to write sb summary information");
+ return (0);
+}
+
+/*
+ * These are the low-level functions that actually read and write
+ * the superblock and its associated data. The actual work is done by
+ * the functions ffs_sbget and ffs_sbput in /sys/ufs/ffs/ffs_subr.c.
+ */
+static int use_pread(void *devfd, off_t loc, void **bufp, int size);
+static int use_pwrite(void *devfd, off_t loc, void *buf, int size);
+
+/*
+ * Read a superblock from the devfd device allocating memory returned
+ * in fsp. Also read the superblock summary information.
+ */
+int
+sbget(int devfd, struct fs **fsp, off_t sblockloc)
+{
+
+ return (ffs_sbget(&devfd, fsp, sblockloc, "user", use_pread));
+}
+
+/*
+ * A read function for use by user-level programs using libufs.
+ */
+static int
+use_pread(void *devfd, off_t loc, void **bufp, int size)
+{
+ int fd;
+
+ fd = *(int *)devfd;
+ if ((*bufp = malloc(size)) == NULL)
+ return (ENOSPC);
+ if (pread(fd, *bufp, size, loc) != size)
+ return (EIO);
+ return (0);
+}
+
+/*
+ * Write a superblock to the devfd device from the memory pointed to by fs.
+ * Also write out the superblock summary information but do not free the
+ * summary information memory.
+ *
+ * Additionally write out numaltwrite of the alternate superblocks. Use
+ * fs->fs_ncg to write out all of the alternate superblocks.
+ */
+int
+sbput(int devfd, struct fs *fs, int numaltwrite)
+{
+ struct csum *savedcsp;
+ off_t savedactualloc;
+ int i, error;
+
+ if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc,
+ use_pwrite)) != 0)
+ return (error);
+ if (numaltwrite == 0)
+ return (0);
+ savedactualloc = fs->fs_sblockactualloc;
+ savedcsp = fs->fs_csp;
+ fs->fs_csp = NULL;
+ for (i = 0; i < numaltwrite; i++) {
+ fs->fs_sblockactualloc = dbtob(fsbtodb(fs, cgsblock(fs, i)));
+ if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc,
+ use_pwrite)) != 0) {
+ fs->fs_sblockactualloc = savedactualloc;
+ fs->fs_csp = savedcsp;
return (-1);
}
- space += size;
- }
- if (all) {
- for (i = 0; i < fs->fs_ncg; i++)
- if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)),
- fs, SBLOCKSIZE) == -1) {
- ERROR(disk, "failed to update a superblock");
- return (-1);
- }
}
+ fs->fs_sblockactualloc = savedactualloc;
+ fs->fs_csp = savedcsp;
+ return (0);
+}
+
+/*
+ * A write function for use by user-level programs using sbput in libufs.
+ */
+static int
+use_pwrite(void *devfd, off_t loc, void *buf, int size)
+{
+ int fd;
+
+ fd = *(int *)devfd;
+ if (pwrite(fd, buf, size, loc) != size)
+ return (EIO);
return (0);
}
diff --git a/lib/libufs/sbread.3 b/lib/libufs/sbread.3
index 8b5e8c0d4d6b..42342b2f3271 100644
--- a/lib/libufs/sbread.3
+++ b/lib/libufs/sbread.3
@@ -2,6 +2,8 @@
.\" Date: June 04, 2003
.\" Description:
.\" Manual page for libufs functions:
+.\" sbget(3)
+.\" sbput(3)
.\" sbread(3)
.\" sbwrite(3)
.\"
@@ -9,11 +11,11 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 4, 2003
+.Dd January 19, 2018
.Dt SBREAD 3
.Os
.Sh NAME
-.Nm sbread , sbwrite
+.Nm sbget , sbput , sbread , sbwrite
.Nd read and write superblocks of a UFS file system
.Sh LIBRARY
.Lb libufs
@@ -25,35 +27,95 @@
.In ufs/ffs/fs.h
.In libufs.h
.Ft int
+.Fn sbget "int devfd" "struct fs **fsp" "off_t sblockloc"
+.Ft int
+.Fn sbput "int devfd" "struct fs *fs" "int numaltwrite"
+.Ft int
.Fn sbread "struct uufsd *disk"
.Ft int
.Fn sbwrite "struct uufsd *disk" "int all"
.Sh DESCRIPTION
The
+.Fn sbget
+and
.Fn sbread
+functions provide superblock reads for
+.Xr libufs 3
+consumers.
+The
+.Fn sbput
and
.Fn sbwrite
-functions provide superblock reads and writes for
+functions provide superblock writes for
.Xr libufs 3
consumers.
+.Pp
+The
+.Fn sbget
+function first allocates a buffer to hold the superblock.
+Using the
+.Va devfd
+file descriptor that references the filesystem disk,
+.Fn sbget
+reads the superblock located at the byte offset specified by
+.Va sblockloc
+into the allocated buffer.
+If successful, it returns a pointer to the buffer containing the superblock in
+.Va fsp .
+The
+.Fn sbget
+function is safe to use in threaded applications.
+.Pp
+The
+.Fn sbput
+function writes the superblock specified by
+.Va fs
+to the location from which it was read on the disk referenced by the
+.Va devfd
+file descriptor.
+Additionally, the
+.Fn sbput
+function will update the first
+.Va numaltwrite
+alternate superblock locations.
+To update all the alternate superblocks,
+specify a
+.Va numaltwrite
+value of
+.Va fs->fs_ncg .
+The
+.Fn sbput
+function is safe to use in threaded applications.
+Note that the
+.Fn sbput
+function needs to be called only if the superblock has been
+modified and the on-disk copy needs to be updated.
+.Pp
The
.Fn sbread
-and
+function reads the standard filesystem superblock into the
+.Va d_sb ,
+structure embedded in the given user-land UFS disk structure.
+.Pp
+The
.Fn sbwrite
-functions operate on the superblock field,
+function writes the superblock from the
.Va d_sb ,
-associated with a given userland UFS disk structure.
+structure embedded in the given user-land UFS disk structure
+to the location from which it was read.
Additionally, the
.Fn sbwrite
-function will write to all superblock locations if the
+function will write to all the alternate superblock locations if the
.Fa all
value is non-zero.
.Sh RETURN VALUES
-.Rv -std sbread sbwrite
+.Rv -std sbget sbput sbread sbwrite
.Sh ERRORS
-The function
+The
+.Fn sbget
+and
.Fn sbread
-may fail and set
+functions may fail and set
.Va errno
for any of the errors specified for the library function
.Xr bread 3 .
@@ -62,9 +124,11 @@ Additionally, it may follow the
error methodologies in situations where no usable superblock could be
found.
.Pp
-The function
+The
+.Fn sbput
+and
.Fn sbwrite
-may fail and set
+functions may fail and set
.Va errno
for any of the errors specified for the library function
.Xr bwrite 3 .
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 <bsd.prog.mk>
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 <ufs/ffs/fs.h>
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
+#include <libufs.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
-/*
- * 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 <errno.h>
#include <fcntl.h>
#include <fstab.h>
+#include <libufs.h>
#include <limits.h>
#include <signal.h>
#include <stdint.h>
@@ -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
@@ -311,70 +311,48 @@ badsb:
}
/*
- * 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 <bsd.prog.mk>
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 <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <libufs.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -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 <paths.h>
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
#include <fstab.h>
#include <inttypes.h>
@@ -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 <fcntl.h>
#include <fstab.h>
#include <grp.h>
+#include <libufs.h>
#include <libutil.h>
#include <pwd.h>
#include <stdint.h>
@@ -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);
@@ -244,11 +245,6 @@ usage(void)
}
/*
- * 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.
*/
int
@@ -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);
}
/*
diff --git a/stand/libsa/Makefile b/stand/libsa/Makefile
index f95bb64806bd..3b54e67a19cf 100644
--- a/stand/libsa/Makefile
+++ b/stand/libsa/Makefile
@@ -141,6 +141,10 @@ SRCS+= pkgfs.c
SRCS+= nandfs.c
.endif
+# kernel ufs support
+.PATH: ${SRCTOP}/sys/ufs/ffs
+SRCS+=ffs_subr.c ffs_tables.c
+
CFLAGS.bzipfs.c+= -I${SRCTOP}/contrib/bzip2
# explicit_bzero
diff --git a/stand/libsa/ufs.c b/stand/libsa/ufs.c
index e0ceed804d9a..1f0b7d3591f6 100644
--- a/stand/libsa/ufs.c
+++ b/stand/libsa/ufs.c
@@ -133,6 +133,11 @@ static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *);
static int buf_read_file(struct open_file *, char **, size_t *);
static int buf_write_file(struct open_file *, char *, size_t *);
static int search_directory(char *, struct open_file *, ino_t *);
+static int ufs_use_sa_read(void *, off_t, void **, int);
+
+/* from ffs_subr.c */
+int ffs_sbget(void *, struct fs **, off_t, char *,
+ int (*)(void *, off_t, void **, int));
/*
* Read a new inode into a file structure.
@@ -485,8 +490,6 @@ search_directory(name, f, inumber_p)
return (ENOENT);
}
-static int sblock_try[] = SBLOCKSEARCH;
-
/*
* Open a file.
*/
@@ -512,31 +515,11 @@ ufs_open(upath, f)
bzero(fp, sizeof(struct file));
f->f_fsdata = (void *)fp;
- /* allocate space and read super block */
- fs = malloc(SBLOCKSIZE);
- fp->f_fs = fs;
+ /* read super block */
twiddle(1);
- /*
- * Try reading the superblock in each of its possible locations.
- */
- for (i = 0; sblock_try[i] != -1; i++) {
- rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
- (char *)fs, &buf_size);
- if (rc)
- goto out;
- if ((fs->fs_magic == FS_UFS1_MAGIC ||
- (fs->fs_magic == FS_UFS2_MAGIC &&
- fs->fs_sblockloc == sblock_try[i])) &&
- buf_size == SBLOCKSIZE &&
- fs->fs_bsize <= MAXBSIZE &&
- fs->fs_bsize >= sizeof(struct fs))
- break;
- }
- if (sblock_try[i] == -1) {
- rc = EINVAL;
+ if ((rc = ffs_sbget(f, &fs, -1, 0, ufs_use_sa_read)) != 0)
goto out;
- }
+ fp->f_fs = fs;
/*
* Calculate indirect block levels.
*/
@@ -693,6 +676,28 @@ out:
return (rc);
}
+/*
+ * A read function for use by standalone-layer routines.
+ */
+static int
+ufs_use_sa_read(void *devfd, off_t loc, void **bufp, int size)
+{
+ struct open_file *f;
+ size_t buf_size;
+ int error;
+
+ f = (struct open_file *)devfd;
+ if ((*bufp = malloc(size)) == NULL)
+ return (ENOSPC);
+ error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, loc / DEV_BSIZE,
+ size, *bufp, &buf_size);
+ if (error != 0)
+ return (error);
+ if (buf_size != size)
+ return (EIO);
+ return (0);
+}
+
static int
ufs_close(f)
struct open_file *f;
diff --git a/sys/geom/geom.h b/sys/geom/geom.h
index e283c999988f..657cc369200b 100644
--- a/sys/geom/geom.h
+++ b/sys/geom/geom.h
@@ -344,6 +344,8 @@ void * g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error
int g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length);
int g_delete_data(struct g_consumer *cp, off_t offset, off_t length);
void g_print_bio(struct bio *bp);
+int g_use_g_read_data(void *, off_t, void **, int);
+int g_use_g_write_data(void *, off_t, void *, int);
/* geom_kern.c / geom_kernsim.c */
diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c
index 9ca441ca4937..bab0041a244c 100644
--- a/sys/geom/geom_io.c
+++ b/sys/geom/geom_io.c
@@ -949,6 +949,29 @@ g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error)
return (ptr);
}
+/*
+ * A read function for use by ffs_sbget when used by GEOM-layer routines.
+ */
+int
+g_use_g_read_data(void *devfd, off_t loc, void **bufp, int size)
+{
+ struct g_consumer *cp;
+
+ cp = (struct g_consumer *)devfd;
+ /*
+ * Take care not to issue an invalid I/O request. The offset of
+ * the superblock candidate must be multiples of the provider's
+ * sector size, otherwise an FFS can't exist on the provider
+ * anyway.
+ */
+ if (loc % cp->provider->sectorsize != 0)
+ return (ENOENT);
+ *bufp = g_read_data(cp, loc, size, NULL);
+ if (*bufp == NULL)
+ return (ENOENT);
+ return (0);
+}
+
int
g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length)
{
@@ -971,6 +994,16 @@ g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length)
return (error);
}
+/*
+ * A write function for use by ffs_sbput when used by GEOM-layer routines.
+ */
+int
+g_use_g_write_data(void *devfd, off_t loc, void *buf, int size)
+{
+
+ return (g_write_data((struct g_consumer *)devfd, loc, buf, size));
+}
+
int
g_delete_data(struct g_consumer *cp, off_t offset, off_t length)
{
diff --git a/sys/geom/journal/g_journal_ufs.c b/sys/geom/journal/g_journal_ufs.c
index 2080808a8c93..ec25750c38ac 100644
--- a/sys/geom/journal/g_journal_ufs.c
+++ b/sys/geom/journal/g_journal_ufs.c
@@ -46,8 +46,6 @@ __FBSDID("$FreeBSD$");
#include <geom/geom.h>
#include <geom/journal/g_journal.h>
-static const int superblocks[] = SBLOCKSEARCH;
-
static int
g_journal_ufs_clean(struct mount *mp)
{
@@ -70,33 +68,25 @@ static void
g_journal_ufs_dirty(struct g_consumer *cp)
{
struct fs *fs;
- int error, i, sb;
+ int error;
- if (SBLOCKSIZE % cp->provider->sectorsize != 0)
+ if (SBLOCKSIZE % cp->provider->sectorsize != 0 ||
+ ffs_sbget(cp, &fs, -1, NULL, g_use_g_read_data) != 0) {
+ GJ_DEBUG(0, "Cannot find superblock to mark file system %s "
+ "as dirty.", cp->provider->name);
return;
- for (i = 0; (sb = superblocks[i]) != -1; i++) {
- if (sb % cp->provider->sectorsize != 0)
- continue;
- fs = g_read_data(cp, sb, SBLOCKSIZE, NULL);
- if (fs == NULL)
- continue;
- if (fs->fs_magic != FS_UFS1_MAGIC &&
- fs->fs_magic != FS_UFS2_MAGIC) {
- g_free(fs);
- continue;
- }
- GJ_DEBUG(0, "clean=%d flags=0x%x", fs->fs_clean, fs->fs_flags);
- fs->fs_clean = 0;
- fs->fs_flags |= FS_NEEDSFSCK | FS_UNCLEAN;
- error = g_write_data(cp, sb, fs, SBLOCKSIZE);
- g_free(fs);
- if (error != 0) {
- GJ_DEBUG(0, "Cannot mark file system %s as dirty "
- "(error=%d).", cp->provider->name, error);
- } else {
- GJ_DEBUG(0, "File system %s marked as dirty.",
- cp->provider->name);
- }
+ }
+ GJ_DEBUG(0, "clean=%d flags=0x%x", fs->fs_clean, fs->fs_flags);
+ fs->fs_clean = 0;
+ fs->fs_flags |= FS_NEEDSFSCK | FS_UNCLEAN;
+ error = ffs_sbput(cp, fs, fs->fs_sblockloc, g_use_g_write_data);
+ g_free(fs);
+ if (error != 0) {
+ GJ_DEBUG(0, "Cannot mark file system %s as dirty "
+ "(error=%d).", cp->provider->name, error);
+ } else {
+ GJ_DEBUG(0, "File system %s marked as dirty.",
+ cp->provider->name);
}
}
diff --git a/sys/geom/label/g_label_ufs.c b/sys/geom/label/g_label_ufs.c
index b53d6e45857e..43c44586cb05 100644
--- a/sys/geom/label/g_label_ufs.c
+++ b/sys/geom/label/g_label_ufs.c
@@ -32,11 +32,14 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/vnode.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/extattr.h>
+#include <ufs/ffs/ffs_extern.h>
#include <geom/geom.h>
#include <geom/label/g_label.h>
@@ -56,106 +59,63 @@ __FBSDID("$FreeBSD$");
< G_LABEL_UFS_MAXDIFF )
#define G_LABEL_UFS_MAXDIFF 0x100
-static const int superblocks[] = SBLOCKSEARCH;
-
+/*
+ * Try to find a superblock on the provider. If successful, then
+ * check that the size in the superblock corresponds to the size
+ * of the underlying provider. Finally, look for a volume label
+ * and create an appropriate provider based on that.
+ */
static void
g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int what)
{
struct g_provider *pp;
- int sb, superblock;
struct fs *fs;
g_topology_assert_not();
pp = cp->provider;
label[0] = '\0';
- if (SBLOCKSIZE % cp->provider->sectorsize != 0)
+ if (SBLOCKSIZE % pp->sectorsize != 0 ||
+ ffs_sbget(cp, &fs, -1, NULL, g_use_g_read_data) != 0)
return;
-
/*
- * Walk through the standard places that superblocks hide and look
- * for UFS magic. If we find magic, then check that the size in the
- * superblock corresponds to the size of the underlying provider.
- * Finally, look for a volume label and create an appropriate
- * provider based on that.
+ * Check for magic. We also need to check if file system size
+ * is almost equal to providers size, because sysinstall(8)
+ * used to bogusly put first partition at offset 0
+ * instead of 16, and glabel/ufs would find file system on slice
+ * instead of partition.
+ *
+ * In addition, media size can be a bit bigger than file system
+ * size. For instance, mkuzip can append bytes to align data
+ * to large sector size (it improves compression rates).
*/
- for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) {
- /*
- * Take care not to issue an invalid I/O request. The offset of
- * the superblock candidate must be multiples of the provider's
- * sector size, otherwise an FFS can't exist on the provider
- * anyway.
- */
- if (superblock % cp->provider->sectorsize != 0)
- continue;
-
- fs = (struct fs *)g_read_data(cp, superblock, SBLOCKSIZE, NULL);
- if (fs == NULL)
- continue;
- /*
- * Check for magic. We also need to check if file system size
- * is almost equal to providers size, because sysinstall(8)
- * used to bogusly put first partition at offset 0
- * instead of 16, and glabel/ufs would find file system on slice
- * instead of partition.
- *
- * In addition, media size can be a bit bigger than file system
- * size. For instance, mkuzip can append bytes to align data
- * to large sector size (it improves compression rates).
- */
- switch (fs->fs_magic){
- case FS_UFS1_MAGIC:
- case FS_UFS2_MAGIC:
- G_LABEL_DEBUG(1, "%s %s params: %jd, %d, %d, %jd\n",
- fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2",
- pp->name, pp->mediasize, fs->fs_fsize,
- fs->fs_old_size, fs->fs_providersize);
- break;
- default:
- break;
- }
-
- if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0 &&
- ( G_LABEL_UFS_CMP(pp, fs, fs_old_size)
- || G_LABEL_UFS_CMP(pp, fs, fs_providersize))) {
- /* Valid UFS1. */
- } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 &&
- ( G_LABEL_UFS_CMP(pp, fs, fs_size)
- || G_LABEL_UFS_CMP(pp, fs, fs_providersize))) {
- /* Valid UFS2. */
- } else {
- g_free(fs);
- continue;
- }
- if (fs->fs_sblockloc != superblock || fs->fs_ncg < 1 ||
- fs->fs_bsize < MINBSIZE ||
- fs->fs_bsize < sizeof(struct fs)) {
- g_free(fs);
- continue;
- }
- G_LABEL_DEBUG(1, "%s file system detected on %s.",
- fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name);
- switch (what) {
- case G_LABEL_UFS_VOLUME:
- /* Check for volume label */
- if (fs->fs_volname[0] == '\0') {
- g_free(fs);
- continue;
- }
+ if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0 &&
+ ( G_LABEL_UFS_CMP(pp, fs, fs_old_size)
+ || G_LABEL_UFS_CMP(pp, fs, fs_providersize))) {
+ /* Valid UFS1. */
+ } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 &&
+ ( G_LABEL_UFS_CMP(pp, fs, fs_size)
+ || G_LABEL_UFS_CMP(pp, fs, fs_providersize))) {
+ /* Valid UFS2. */
+ } else {
+ g_free(fs);
+ return;
+ }
+ G_LABEL_DEBUG(1, "%s file system detected on %s.",
+ fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name);
+ switch (what) {
+ case G_LABEL_UFS_VOLUME:
+ /* Check for volume label */
+ if (fs->fs_volname[0] != '\0')
strlcpy(label, fs->fs_volname, size);
- break;
- case G_LABEL_UFS_ID:
- if (fs->fs_id[0] == 0 && fs->fs_id[1] == 0) {
- g_free(fs);
- continue;
- }
+ break;
+ case G_LABEL_UFS_ID:
+ if (fs->fs_id[0] != 0 || fs->fs_id[1] != 0)
snprintf(label, size, "%08x%08x", fs->fs_id[0],
fs->fs_id[1]);
- break;
- }
- g_free(fs);
break;
}
+ g_free(fs);
}
static void
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index 5e9be1ea914a..2df48ec91de9 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -87,6 +87,10 @@ int ffs_reallocblks(struct vop_reallocblks_args *);
int ffs_realloccg(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
ufs2_daddr_t, int, int, int, struct ucred *, struct buf **);
int ffs_reload(struct mount *, struct thread *, int);
+int ffs_sbget(void *, struct fs **, off_t, struct malloc_type *,
+ int (*)(void *, off_t, void **, int));
+int ffs_sbput(void *, struct fs *, off_t, int (*)(void *, off_t, void *,
+ int));
int ffs_sbupdate(struct ufsmount *, int, int);
void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
int ffs_snapblkfree(struct fs *, struct vnode *, ufs2_daddr_t, long, ino_t,
@@ -95,18 +99,17 @@ void ffs_snapremove(struct vnode *vp);
int ffs_snapshot(struct mount *mp, char *snapfile);
void ffs_snapshot_mount(struct mount *mp);
void ffs_snapshot_unmount(struct mount *mp);
-void process_deferred_inactive(struct mount *mp);
+void ffs_susp_initialize(void);
+void ffs_susp_uninitialize(void);
void ffs_sync_snap(struct mount *, int);
int ffs_syncvnode(struct vnode *vp, int waitfor, int flags);
int ffs_truncate(struct vnode *, off_t, int, struct ucred *);
int ffs_update(struct vnode *, int);
int ffs_valloc(struct vnode *, int, struct ucred *, struct vnode **);
-
int ffs_vfree(struct vnode *, ino_t, int);
vfs_vget_t ffs_vget;
int ffs_vgetf(struct mount *, ino_t, int, struct vnode **, int);
-void ffs_susp_initialize(void);
-void ffs_susp_uninitialize(void);
+void process_deferred_inactive(struct mount *mp);
#define FFSV_FORCEINSMQ 0x0001
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index 5a07ab5ae106..3504c625eb70 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -37,9 +37,20 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#ifndef _KERNEL
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/errno.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
-#else
+
+struct malloc_type;
+#define UFS_MALLOC(size, type, flags) malloc(size)
+#define UFS_FREE(ptr, type) free(ptr)
+#define UFS_TIME time(NULL)
+
+#else /* _KERNEL */
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -57,6 +68,10 @@ __FBSDID("$FreeBSD$");
#include <ufs/ffs/ffs_extern.h>
#include <ufs/ffs/fs.h>
+#define UFS_MALLOC(size, type, flags) malloc(size, type, flags)
+#define UFS_FREE(ptr, type) free(ptr, type)
+#define UFS_TIME time_second
+
/*
* Return buffer with the contents of block "offset" from the beginning of
* directory "ip". If "res" is non-zero, fill it in with a pointer to the
@@ -121,6 +136,175 @@ ffs_load_inode(struct buf *bp, struct inode *ip, struct fs *fs, ino_t ino)
#endif /* KERNEL */
/*
+ * These are the low-level functions that actually read and write
+ * the superblock and its associated data.
+ */
+static off_t sblock_try[] = SBLOCKSEARCH;
+static int readsuper(void *, struct fs **, off_t,
+ int (*)(void *, off_t, void **, int));
+
+/*
+ * Read a superblock from the devfd device.
+ *
+ * If an alternate superblock is specified, it is read. Otherwise the
+ * set of locations given in the SBLOCKSEARCH list is searched for a
+ * superblock. Memory is allocated for the superblock by the readfunc and
+ * is returned. If filltype is non-NULL, additional memory is allocated
+ * of type filltype and filled in with the superblock summary information.
+ *
+ * If a superblock is found, zero is returned. Otherwise one of the
+ * following error values is returned:
+ * EIO: non-existent or truncated superblock.
+ * EIO: error reading summary information.
+ * ENOENT: no usable known superblock found.
+ * ENOSPC: failed to allocate space for the superblock.
+ * EINVAL: The previous newfs operation on this volume did not complete.
+ * The administrator must complete newfs before using this volume.
+ */
+int
+ffs_sbget(void *devfd, struct fs **fsp, off_t altsuperblock,
+ struct malloc_type *filltype,
+ int (*readfunc)(void *devfd, off_t loc, void **bufp, int size))
+{
+ struct fs *fs;
+ int i, ret, size, blks;
+ uint8_t *space;
+ int32_t *lp;
+ char *buf;
+
+ if (altsuperblock != -1) {
+ if ((ret = readsuper(devfd, fsp, altsuperblock, readfunc)) != 0)
+ return (ret);
+ } else {
+ for (i = 0; sblock_try[i] != -1; i++) {
+ if ((ret = readsuper(devfd, fsp, sblock_try[i],
+ readfunc)) == 0)
+ break;
+ if (ret == ENOENT)
+ continue;
+ return (ret);
+ }
+ if (sblock_try[i] == -1)
+ return (ENOENT);
+ }
+ /*
+ * If not filling in summary information, NULL out fs_csp and return.
+ */
+ fs = *fsp;
+ if (filltype == NULL) {
+ fs->fs_csp = NULL;
+ return (0);
+ }
+ /*
+ * Read in the superblock summary information.
+ */
+ size = fs->fs_cssize;
+ blks = howmany(size, fs->fs_fsize);
+ if (fs->fs_contigsumsize > 0)
+ size += fs->fs_ncg * sizeof(int32_t);
+ size += fs->fs_ncg * sizeof(u_int8_t);
+ space = UFS_MALLOC(size, filltype, M_WAITOK);
+ fs->fs_csp = (struct csum *)space;
+ for (i = 0; i < blks; i += fs->fs_frag) {
+ size = fs->fs_bsize;
+ if (i + fs->fs_frag > blks)
+ size = (blks - i) * fs->fs_fsize;
+ ret = (*readfunc)(devfd,
+ dbtob(fsbtodb(fs, fs->fs_csaddr + i)), (void **)&buf, size);
+ if (ret) {
+ UFS_FREE(fs->fs_csp, filltype);
+ fs->fs_csp = NULL;
+ return (ret);
+ }
+ memcpy(space, buf, size);
+ UFS_FREE(buf, filltype);
+ space += size;
+ }
+ if (fs->fs_contigsumsize > 0) {
+ fs->fs_maxcluster = lp = (int32_t *)space;
+ for (i = 0; i < fs->fs_ncg; i++)
+ *lp++ = fs->fs_contigsumsize;
+ space = (uint8_t *)lp;
+ }
+ size = fs->fs_ncg * sizeof(u_int8_t);
+ fs->fs_contigdirs = (u_int8_t *)space;
+ bzero(fs->fs_contigdirs, size);
+ return (0);
+}
+
+/*
+ * Try to read a superblock from the location specified by sblockloc.
+ * Return zero on success or an errno on failure.
+ */
+static int
+readsuper(void *devfd, struct fs **fsp, off_t sblockloc,
+ int (*readfunc)(void *devfd, off_t loc, void **bufp, int size))
+{
+ struct fs *fs;
+ int error;
+
+ error = (*readfunc)(devfd, sblockloc, (void **)fsp, SBLOCKSIZE);
+ if (error != 0)
+ return (error);
+ fs = *fsp;
+ if (fs->fs_magic == FS_BAD_MAGIC)
+ return (EINVAL);
+ if (((fs->fs_magic == FS_UFS1_MAGIC && sblockloc <= SBLOCK_UFS1) ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ sblockloc == fs->fs_sblockloc)) &&
+ fs->fs_ncg >= 1 &&
+ fs->fs_bsize >= MINBSIZE &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= roundup(sizeof(struct fs), DEV_BSIZE)) {
+ /* Have to set for old filesystems that predate this field */
+ fs->fs_sblockactualloc = sblockloc;
+ return (0);
+ }
+ return (ENOENT);
+}
+
+/*
+ * Write a superblock to the devfd device from the memory pointed to by fs.
+ * Write out the superblock summary information if it is present.
+ *
+ * If the write is successful, zero is returned. Otherwise one of the
+ * following error values is returned:
+ * EIO: failed to write superblock.
+ * EIO: failed to write superblock summary information.
+ */
+int
+ffs_sbput(void *devfd, struct fs *fs, off_t loc,
+ int (*writefunc)(void *devfd, off_t loc, void *buf, int size))
+{
+ int i, error, blks, size;
+ uint8_t *space;
+
+ /*
+ * If there is summary information, write it first, so if there
+ * is an error, the superblock will not be marked as clean.
+ */
+ if (fs->fs_csp != NULL) {
+ blks = howmany(fs->fs_cssize, fs->fs_fsize);
+ space = (uint8_t *)fs->fs_csp;
+ for (i = 0; i < blks; i += fs->fs_frag) {
+ size = fs->fs_bsize;
+ if (i + fs->fs_frag > blks)
+ size = (blks - i) * fs->fs_fsize;
+ if ((error = (*writefunc)(devfd,
+ dbtob(fsbtodb(fs, fs->fs_csaddr + i)),
+ space, size)) != 0)
+ return (error);
+ space += size;
+ }
+ }
+ fs->fs_fmod = 0;
+ fs->fs_time = UFS_TIME;
+ if ((error = (*writefunc)(devfd, loc, fs, fs->fs_sbsize)) != 0)
+ return (error);
+ return (0);
+}
+
+/*
* Update the frsum fields to reflect addition or deletion
* of some frags.
*/
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 2a63ee74b654..caf062867dbe 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -87,6 +87,8 @@ static void ffs_oldfscompat_read(struct fs *, struct ufsmount *,
ufs2_daddr_t);
static void ffs_ifree(struct ufsmount *ump, struct inode *ip);
static int ffs_sync_lazy(struct mount *mp);
+static int ffs_use_bread(void *devfd, off_t loc, void **bufp, int size);
+static int ffs_use_bwrite(void *devfd, off_t loc, void *buf, int size);
static vfs_init_t ffs_init;
static vfs_uninit_t ffs_uninit;
@@ -753,11 +755,6 @@ loop:
}
/*
- * Possible superblock locations ordered from most to least likely.
- */
-static int sblock_try[] = SBLOCKSEARCH;
-
-/*
* Common code for mount and mountroot
*/
static int
@@ -767,19 +764,14 @@ ffs_mountfs(devvp, mp, td)
struct thread *td;
{
struct ufsmount *ump;
- struct buf *bp;
struct fs *fs;
struct cdev *dev;
- void *space;
- ufs2_daddr_t sblockloc;
- int error, i, blks, len, ronly;
- u_long size;
- int32_t *lp;
+ int error, i, len, ronly;
struct ucred *cred;
struct g_consumer *cp;
struct mount *nmp;
- bp = NULL;
+ fs = NULL;
ump = NULL;
cred = td ? td->td_ucred : NOCRED;
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
@@ -806,39 +798,16 @@ ffs_mountfs(devvp, mp, td)
mp->mnt_iosize_max = dev->si_iosize_max;
if (mp->mnt_iosize_max > MAXPHYS)
mp->mnt_iosize_max = MAXPHYS;
-
- fs = NULL;
- sblockloc = 0;
- /*
- * Try reading the superblock in each of its possible locations.
- */
- for (i = 0; sblock_try[i] != -1; i++) {
- if ((SBLOCKSIZE % cp->provider->sectorsize) != 0) {
- error = EINVAL;
- vfs_mount_error(mp,
- "Invalid sectorsize %d for superblock size %d",
- cp->provider->sectorsize, SBLOCKSIZE);
- goto out;
- }
- if ((error = bread(devvp, btodb(sblock_try[i]), SBLOCKSIZE,
- cred, &bp)) != 0)
- goto out;
- fs = (struct fs *)bp->b_data;
- sblockloc = sblock_try[i];
- if ((fs->fs_magic == FS_UFS1_MAGIC ||
- (fs->fs_magic == FS_UFS2_MAGIC &&
- (fs->fs_sblockloc == sblockloc ||
- (fs->fs_old_flags & FS_FLAGS_UPDATED) == 0))) &&
- fs->fs_bsize <= MAXBSIZE &&
- fs->fs_bsize >= sizeof(struct fs))
- break;
- brelse(bp);
- bp = NULL;
- }
- if (sblock_try[i] == -1) {
- error = EINVAL; /* XXX needs translation */
+ if ((SBLOCKSIZE % cp->provider->sectorsize) != 0) {
+ error = EINVAL;
+ vfs_mount_error(mp,
+ "Invalid sectorsize %d for superblock size %d",
+ cp->provider->sectorsize, SBLOCKSIZE);
goto out;
}
+ /* fetch the superblock and summary information */
+ if ((error = ffs_sbget(devvp, &fs, -1, M_UFSMNT, ffs_use_bread)) != 0)
+ goto out;
fs->fs_fmod = 0;
/* none of these types of check-hashes are maintained */
fs->fs_metackhash &= ~(CK_SUPERBLOCK | CK_INODE | CK_INDIR | CK_DIR);
@@ -908,7 +877,7 @@ ffs_mountfs(devvp, mp, td)
ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO);
ump->um_cp = cp;
ump->um_bo = &devvp->v_bufobj;
- ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, M_WAITOK);
+ ump->um_fs = fs;
if (fs->fs_magic == FS_UFS1_MAGIC) {
ump->um_fstype = UFS1;
ump->um_balloc = ffs_balloc_ufs1;
@@ -925,44 +894,8 @@ ffs_mountfs(devvp, mp, td)
ump->um_rdonly = ffs_rdonly;
ump->um_snapgone = ffs_snapgone;
mtx_init(UFS_MTX(ump), "FFS", "FFS Lock", MTX_DEF);
- bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
- if (fs->fs_sbsize < SBLOCKSIZE)
- bp->b_flags |= B_INVAL | B_NOCACHE;
- brelse(bp);
- bp = NULL;
- fs = ump->um_fs;
- ffs_oldfscompat_read(fs, ump, sblockloc);
+ ffs_oldfscompat_read(fs, ump, fs->fs_sblockloc);
fs->fs_ronly = ronly;
- size = fs->fs_cssize;
- blks = howmany(size, fs->fs_fsize);
- if (fs->fs_contigsumsize > 0)
- size += fs->fs_ncg * sizeof(int32_t);
- size += fs->fs_ncg * sizeof(u_int8_t);
- space = malloc(size, M_UFSMNT, M_WAITOK);
- fs->fs_csp = space;
- for (i = 0; i < blks; i += fs->fs_frag) {
- size = fs->fs_bsize;
- if (i + fs->fs_frag > blks)
- size = (blks - i) * fs->fs_fsize;
- if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
- cred, &bp)) != 0) {
- free(fs->fs_csp, M_UFSMNT);
- goto out;
- }
- bcopy(bp->b_data, space, (u_int)size);
- space = (char *)space + size;
- brelse(bp);
- bp = NULL;
- }
- if (fs->fs_contigsumsize > 0) {
- fs->fs_maxcluster = lp = space;
- for (i = 0; i < fs->fs_ncg; i++)
- *lp++ = fs->fs_contigsumsize;
- space = lp;
- }
- size = fs->fs_ncg * sizeof(u_int8_t);
- fs->fs_contigdirs = (u_int8_t *)space;
- bzero(fs->fs_contigdirs, size);
fs->fs_active = NULL;
mp->mnt_data = ump;
mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0];
@@ -1075,7 +1008,6 @@ ffs_mountfs(devvp, mp, td)
fs->fs_mtime = time_second;
if ((fs->fs_flags & FS_DOSOFTDEP) &&
(error = softdep_mount(devvp, mp, fs, cred)) != 0) {
- free(fs->fs_csp, M_UFSMNT);
ffs_flushfiles(mp, FORCECLOSE, td);
goto out;
}
@@ -1109,8 +1041,10 @@ ffs_mountfs(devvp, mp, td)
#endif /* !UFS_EXTATTR */
return (0);
out:
- if (bp)
- brelse(bp);
+ if (fs != NULL) {
+ free(fs->fs_csp, M_UFSMNT);
+ free(fs, M_UFSMNT);
+ }
if (cp != NULL) {
g_topology_lock();
g_vfs_close(cp);
@@ -1122,7 +1056,6 @@ out:
free(mp->mnt_gjprovider, M_UFSMNT);
mp->mnt_gjprovider = NULL;
}
- free(ump->um_fs, M_UFSMNT);
free(ump, M_UFSMNT);
mp->mnt_data = NULL;
}
@@ -1131,6 +1064,28 @@ out:
return (error);
}
+/*
+ * A read function for use by filesystem-layer routines.
+ */
+static int
+ffs_use_bread(void *devfd, off_t loc, void **bufp, int size)
+{
+ struct buf *bp;
+ int error;
+
+ *bufp = malloc(size, M_UFSMNT, M_WAITOK);
+ if ((error = bread((struct vnode *)devfd, btodb(loc), size, NOCRED,
+ &bp)) != 0) {
+ free(*bufp, M_UFSMNT);
+ *bufp = NULL;
+ return (error);
+ }
+ bcopy(bp->b_data, *bufp, size);
+ bp->b_flags |= B_INVAL | B_NOCACHE;
+ brelse(bp);
+ return (0);
+}
+
#include <sys/sysctl.h>
static int bigcgs = 0;
SYSCTL_INT(_debug, OID_AUTO, bigcgs, CTLFLAG_RW, &bigcgs, 0, "");
@@ -1908,6 +1863,18 @@ ffs_uninit(vfsp)
}
/*
+ * Structure used to pass information from ffs_sbupdate to its
+ * helper routine ffs_use_bwrite.
+ */
+struct devfd {
+ struct ufsmount *ump;
+ struct buf *sbbp;
+ int waitfor;
+ int suspended;
+ int error;
+};
+
+/*
* Write a superblock and associated information back to disk.
*/
int
@@ -1916,13 +1883,11 @@ ffs_sbupdate(ump, waitfor, suspended)
int waitfor;
int suspended;
{
- struct fs *fs = ump->um_fs;
+ struct fs *fs;
struct buf *sbbp;
- struct buf *bp;
- int blks;
- void *space;
- int i, size, error, allerror = 0;
+ struct devfd devfd;
+ fs = ump->um_fs;
if (fs->fs_ronly == 1 &&
(ump->um_mountp->mnt_flag & (MNT_RDONLY | MNT_UPDATE)) !=
(MNT_RDONLY | MNT_UPDATE) && ump->um_fsckpid == 0)
@@ -1933,35 +1898,53 @@ ffs_sbupdate(ump, waitfor, suspended)
sbbp = getblk(ump->um_devvp, btodb(fs->fs_sblockloc),
(int)fs->fs_sbsize, 0, 0, 0);
/*
- * First write back the summary information.
+ * Initialize info needed for write function.
*/
- blks = howmany(fs->fs_cssize, fs->fs_fsize);
- space = fs->fs_csp;
- for (i = 0; i < blks; i += fs->fs_frag) {
- size = fs->fs_bsize;
- if (i + fs->fs_frag > blks)
- size = (blks - i) * fs->fs_fsize;
- bp = getblk(ump->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
- size, 0, 0, 0);
- bcopy(space, bp->b_data, (u_int)size);
- space = (char *)space + size;
- if (suspended)
+ devfd.ump = ump;
+ devfd.sbbp = sbbp;
+ devfd.waitfor = waitfor;
+ devfd.suspended = suspended;
+ devfd.error = 0;
+ return (ffs_sbput(&devfd, fs, fs->fs_sblockloc, ffs_use_bwrite));
+}
+
+/*
+ * Write function for use by filesystem-layer routines.
+ */
+static int
+ffs_use_bwrite(void *devfd, off_t loc, void *buf, int size)
+{
+ struct devfd *devfdp;
+ struct ufsmount *ump;
+ struct buf *bp;
+ struct fs *fs;
+ int error;
+
+ devfdp = devfd;
+ ump = devfdp->ump;
+ fs = ump->um_fs;
+ /*
+ * Writing the superblock summary information.
+ */
+ if (loc != fs->fs_sblockloc) {
+ bp = getblk(ump->um_devvp, btodb(loc), size, 0, 0, 0);
+ bcopy(buf, bp->b_data, (u_int)size);
+ if (devfdp->suspended)
bp->b_flags |= B_VALIDSUSPWRT;
- if (waitfor != MNT_WAIT)
+ if (devfdp->waitfor != MNT_WAIT)
bawrite(bp);
else if ((error = bwrite(bp)) != 0)
- allerror = error;
+ devfdp->error = error;
+ return (0);
}
/*
- * Now write back the superblock itself. If any errors occurred
- * up to this point, then fail so that the superblock avoids
- * being written out as clean.
+ * Writing the superblock itself. We need to do special checks for it.
*/
- if (allerror) {
- brelse(sbbp);
- return (allerror);
+ bp = devfdp->sbbp;
+ if (devfdp->error != 0) {
+ brelse(bp);
+ return (devfdp->error);
}
- bp = sbbp;
if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_sblockloc != SBLOCK_UFS1 &&
(fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) {
printf("WARNING: %s: correcting fs_sblockloc from %jd to %d\n",
@@ -1974,19 +1957,17 @@ ffs_sbupdate(ump, waitfor, suspended)
fs->fs_fsmnt, fs->fs_sblockloc, SBLOCK_UFS2);
fs->fs_sblockloc = SBLOCK_UFS2;
}
- fs->fs_fmod = 0;
- fs->fs_time = time_second;
if (MOUNTEDSOFTDEP(ump->um_mountp))
softdep_setup_sbupdate(ump, (struct fs *)bp->b_data, bp);
bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
ffs_oldfscompat_write((struct fs *)bp->b_data, ump);
- if (suspended)
+ if (devfdp->suspended)
bp->b_flags |= B_VALIDSUSPWRT;
- if (waitfor != MNT_WAIT)
+ if (devfdp->waitfor != MNT_WAIT)
bawrite(bp);
else if ((error = bwrite(bp)) != 0)
- allerror = error;
- return (allerror);
+ devfdp->error = error;
+ return (devfdp->error);
}
static int
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index cc0a480f253e..81deda7b8517 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -348,7 +348,8 @@ struct fs {
int64_t fs_unrefs; /* number of unreferenced inodes */
int64_t fs_providersize; /* size of underlying GEOM provider */
int64_t fs_metaspace; /* size of area reserved for metadata */
- int64_t fs_sparecon64[14]; /* old rotation block list head */
+ int64_t fs_sparecon64[13]; /* old rotation block list head */
+ int64_t fs_sblockactualloc; /* byte offset of this superblock */
int64_t fs_sblockloc; /* byte offset of standard superblock */
struct csum_total fs_cstotal; /* (u) cylinder summary information */
ufs_time_t fs_time; /* last time written */
diff --git a/usr.sbin/fstyp/Makefile b/usr.sbin/fstyp/Makefile
index 34be663fc362..f3fb038ed542 100644
--- a/usr.sbin/fstyp/Makefile
+++ b/usr.sbin/fstyp/Makefile
@@ -37,7 +37,7 @@ CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/head
CFLAGS+=-I${SRCTOP}/sys
-LIBADD= geom md
+LIBADD= geom md ufs
.if ${MK_ZFS} != "no"
LIBADD+=nvpair zfs
diff --git a/usr.sbin/fstyp/ufs.c b/usr.sbin/fstyp/ufs.c
index 8b27ca00fe43..340119dada4c 100644
--- a/usr.sbin/fstyp/ufs.c
+++ b/usr.sbin/fstyp/ufs.c
@@ -33,77 +33,32 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <errno.h>
+#include <libufs.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <ufs/ufs/dinode.h>
-#include <ufs/ffs/fs.h>
-
#include "fstyp.h"
-static const int superblocks[] = SBLOCKSEARCH;
-
int
fstyp_ufs(FILE *fp, char *label, size_t labelsize)
{
- int sb, superblock;
struct fs *fs;
- /*
- * Walk through the standard places that superblocks hide and look
- * for UFS magic. If we find magic, then check that the size in the
- * superblock corresponds to the size of the underlying provider.
- * Finally, look for a volume label and create an appropriate
- * provider based on that.
- */
- for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) {
- fs = (struct fs *)read_buf(fp, superblock, SBLOCKSIZE);
- if (fs == NULL)
- continue;
- /*
- * Check for magic. We also need to check if file system size is equal
- * to providers size, because sysinstall(8) used to bogusly put first
- * partition at offset 0 instead of 16, and glabel/ufs would find file
- * system on slice instead of partition.
- */
-#ifdef notyet
- if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0 &&
- ((pp->mediasize / fs->fs_fsize == fs->fs_old_size) ||
- (pp->mediasize / fs->fs_fsize == fs->fs_providersize))) {
- /* Valid UFS1. */
- } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 &&
- ((pp->mediasize / fs->fs_fsize == fs->fs_size) ||
- (pp->mediasize / fs->fs_fsize == fs->fs_providersize))) {
- /* Valid UFS2. */
- } else {
- g_free(fs);
- continue;
- }
-#else
- if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0) {
- /* Valid UFS1. */
- } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0) {
- /* Valid UFS2. */
- } else {
- free(fs);
- continue;
- }
-#endif
-
- if (fs->fs_sblockloc != superblock || fs->fs_ncg < 1 ||
- fs->fs_bsize < MINBSIZE ||
- (size_t)fs->fs_bsize < sizeof(struct fs)) {
- free(fs);
- continue;
- }
-
+ switch (sbget(fileno(fp), &fs, -1)) {
+ case 0:
strlcpy(label, fs->fs_volname, labelsize);
-
- free(fs);
return (0);
+ case ENOENT:
+ /* Cannot find file system superblock */
+ return (1);
+ default:
+ /* Unable to read file system superblock */
+ return (1);
}
-
- return (1);
}
diff --git a/usr.sbin/quot/Makefile b/usr.sbin/quot/Makefile
index 07bcc7eff1cf..3ec74b02ce5c 100644
--- a/usr.sbin/quot/Makefile
+++ b/usr.sbin/quot/Makefile
@@ -2,6 +2,7 @@
PROG= quot
MAN= quot.8
+LIBADD= ufs
WARNS?= 2
diff --git a/usr.sbin/quot/quot.c b/usr.sbin/quot/quot.c
index 49822e4d84ad..348946ff7dbb 100644
--- a/usr.sbin/quot/quot.c
+++ b/usr.sbin/quot/quot.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <fcntl.h>
#include <fstab.h>
#include <errno.h>
+#include <libufs.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
@@ -535,16 +536,10 @@ usage(void)
exit(1);
}
-/*
- * Possible superblock locations ordered from most to least likely.
- */
-static int sblock_try[] = SBLOCKSEARCH;
-static char superblock[SBLOCKSIZE];
-
void
quot(char *name, char *mp)
{
- int i, fd;
+ int fd;
struct fs *fs;
get_inode(-1, NULL, 0); /* flush cache */
@@ -555,25 +550,15 @@ quot(char *name, char *mp)
close(fd);
return;
}
- for (i = 0; sblock_try[i] != -1; i++) {
- if (lseek(fd, sblock_try[i], 0) != sblock_try[i]) {
- close(fd);
- return;
- }
- if (read(fd, superblock, SBLOCKSIZE) != SBLOCKSIZE) {
- close(fd);
- return;
- }
- fs = (struct fs *)superblock;
- if ((fs->fs_magic == FS_UFS1_MAGIC ||
- (fs->fs_magic == FS_UFS2_MAGIC &&
- fs->fs_sblockloc == sblock_try[i])) &&
- fs->fs_bsize <= MAXBSIZE &&
- fs->fs_bsize >= sizeof(struct fs))
- break;
- }
- if (sblock_try[i] == -1) {
- warnx("%s: not a BSD filesystem",name);
+ switch (sbget(fd, &fs, -1)) {
+ case 0:
+ break;
+ case ENOENT:
+ warn("Cannot find file system superblock");
+ close(fd);
+ return;
+ default:
+ warn("Unable to read file system superblock");
close(fd);
return;
}