aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2018-01-26 00:58:32 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2018-01-26 00:58:32 +0000
commitdffce2150eeac1c7f424324a5cade7a97b308979 (patch)
tree3de8c223a1cb007078f3bb3e3c062127eb1b80a8
parenta99028fc70be602db425c092b70dd0221e253bb3 (diff)
downloadsrc-dffce2150eeac1c7f424324a5cade7a97b308979.tar.gz
src-dffce2150eeac1c7f424324a5cade7a97b308979.zip
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
Notes
Notes: svn path=/head/; revision=328426
-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;
}