aboutsummaryrefslogtreecommitdiff
path: root/sys/ufs/ffs
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 /sys/ufs/ffs
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
Diffstat (limited to 'sys/ufs/ffs')
-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
4 files changed, 292 insertions, 123 deletions
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 */