Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/ext2fs Several fixes:
details: https://anonhg.NetBSD.org/src/rev/3f05220b95d2
branches: trunk
changeset: 336237:3f05220b95d2
user: maxv <maxv%NetBSD.org@localhost>
date: Fri Feb 20 17:44:54 2015 +0000
description:
Several fixes:
- rename ext2fs_checksb() -> ext2fs_sbcheck(): more consistent
- in ext2fs_sbcheck(), add a check to ensure e2fs_inode_size!=0,
otherwise division by zero
- add ext2fs_sbcompute(), to compute dynamic values of the superblock.
It is done twice in _reload() and _mountfs(), so put it in a function.
- reorder the code in charge of loading the superblock: now, read the
superblock, swap it directly, and *then* pass it to ext2fs_sbcheck().
It is similar to what ffs now does. It is better since the fields don't
need to be swapped on the fly in ext2fs_sbcheck().
Tested on amd64.
diffstat:
sys/ufs/ext2fs/ext2fs_vfsops.c | 159 +++++++++++++++++++---------------------
1 files changed, 77 insertions(+), 82 deletions(-)
diffs (250 lines):
diff -r 18380bfbf53a -r 3f05220b95d2 sys/ufs/ext2fs/ext2fs_vfsops.c
--- a/sys/ufs/ext2fs/ext2fs_vfsops.c Fri Feb 20 17:10:17 2015 +0000
+++ b/sys/ufs/ext2fs/ext2fs_vfsops.c Fri Feb 20 17:44:54 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_vfsops.c,v 1.187 2015/02/19 21:31:44 maxv Exp $ */
+/* $NetBSD: ext2fs_vfsops.c,v 1.188 2015/02/20 17:44:54 maxv Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1994
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.187 2015/02/19 21:31:44 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.188 2015/02/20 17:44:54 maxv Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@@ -104,7 +104,8 @@
MODULE(MODULE_CLASS_VFS, ext2fs, "ffs");
int ext2fs_sbupdate(struct ufsmount *, int);
-static int ext2fs_checksb(struct ext2fs *, int);
+static void ext2fs_sbcompute(struct m_ext2fs *);
+static int ext2fs_sbcheck(struct ext2fs *, int);
static struct sysctllog *ext2fs_sysctl_log;
@@ -534,43 +535,28 @@
VOP_UNLOCK(devvp);
if (error)
panic("ext2fs_reload: dirty1");
- /*
- * Step 2: re-read superblock from disk.
- */
- error = bread(devvp, SBLOCK, SBSIZE, NOCRED, 0, &bp);
- if (error) {
- return (error);
- }
- newfs = (struct ext2fs *)bp->b_data;
- error = ext2fs_checksb(newfs, (mp->mnt_flag & MNT_RDONLY) != 0);
- if (error) {
- brelse(bp, 0);
- return (error);
- }
fs = ump->um_e2fs;
/*
- * copy in new superblock, and compute in-memory values
+ * Step 2: re-read superblock from disk. Copy in new superblock, and compute
+ * in-memory values.
*/
+ error = bread(devvp, SBLOCK, SBSIZE, NOCRED, 0, &bp);
+ if (error)
+ return error;
+ newfs = (struct ext2fs *)bp->b_data;
e2fs_sbload(newfs, &fs->e2fs);
- fs->e2fs_ncg =
- howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
- fs->e2fs.e2fs_bpg);
- fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + LOG_MINBSIZE - DEV_BSHIFT;
- fs->e2fs_bsize = MINBSIZE << fs->e2fs.e2fs_log_bsize;
- fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
- fs->e2fs_qbmask = fs->e2fs_bsize - 1;
- fs->e2fs_bmask = ~fs->e2fs_qbmask;
- fs->e2fs_ngdb =
- howmany(fs->e2fs_ncg, fs->e2fs_bsize / sizeof(struct ext2_gd));
- fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE(fs);
- fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb;
+
brelse(bp, 0);
+ error = ext2fs_sbcheck(&fs->e2fs, (mp->mnt_flag & MNT_RDONLY) != 0);
+ if (error)
+ return error;
+ ext2fs_sbcompute(fs);
+
/*
* Step 3: re-read summary information from disk.
*/
-
for (i = 0; i < fs->e2fs_ngdb; i++) {
error = bread(devvp ,
EXT2_FSBTODB(fs, fs->e2fs.e2fs_first_dblock +
@@ -652,29 +638,30 @@
bp = NULL;
ump = NULL;
-#ifdef DEBUG_EXT2
- printf("ext2 sb size: %zu\n", sizeof(struct ext2fs));
-#endif
+ /* Read the superblock from disk, and swap it directly. */
error = bread(devvp, SBLOCK, SBSIZE, cred, 0, &bp);
if (error)
goto out;
fs = (struct ext2fs *)bp->b_data;
- error = ext2fs_checksb(fs, ronly);
- if (error)
+ m_fs = kmem_zalloc(sizeof(struct m_ext2fs), KM_SLEEP);
+ e2fs_sbload(fs, &m_fs->e2fs);
+
+ brelse(bp, 0);
+ bp = NULL;
+
+ /* Once swapped, validate the superblock. */
+ error = ext2fs_sbcheck(&m_fs->e2fs, ronly);
+ if (error) {
+ kmem_free(m_fs, sizeof(struct m_ext2fs));
goto out;
+ }
+ m_fs->e2fs_ronly = ronly;
+
ump = kmem_zalloc(sizeof(*ump), KM_SLEEP);
ump->um_fstype = UFS1;
ump->um_ops = &ext2fs_ufsops;
- ump->um_e2fs = kmem_zalloc(sizeof(struct m_ext2fs), KM_SLEEP);
- e2fs_sbload((struct ext2fs *)bp->b_data, &ump->um_e2fs->e2fs);
- brelse(bp, 0);
- bp = NULL;
- m_fs = ump->um_e2fs;
- m_fs->e2fs_ronly = ronly;
+ ump->um_e2fs = m_fs;
-#ifdef DEBUG_EXT2
- printf("ext2 ino size %zu\n", EXT2_DINODE_SIZE(m_fs));
-#endif
if (ronly == 0) {
if (m_fs->e2fs.e2fs_state == E2FS_ISCLEAN)
m_fs->e2fs.e2fs_state = 0;
@@ -683,23 +670,12 @@
m_fs->e2fs_fmod = 1;
}
- /* compute dynamic sb infos */
- m_fs->e2fs_ncg =
- howmany(m_fs->e2fs.e2fs_bcount - m_fs->e2fs.e2fs_first_dblock,
- m_fs->e2fs.e2fs_bpg);
- m_fs->e2fs_fsbtodb = m_fs->e2fs.e2fs_log_bsize + LOG_MINBSIZE - DEV_BSHIFT;
- m_fs->e2fs_bsize = MINBSIZE << m_fs->e2fs.e2fs_log_bsize;
- m_fs->e2fs_bshift = LOG_MINBSIZE + m_fs->e2fs.e2fs_log_bsize;
- m_fs->e2fs_qbmask = m_fs->e2fs_bsize - 1;
- m_fs->e2fs_bmask = ~m_fs->e2fs_qbmask;
- m_fs->e2fs_ngdb =
- howmany(m_fs->e2fs_ncg, m_fs->e2fs_bsize / sizeof(struct ext2_gd));
- m_fs->e2fs_ipb = m_fs->e2fs_bsize / EXT2_DINODE_SIZE(m_fs);
- m_fs->e2fs_itpg = m_fs->e2fs.e2fs_ipg / m_fs->e2fs_ipb;
+ /* Compute dynamic sb infos */
+ ext2fs_sbcompute(m_fs);
m_fs->e2fs_gd = kmem_alloc(m_fs->e2fs_ngdb * m_fs->e2fs_bsize, KM_SLEEP);
for (i = 0; i < m_fs->e2fs_ngdb; i++) {
- error = bread(devvp ,
+ error = bread(devvp,
EXT2_FSBTODB(m_fs, m_fs->e2fs.e2fs_first_dblock +
1 /* superblock */ + i),
m_fs->e2fs_bsize, NOCRED, 0, &bp);
@@ -1142,50 +1118,69 @@
return (allerror);
}
+static void
+ext2fs_sbcompute(struct m_ext2fs *fs)
+{
+ fs->e2fs_ncg = howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
+ fs->e2fs.e2fs_bpg);
+ fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + LOG_MINBSIZE - DEV_BSHIFT;
+ fs->e2fs_bsize = MINBSIZE << fs->e2fs.e2fs_log_bsize;
+ fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
+ fs->e2fs_qbmask = fs->e2fs_bsize - 1;
+ fs->e2fs_bmask = ~fs->e2fs_qbmask;
+ fs->e2fs_ngdb =
+ howmany(fs->e2fs_ncg, fs->e2fs_bsize / sizeof(struct ext2_gd));
+ fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE(fs);
+ fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb;
+}
+
+/*
+ * NOTE: here, the superblock is already swapped.
+ */
static int
-ext2fs_checksb(struct ext2fs *fs, int ronly)
+ext2fs_sbcheck(struct ext2fs *fs, int ronly)
{
uint32_t u32;
- if (fs2h16(fs->e2fs_magic) != E2FS_MAGIC) {
- return (EINVAL); /* XXX needs translation */
+ if (fs->e2fs_magic != E2FS_MAGIC)
+ return EINVAL;
+ if (fs->e2fs_rev > E2FS_REV1) {
+ printf("ext2fs: unsupported revision number: %x\n", fs->e2fs_rev);
+ return EINVAL;
}
- if (fs2h32(fs->e2fs_rev) > E2FS_REV1) {
- printf("ext2fs: unsupported revision number: %x\n",
- fs2h32(fs->e2fs_rev));
- return (EINVAL); /* XXX needs translation */
- }
- if (fs2h32(fs->e2fs_log_bsize) > 2) { /* block size = 1024|2048|4096 */
- printf("ext2fs: bad block size: %d "
- "(expected <= 2 for ext2 fs)\n",
- fs2h32(fs->e2fs_log_bsize));
- return (EINVAL); /* XXX needs translation */
+ if (fs->e2fs_log_bsize > 2) {
+ /* block size = 1024|2048|4096 */
+ printf("ext2fs: bad block size: %d\n", fs->e2fs_log_bsize);
+ return EINVAL;
}
if (fs->e2fs_bpg == 0) {
printf("ext2fs: zero blocks per group\n");
return EINVAL;
}
-
- if (fs2h32(fs->e2fs_rev) > E2FS_REV0) {
+
+ if (fs->e2fs_rev > E2FS_REV0) {
char buf[256];
- if (fs2h32(fs->e2fs_first_ino) != EXT2_FIRSTINO) {
+ if (fs->e2fs_first_ino != EXT2_FIRSTINO) {
printf("ext2fs: unsupported first inode position\n");
- return (EINVAL); /* XXX needs translation */
+ return EINVAL;
}
- u32 = fs2h32(fs->e2fs_features_incompat) & ~EXT2F_INCOMPAT_SUPP;
+ u32 = fs->e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP;
if (u32) {
snprintb(buf, sizeof(buf), EXT2F_INCOMPAT_BITS, u32);
- printf("ext2fs: unsupported incompat features: %s\n",
- buf);
- return EINVAL; /* XXX needs translation */
+ printf("ext2fs: unsupported incompat features: %s\n", buf);
+ return EINVAL;
}
- u32 = fs2h32(fs->e2fs_features_rocompat) & ~EXT2F_ROCOMPAT_SUPP;
+ u32 = fs->e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP;
if (!ronly && u32) {
snprintb(buf, sizeof(buf), EXT2F_ROCOMPAT_BITS, u32);
printf("ext2fs: unsupported ro-incompat features: %s\n",
buf);
- return EROFS; /* XXX needs translation */
+ return EROFS;
+ }
+ if (fs->e2fs_inode_size == 0) {
+ printf("ext2fs: bad inode size\n");
+ return EINVAL;
}
}
- return (0);
+ return 0;
}
Home |
Main Index |
Thread Index |
Old Index