aboutsummaryrefslogtreecommitdiff
path: root/lib/libufs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libufs')
-rw-r--r--lib/libufs/Makefile8
-rw-r--r--lib/libufs/Makefile.depend1
-rw-r--r--lib/libufs/block.c50
-rw-r--r--lib/libufs/bread.32
-rw-r--r--lib/libufs/cgread.32
-rw-r--r--lib/libufs/cgroup.c9
-rw-r--r--lib/libufs/getinode.32
-rw-r--r--lib/libufs/inode.c33
-rw-r--r--lib/libufs/libufs.34
-rw-r--r--lib/libufs/libufs.h73
-rw-r--r--lib/libufs/sblock.c116
-rw-r--r--lib/libufs/sbread.383
-rw-r--r--lib/libufs/type.c19
-rw-r--r--lib/libufs/ufs_disk_close.311
14 files changed, 270 insertions, 143 deletions
diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile
index a767546f457f..3b1911d7a5cd 100644
--- a/lib/libufs/Makefile
+++ b/lib/libufs/Makefile
@@ -1,9 +1,9 @@
-# $FreeBSD$
+PACKAGE= ufs
+LIB_PACKAGE=
-PACKAGE= runtime
LIB= ufs
SHLIBDIR?= /lib
-SHLIB_MAJOR= 7
+SHLIB_MAJOR= 8
SRCS= block.c cgroup.c gsb_crc32.c inode.c sblock.c type.c ffs_subr.c
SRCS+= ffs_tables.c
@@ -20,6 +20,8 @@ MLINKS+= cgread.3 cgput.3
MLINKS+= getinode.3 putinode.3
MLINKS+= sbread.3 sbwrite.3
MLINKS+= sbread.3 sbget.3
+MLINKS+= sbread.3 sbsearch.3
+MLINKS+= sbread.3 sbfind.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
diff --git a/lib/libufs/Makefile.depend b/lib/libufs/Makefile.depend
index 8d409f5263ac..6ef78fac5cbf 100644
--- a/lib/libufs/Makefile.depend
+++ b/lib/libufs/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/lib/libufs/block.c b/lib/libufs/block.c
index 3c99d288a402..8bccc18ed3dd 100644
--- a/lib/libufs/block.c
+++ b/lib/libufs/block.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 Juli Mallett. All rights reserved.
*
@@ -27,9 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/disk.h>
@@ -59,19 +56,10 @@ bread(struct uufsd *disk, ufs2_daddr_t blockno, void *data, size_t size)
ERROR(disk, NULL);
- p2 = data;
- /*
- * XXX: various disk controllers require alignment of our buffer
- * XXX: which is stricter than struct alignment.
- * XXX: Bounce the buffer if not 64 byte aligned.
- * XXX: this can be removed if/when the kernel is fixed
- */
- if (((intptr_t)data) & 0x3f) {
- p2 = malloc(size);
- if (p2 == NULL) {
- ERROR(disk, "allocate bounce buffer");
- goto fail;
- }
+ BUF_MALLOC(&p2, data, size);
+ if (p2 == NULL) {
+ ERROR(disk, "allocate bounce buffer");
+ goto fail;
}
cnt = pread(disk->d_fd, p2, size, (off_t)(blockno * disk->d_bsize));
if (cnt == -1) {
@@ -103,7 +91,7 @@ bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
{
ssize_t cnt;
int rv;
- void *p2 = NULL;
+ void *p2;
ERROR(disk, NULL);
@@ -112,24 +100,15 @@ bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
ERROR(disk, "failed to open disk for writing");
return (-1);
}
-
- /*
- * XXX: various disk controllers require alignment of our buffer
- * XXX: which is stricter than struct alignment.
- * XXX: Bounce the buffer if not 64 byte aligned.
- * XXX: this can be removed if/when the kernel is fixed
- */
- if (((intptr_t)data) & 0x3f) {
- p2 = malloc(size);
- if (p2 == NULL) {
- ERROR(disk, "allocate bounce buffer");
- return (-1);
- }
- memcpy(p2, data, size);
- data = p2;
+ BUF_MALLOC(&p2, data, size);
+ if (p2 == NULL) {
+ ERROR(disk, "allocate bounce buffer");
+ return (-1);
}
- cnt = pwrite(disk->d_fd, data, size, (off_t)(blockno * disk->d_bsize));
- if (p2 != NULL)
+ if (p2 != data)
+ memcpy(p2, data, size);
+ cnt = pwrite(disk->d_fd, p2, size, (off_t)(blockno * disk->d_bsize));
+ if (p2 != data)
free(p2);
if (cnt == -1) {
ERROR(disk, "write error to block device");
@@ -139,7 +118,6 @@ bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
ERROR(disk, "short write to block device");
return (-1);
}
-
return (cnt);
}
diff --git a/lib/libufs/bread.3 b/lib/libufs/bread.3
index 9109166bea49..b3a61b4a5325 100644
--- a/lib/libufs/bread.3
+++ b/lib/libufs/bread.3
@@ -7,8 +7,6 @@
.\"
.\" This file is in the public domain.
.\"
-.\" $FreeBSD$
-.\"
.Dd June 4, 2003
.Dt BREAD 3
.Os
diff --git a/lib/libufs/cgread.3 b/lib/libufs/cgread.3
index cbc633708506..78a62f75e82b 100644
--- a/lib/libufs/cgread.3
+++ b/lib/libufs/cgread.3
@@ -11,8 +11,6 @@
.\"
.\" This file is in the public domain.
.\"
-.\" $FreeBSD$
-.\"
.Dd September 2, 2020
.Dt CGREAD 3
.Os
diff --git a/lib/libufs/cgroup.c b/lib/libufs/cgroup.c
index 90b28eadad2c..7c7ca0d242b4 100644
--- a/lib/libufs/cgroup.c
+++ b/lib/libufs/cgroup.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2003 Juli Mallett. All rights reserved.
*
@@ -27,9 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/disklabel.h>
@@ -268,6 +265,10 @@ cgwrite1(struct uufsd *disk, int cg)
static char errmsg[BUFSIZ];
if (cg == disk->d_cg.cg_cgx) {
+ if (ufs_disk_write(disk) == -1) {
+ ERROR(disk, "failed to open disk for writing");
+ return (-1);
+ }
if (cgput(disk->d_fd, &disk->d_fs, &disk->d_cg) == 0)
return (0);
ERROR(disk, NULL);
diff --git a/lib/libufs/getinode.3 b/lib/libufs/getinode.3
index fde249e86102..1668e65551e5 100644
--- a/lib/libufs/getinode.3
+++ b/lib/libufs/getinode.3
@@ -7,8 +7,6 @@
.\"
.\" This file is in the public domain.
.\"
-.\" $FreeBSD$
-.\"
.Dd September 2, 2020
.Dt GETINODE 3
.Os
diff --git a/lib/libufs/inode.c b/lib/libufs/inode.c
index c4a0cab9e95a..863e71867daa 100644
--- a/lib/libufs/inode.c
+++ b/lib/libufs/inode.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 Juli Mallett. All rights reserved.
*
@@ -27,9 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/disklabel.h>
@@ -46,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <libufs.h>
@@ -56,6 +54,7 @@ getinode(struct uufsd *disk, union dinodep *dp, ino_t inum)
ino_t min, max;
caddr_t inoblock;
struct fs *fs;
+ struct timespec now;
ERROR(disk, NULL);
@@ -64,17 +63,13 @@ getinode(struct uufsd *disk, union dinodep *dp, ino_t inum)
ERROR(disk, "inode number out of range");
return (-1);
}
- inoblock = disk->d_inoblock;
+ inoblock = (caddr_t)&disk->d_inos[0];
min = disk->d_inomin;
max = disk->d_inomax;
- if (inoblock == NULL) {
- inoblock = malloc(fs->fs_bsize);
- if (inoblock == NULL) {
- ERROR(disk, "unable to allocate inode block");
- return (-1);
- }
- disk->d_inoblock = inoblock;
+ if (clock_gettime(CLOCK_REALTIME_FAST, &now) != 0) {
+ ERROR(disk, "cannot get current time of day");
+ return (-1);
}
if (inum >= min && inum < max)
goto gotit;
@@ -85,6 +80,8 @@ getinode(struct uufsd *disk, union dinodep *dp, ino_t inum)
gotit: switch (disk->d_ufs) {
case 1:
disk->d_dp.dp1 = &((struct ufs1_dinode *)inoblock)[inum - min];
+ if (ffs_oldfscompat_inode_read(fs, disk->d_dp, now.tv_sec))
+ putinode(disk);
if (dp != NULL)
*dp = disk->d_dp;
return (0);
@@ -92,8 +89,12 @@ gotit: switch (disk->d_ufs) {
disk->d_dp.dp2 = &((struct ufs2_dinode *)inoblock)[inum - min];
if (dp != NULL)
*dp = disk->d_dp;
- if (ffs_verify_dinode_ckhash(fs, disk->d_dp.dp2) == 0)
+ if (ffs_verify_dinode_ckhash(fs, disk->d_dp.dp2) == 0) {
+ if (ffs_oldfscompat_inode_read(fs, disk->d_dp,
+ now.tv_sec))
+ putinode(disk);
return (0);
+ }
ERROR(disk, "check-hash failed for inode read from disk");
return (-1);
default:
@@ -109,14 +110,10 @@ putinode(struct uufsd *disk)
struct fs *fs;
fs = &disk->d_fs;
- if (disk->d_inoblock == NULL) {
- ERROR(disk, "No inode block allocated");
- return (-1);
- }
if (disk->d_ufs == 2)
ffs_update_dinode_ckhash(fs, disk->d_dp.dp2);
if (bwrite(disk, fsbtodb(fs, ino_to_fsba(&disk->d_fs, disk->d_inomin)),
- disk->d_inoblock, disk->d_fs.fs_bsize) <= 0)
+ (caddr_t)&disk->d_inos[0], disk->d_fs.fs_bsize) <= 0)
return (-1);
return (0);
}
diff --git a/lib/libufs/libufs.3 b/lib/libufs/libufs.3
index 578b63d87345..aa3386ad9771 100644
--- a/lib/libufs/libufs.3
+++ b/lib/libufs/libufs.3
@@ -5,8 +5,6 @@
.\"
.\" This file is in the public domain.
.\"
-.\" $FreeBSD$
-.\"
.Dd September 2, 2020
.Dt LIBUFS 3
.Os
@@ -72,7 +70,7 @@ to a string describing the error.
.Xr ufs_disk_fillout 3 ,
.Xr ufs_disk_fillout_blank 3 ,
.Xr ufs_disk_write 3 ,
-.Xr ffs 7
+.Xr ffs 4
.Sh HISTORY
The
.Xr libufs 3
diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h
index 63a8dc170997..bb92e082a875 100644
--- a/lib/libufs/libufs.h
+++ b/lib/libufs/libufs.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 Juli Mallett. All rights reserved.
*
@@ -25,57 +25,69 @@
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
*/
#ifndef __LIBUFS_H__
#define __LIBUFS_H__
+#include <stdbool.h>
/*
- * libufs structures.
+ * Various disk controllers require their buffers to be aligned to the size
+ * of a cache line. The LIBUFS_BUFALIGN defines the required alignment size.
+ * The alignment must be a power of 2.
*/
-union dinodep {
- struct ufs1_dinode *dp1;
- struct ufs2_dinode *dp2;
-};
+#define LIBUFS_BUFALIGN 128
/*
* userland ufs disk.
*/
struct uufsd {
- const char *d_name; /* disk name */
- int d_ufs; /* decimal UFS version */
- int d_fd; /* raw device file descriptor */
- long d_bsize; /* device bsize */
- ufs2_daddr_t d_sblock; /* superblock location */
- struct fs_summary_info *d_si; /* Superblock summary info */
- caddr_t d_inoblock; /* inode block */
- uint32_t d_inomin; /* low ino, not ino_t for ABI compat */
- uint32_t d_inomax; /* high ino, not ino_t for ABI compat */
- union dinodep d_dp; /* pointer to currently active inode */
union {
struct fs d_fs; /* filesystem information */
- char d_sb[MAXBSIZE]; /* superblock as buffer */
- } d_sbunion;
+ char d_sb[SBLOCKSIZE]; /* superblock as buffer */
+ } d_sbunion __aligned(LIBUFS_BUFALIGN);
union {
struct cg d_cg; /* cylinder group */
char d_buf[MAXBSIZE]; /* cylinder group storage */
- } d_cgunion;
- int d_ccg; /* current cylinder group */
- int d_lcg; /* last cylinder group (in d_cg) */
+ } d_cgunion __aligned(LIBUFS_BUFALIGN);
+ union {
+ union dinodep d_ino[1]; /* inode block */
+ char d_inos[MAXBSIZE]; /* inode block as buffer */
+ } d_inosunion __aligned(LIBUFS_BUFALIGN);
+ const char *d_name; /* disk name */
const char *d_error; /* human readable disk error */
- int d_mine; /* internal flags */
+ ufs2_daddr_t d_sblock; /* superblock location */
+ struct fs_summary_info *d_si; /* Superblock summary info */
+ union dinodep d_dp; /* pointer to currently active inode */
+ ino_t d_inomin; /* low ino */
+ ino_t d_inomax; /* high ino */
+ off_t d_sblockloc; /* where to look for the superblock */
+ int64_t d_bsize; /* device bsize */
+ int64_t d_lookupflags; /* flags to superblock lookup */
+ int64_t d_mine; /* internal flags */
+ int32_t d_ccg; /* current cylinder group */
+ int32_t d_ufs; /* decimal UFS version */
+ int32_t d_fd; /* raw device file descriptor */
+ int32_t d_lcg; /* last cylinder group (in d_cg) */
+};
+#define d_inos d_inosunion.d_inos
#define d_fs d_sbunion.d_fs
-#define d_sb d_sbunion.d_sb
#define d_cg d_cgunion.d_cg
-};
/*
* libufs macros (internal, non-exported).
*/
#ifdef _LIBUFS
/*
+ * Ensure that the buffer is aligned to the I/O subsystem requirements.
+ */
+#define BUF_MALLOC(newbufpp, data, size) { \
+ if (data != NULL && (((intptr_t)data) & (LIBUFS_BUFALIGN - 1)) == 0) \
+ *newbufpp = (void *)data; \
+ else \
+ *newbufpp = aligned_alloc(LIBUFS_BUFALIGN, size); \
+}
+/*
* Trace steps through libufs, to be used at entry and erroneous return.
*/
static inline void
@@ -109,8 +121,11 @@ 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);
+bool ffs_oldfscompat_inode_read(struct fs *, union dinodep, time_t);
+int ffs_sbsearch(void *, struct fs **, int, char *,
+ int (*)(void *, off_t, void **, int));
void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
-int ffs_sbget(void *, struct fs **, off_t, char *,
+int ffs_sbget(void *, struct fs **, off_t, int, char *,
int (*)(void *, off_t, void **, int));
int ffs_sbput(void *, struct fs *, off_t,
int (*)(void *, off_t, void *, int));
@@ -147,9 +162,11 @@ int putinode(struct uufsd *);
* sblock.c
*/
int sbread(struct uufsd *);
+int sbfind(struct uufsd *, int);
int sbwrite(struct uufsd *, int);
/* low level superblock read/write functions */
-int sbget(int, struct fs **, off_t);
+int sbget(int, struct fs **, off_t, int);
+int sbsearch(int, struct fs **, int);
int sbput(int, struct fs *, int);
/*
diff --git a/lib/libufs/sblock.c b/lib/libufs/sblock.c
index 3b65e79b02b5..09d478bfe71e 100644
--- a/lib/libufs/sblock.c
+++ b/lib/libufs/sblock.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 Juli Mallett. All rights reserved.
*
@@ -27,9 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/disklabel.h>
@@ -49,21 +46,70 @@ __FBSDID("$FreeBSD$");
#include <libufs.h>
+static int handle_disk_read(struct uufsd *, struct fs *, int);
+
+/*
+ * Read the standard superblock.
+ *
+ * The following option flags can be or'ed into disk->d_lookupflags:
+ *
+ * UFS_NOMSG indicates that superblock inconsistency error messages
+ * should not be printed.
+ *
+ * UFS_NOCSUM causes only the superblock itself to be returned, but does
+ * not read in any auxillary data structures like the cylinder group
+ * summary information.
+ */
int
sbread(struct uufsd *disk)
{
struct fs *fs;
+ int error;
- ERROR(disk, NULL);
+ error = sbget(disk->d_fd, &fs, disk->d_sblockloc, disk->d_lookupflags);
+ return (handle_disk_read(disk, fs, error));
+}
- if ((errno = sbget(disk->d_fd, &fs, STDSB)) != 0) {
- switch (errno) {
+/*
+ * Make an extensive search to find a superblock. If the superblock
+ * in the standard place cannot be used, try looking for one of the
+ * backup superblocks.
+ *
+ * The flags parameter is made up of the following or'ed together options:
+ *
+ * UFS_NOMSG indicates that superblock inconsistency error messages
+ * should not be printed.
+ *
+ * UFS_NOCSUM causes only the superblock itself to be returned, but does
+ * not read in any auxillary data structures like the cylinder group
+ * summary information.
+ */
+int
+sbfind(struct uufsd *disk, int flags)
+{
+ struct fs *fs;
+ int error;
+
+ error = sbsearch(disk->d_fd, &fs, flags);
+ return (handle_disk_read(disk, fs, error));
+}
+
+static int
+handle_disk_read(struct uufsd *disk, struct fs *fs, int error)
+{
+
+ ERROR(disk, NULL);
+ if (error != 0) {
+ switch (error) {
case EIO:
ERROR(disk, "non-existent or truncated superblock");
break;
case ENOENT:
ERROR(disk, "no usable known superblock found");
break;
+ case EINTEGRITY:
+ ERROR(disk, "superblock check-hash failure");
+ break;
case ENOSPC:
ERROR(disk, "failed to allocate space for superblock "
"information");
@@ -133,14 +179,43 @@ 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);
/*
+ * The following two functions read a superblock. Their flags
+ * parameter are made up of the following or'ed together options:
+ *
+ * UFS_NOMSG indicates that superblock inconsistency error messages
+ * should not be printed.
+ *
+ * UFS_NOCSUM causes only the superblock itself to be returned, but does
+ * not read in any auxillary data structures like the cylinder group
+ * summary information.
+ *
* Read a superblock from the devfd device allocating memory returned
- * in fsp. Also read the superblock summary information.
+ * in fsp.
*/
int
-sbget(int devfd, struct fs **fsp, off_t sblockloc)
+sbget(int devfd, struct fs **fsp, off_t sblockloc, int flags)
{
+ int error;
- return (ffs_sbget(&devfd, fsp, sblockloc, "user", use_pread));
+ error = ffs_sbget(&devfd, fsp, sblockloc, flags, "user", use_pread);
+ fflush(NULL); /* flush any messages */
+ return (error);
+}
+
+/*
+ * Make an extensive search of the devfd device to find a superblock.
+ * If the superblock in the standard place cannot be used, try looking
+ * for one of the backup superblocks. If found, memory is allocated and
+ * returned in fsp.
+ */
+int
+sbsearch(int devfd, struct fs **fsp, int flags)
+{
+ int error;
+
+ error = ffs_sbsearch(&devfd, fsp, flags, "user", use_pread);
+ fflush(NULL); /* flush any messages */
+ return (error);
}
/*
@@ -152,7 +227,8 @@ use_pread(void *devfd, off_t loc, void **bufp, int size)
int fd;
fd = *(int *)devfd;
- if ((*bufp = malloc(size)) == NULL)
+ BUF_MALLOC(bufp, NULL, size);
+ if (*bufp == NULL)
return (ENOSPC);
if (pread(fd, *bufp, size, loc) != size)
return (EIO);
@@ -174,25 +250,29 @@ sbput(int devfd, struct fs *fs, int numaltwrite)
off_t savedactualloc;
int i, error;
- if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc,
- use_pwrite)) != 0)
+ error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc, use_pwrite);
+ fflush(NULL); /* flush any messages */
+ if (error != 0 || numaltwrite == 0)
return (error);
- if (numaltwrite == 0)
- return (0);
savedactualloc = fs->fs_sblockactualloc;
- savedcsp = fs->fs_csp;
- fs->fs_csp = NULL;
+ if (fs->fs_si != NULL) {
+ 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) {
+ fflush(NULL); /* flush any messages */
fs->fs_sblockactualloc = savedactualloc;
fs->fs_csp = savedcsp;
return (error);
}
}
fs->fs_sblockactualloc = savedactualloc;
- fs->fs_csp = savedcsp;
+ if (fs->fs_si != NULL)
+ fs->fs_csp = savedcsp;
+ fflush(NULL); /* flush any messages */
return (0);
}
diff --git a/lib/libufs/sbread.3 b/lib/libufs/sbread.3
index e97469f86873..47c32ce029ae 100644
--- a/lib/libufs/sbread.3
+++ b/lib/libufs/sbread.3
@@ -3,19 +3,19 @@
.\" Description:
.\" Manual page for libufs functions:
.\" sbget(3)
+.\" sbsearch(3)
.\" sbput(3)
.\" sbread(3)
+.\" sbfind(3)
.\" sbwrite(3)
.\"
.\" This file is in the public domain.
.\"
-.\" $FreeBSD$
-.\"
-.Dd September 2, 2020
+.Dd August 8, 2022
.Dt SBREAD 3
.Os
.Sh NAME
-.Nm sbget , sbput , sbread , sbwrite
+.Nm sbget , sbsearch , sbput , sbread , sbfind , sbwrite
.Nd read and write superblocks of a UFS file system
.Sh LIBRARY
.Lb libufs
@@ -27,18 +27,24 @@
.In ufs/ffs/fs.h
.In libufs.h
.Ft int
-.Fn sbget "int devfd" "struct fs **fsp" "off_t sblockloc"
+.Fn sbget "int devfd" "struct fs **fsp" "off_t sblockloc" "int flags"
+.Ft int
+.Fn sbsearch "int devfd" "struct fs **fsp" "int flags"
.Ft int
.Fn sbput "int devfd" "struct fs *fs" "int numaltwrite"
.Ft int
.Fn sbread "struct uufsd *disk"
.Ft int
+.Fn sbfind "struct uufsd *disk" "int flags"
+.Ft int
.Fn sbwrite "struct uufsd *disk" "int all"
.Sh DESCRIPTION
The
-.Fn sbget
+.Fn sbget ,
+.Fn sbsearch ,
+.Fn sbread ,
and
-.Fn sbread
+.Fn sbfind
functions provide superblock reads for
.Xr libufs 3
consumers.
@@ -52,7 +58,9 @@ consumers.
.Pp
The
.Fn sbget
-function first allocates a buffer to hold the superblock.
+and
+.Fn sbsearch
+functions first allocate a buffer to hold the superblock.
Using the
.Va devfd
file descriptor that references the filesystem disk,
@@ -60,11 +68,43 @@ file descriptor that references the filesystem disk,
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
+The value
+.Cm UFS_STDSB
+may be specified for
+.Va sblockloc
+to request that the standard location for the superblock be read.
+The
+.Fn sbsearch
+function uses the
+.Va devfd
+file descriptor that references the filesystem disk,
+to search first for the superblock at the standard location.
+If it is not found or is too damaged to use
+.Fn sbsearch
+will attempt to find one of the filesystem's alternate superblocks.
+Flags are specified by
+.Em or Ns 'ing
+the following values:
+.Pp
+.Bl -tag -width UFS_NOCSUM
+.It Cm UFS_NOCSUM
+Causes only the superblock itself to be returned, but does not read in any
+auxiliary data structures like the cylinder group summary information.
+.It Cm UFS_NOMSG
+Indicates that superblock inconsistency error messages should not be printed.
+.El
+.Pp
+If successful,
+.Fn sbget
+and
+.Fn sbsearch
+functions return a pointer to the buffer containing the superblock in
.Va fsp .
The
.Fn sbget
-function is safe to use in threaded applications.
+and
+.Fn sbsearch
+functions are safe to use in threaded applications.
.Pp
The
.Fn sbput
@@ -93,7 +133,19 @@ modified and the on-disk copy needs to be updated.
.Pp
The
.Fn sbread
-function reads the standard filesystem superblock into the
+function reads the standard filesystem superblock.
+The
+.Fn sbfind
+function tries to find a usable superblock.
+It searchs first for the superblock at the standard location.
+If it is not found or is too damaged to use
+.Fn sbfind
+will attempt to find one of the filesystem's alternate superblocks.
+If successful
+.Fn sbread
+and
+.Fn sbfind
+return a superblock in the
.Va d_sb ,
structure embedded in the given user-land UFS disk structure.
.Pp
@@ -111,16 +163,19 @@ value is non-zero.
.Sh RETURN VALUES
.Rv -std sbread sbwrite
The
-.Fn sbget
+.Fn sbget ,
+.Fn sbsearch ,
and
.Fn sbput
functions return the value 0 if successful;
otherwise they return one of the errors described below.
.Sh ERRORS
The errors returned by
-.Fn sbget
+.Fn sbget ,
+.Fn sbsearch ,
+.Fn sbread ,
and
-.Fn sbread
+.Fn sbfind ,
include any of the errors specified for the library function
.Xr bread 3 .
Additionally, they may follow the
diff --git a/lib/libufs/type.c b/lib/libufs/type.c
index a060f8ec5abf..557e6cdead63 100644
--- a/lib/libufs/type.c
+++ b/lib/libufs/type.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 Juli Mallett. All rights reserved.
*
@@ -27,9 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/disklabel.h>
@@ -63,10 +60,6 @@ ufs_disk_close(struct uufsd *disk)
ERROR(disk, NULL);
close(disk->d_fd);
disk->d_fd = -1;
- if (disk->d_inoblock != NULL) {
- free(disk->d_inoblock);
- disk->d_inoblock = NULL;
- }
if (disk->d_mine & MINE_NAME) {
free((char *)(uintptr_t)disk->d_name);
disk->d_name = NULL;
@@ -157,10 +150,16 @@ again: if ((ret = stat(name, &st)) < 0) {
return (-1);
}
+ if (((uintptr_t)disk & ~(LIBUFS_BUFALIGN - 1)) != (uintptr_t)disk) {
+ ERROR(disk, "uufsd structure must be aligned to "
+ "LIBUFS_BUFALIGN byte boundry, see ufs_disk_fillout(3)");
+ close(fd);
+ return (-1);
+ }
+
disk->d_bsize = 1;
disk->d_ccg = 0;
disk->d_fd = fd;
- disk->d_inoblock = NULL;
disk->d_inomin = 0;
disk->d_inomax = 0;
disk->d_lcg = 0;
@@ -168,6 +167,8 @@ again: if ((ret = stat(name, &st)) < 0) {
disk->d_ufs = 0;
disk->d_error = NULL;
disk->d_si = NULL;
+ disk->d_sblockloc = UFS_STDSB;
+ disk->d_lookupflags = 0;
if (oname != name) {
name = strdup(name);
diff --git a/lib/libufs/ufs_disk_close.3 b/lib/libufs/ufs_disk_close.3
index d01e302d98df..f332a9bb5de9 100644
--- a/lib/libufs/ufs_disk_close.3
+++ b/lib/libufs/ufs_disk_close.3
@@ -9,9 +9,7 @@
.\"
.\" This file is in the public domain.
.\"
-.\" $FreeBSD$
-.\"
-.Dd June 4, 2003
+.Dd November 17, 2023
.Dt UFS_DISK_CLOSE 3
.Os
.Sh NAME
@@ -53,6 +51,13 @@ functions open a disk specified by
.Fa name
and populate the structure pointed to by
.Fa disk .
+The structure referenced by the
+.Fa disk
+pointer must be aligned to at least the alignment specified by
+.Dv LIBUFS_ALIGN
+that is defined in the
+.Lb libufs.h
+header file.
The disk is opened read-only.
The specified
.Fa name