tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: panic ffs_valloc dup_alloc
In article <201712132230.vBDMU37I021442%sdf.org@localhost>,
Stephen M. Jones <martians%sdf.org@localhost> wrote:
>
>I have NetBSD-7 deployed on many systems (the majority being amd64) and
>have noticed that the busy machines (smtpd, imapd, httpd) tend to develop
>filesystem inconsistencies that get worse with time. The inconsistencies
>usually result in a panic: ffs_valloc: dup_alloc.
>
>Bringing the machine up in single user and doing several fsck -f -y on
>the file system will clear these problems for a while, but they'll develop
>again.
>
>In some cases the filesystem corruption can only be corrected by a newfs.
>
>I have crash dumps console output with messages like the following:
>
>panic: ffs_valloc: dup alloc
>dmode 8180 mode 8180 dgen 1ee653a5 gen 1ee653a5
>size 0 blocks 0
>ino 9439504 ipref 9439135
>panic: ffs_valloc: dup alloc
>cpu0: Begin traceback...
>vpanic() at netbsd:vpanic+0x13c
>snprintf() at netbsd:snprintf
>ffs_valloc() at netbsd:ffs_valloc+0x889
>ufs_makeinode() at netbsd:ufs_makeinode+0x5e
>ufs_create() at netbsd:ufs_create+0x5b
>VOP_CREATE() at netbsd:VOP_CREATE+0x38
>vn_open() at netbsd:vn_open+0x330
>do_open() at netbsd:do_open+0x111
>do_sys_openat() at netbsd:do_sys_openat+0x68
>sys_open() at netbsd:sys_open+0x24
>syscall() at netbsd:syscall+0x9a
>
>I've seen this problem since NetBSD-6. Again, this is on busy servers and
>not idle machines.
I am guessing this is ffs2... Try this:
christos
Index: ffs_alloc.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_alloc.c,v
retrieving revision 1.146.2.1
diff -u -u -r1.146.2.1 ffs_alloc.c
--- ffs_alloc.c 14 Aug 2015 05:29:14 -0000 1.146.2.1
+++ ffs_alloc.c 14 Dec 2017 20:09:22 -0000
@@ -615,29 +615,21 @@
KASSERT((*vpp)->v_type == VNON);
ip = VTOI(*vpp);
if (ip->i_mode) {
-#if 0
- printf("mode = 0%o, inum = %d, fs = %s\n",
- ip->i_mode, ip->i_number, fs->fs_fsmnt);
-#else
- printf("dmode %x mode %x dgen %x gen %x\n",
- DIP(ip, mode), ip->i_mode,
- DIP(ip, gen), ip->i_gen);
- printf("size %llx blocks %llx\n",
- (long long)DIP(ip, size), (long long)DIP(ip, blocks));
- printf("ino %llu ipref %llu\n", (unsigned long long)ino,
- (unsigned long long)ipref);
-#if 0
- error = bread(ump->um_devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ino)),
- (int)fs->fs_bsize, NOCRED, 0, &bp);
-#endif
-
-#endif
- panic("ffs_valloc: dup alloc");
- }
- if (DIP(ip, blocks)) { /* XXX */
- printf("free inode %llu on %s had %" PRId64 " blocks\n",
- (unsigned long long)ino, fs->fs_fsmnt, DIP(ip, blocks));
+ panic("%s: dup alloc ino=%" PRId64 " on %s: mode %x/%x "
+ "gen %x/%x size %" PRIx64 " blocks %" PRIx64,
+ __func__, ino, fs->fs_fsmnt, DIP(ip, mode), ip->i_mode,
+ DIP(ip, gen), ip->i_gen, DIP(ip, size), DIP(ip, blocks));
+ }
+ if (DIP(ip, size) || DIP(ip, blocks)) {
+ printf("%s: ino=%" PRId64 " on %s: "
+ "gen %x/%x has non zero blocks %" PRIx64 " or size %"
+ PRIx64 "\n",
+ __func__, ino, fs->fs_fsmnt, DIP(ip, gen), ip->i_gen,
+ DIP(ip, blocks), DIP(ip, size));
+ if ((ip)->i_ump->um_fstype == UFS1)
+ panic("%s: dirty filesystem?", __func__);
DIP_ASSIGN(ip, blocks, 0);
+ DIP_ASSIGN(ip, size, 0);
}
ip->i_flag &= ~IN_SPACECOUNTED;
ip->i_flags = 0;
Index: ffs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.299.2.4
diff -u -u -r1.299.2.4 ffs_vfsops.c
--- ffs_vfsops.c 27 Aug 2016 15:17:34 -0000 1.299.2.4
+++ ffs_vfsops.c 14 Dec 2017 20:09:22 -0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_vfsops.c,v 1.299.2.4 2016/08/27 15:17:34 bouyer Exp $ */
+/* $NetBSD: ffs_vfsops.c,v 1.339 2016/06/19 22:41:31 christos Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -182,6 +182,54 @@
};
static int
+ffs_checkrange(struct mount *mp, uint32_t ino)
+{
+ struct fs *fs = VFSTOUFS(mp)->um_fs;
+
+ if (ino < UFS_ROOTINO || ino >= fs->fs_ncg * fs->fs_ipg) {
+ DPRINTF("out of range %u\n", ino);
+ return ESTALE;
+ }
+
+ /*
+ * Need to check if inode is initialized because ffsv2 does
+ * lazy initialization and we can get here from nfs_fhtovp
+ */
+ if (fs->fs_magic != FS_UFS2_MAGIC)
+ return 0;
+
+ struct buf *bp;
+ int cg = ino_to_cg(fs, ino);
+ struct ufsmount *ump = VFSTOUFS(mp);
+
+ int error = bread(ump->um_devvp, FFS_FSBTODB(fs, cgtod(fs, cg)),
+ (int)fs->fs_cgsize, B_MODIFY, &bp);
+ if (error) {
+ DPRINTF("error %d reading cg %d ino %u\n", error, cg, ino);
+ return error;
+ }
+
+ const int needswap = UFS_FSNEEDSWAP(fs);
+
+ struct cg *cgp = (struct cg *)bp->b_data;
+ if (!cg_chkmagic(cgp, needswap)) {
+ brelse(bp, 0);
+ DPRINTF("bad cylinder group magic cg %d ino %u\n", cg, ino);
+ return ESTALE;
+ }
+
+ int32_t initediblk = ufs_rw32(cgp->cg_initediblk, needswap);
+ brelse(bp, 0);
+
+ if (cg * fs->fs_ipg + initediblk < ino) {
+ DPRINTF("cg=%d fs->fs_ipg=%d initediblk=%d ino=%u\n",
+ cg, fs->fs_ipg, initediblk, ino);
+ return ESTALE;
+ }
+ return 0;
+}
+
+static int
ffs_snapshot_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
void *arg0, void *arg1, void *arg2, void *arg3)
{
@@ -717,7 +765,7 @@
error = vinvalbuf(devvp, 0, cred, l, 0, 0);
VOP_UNLOCK(devvp);
if (error)
- panic("ffs_reload: dirty1");
+ panic("%s: dirty1", __func__);
/*
* Step 2: re-read superblock from disk.
*/
@@ -879,7 +927,7 @@
continue;
}
if (vinvalbuf(vp, 0, cred, l, 0, 0))
- panic("ffs_reload: dirty2");
+ panic("%s: dirty2", __func__);
/*
* Step 6: re-read inode data for all active vnodes.
*/
@@ -1748,8 +1796,7 @@
fs = ump->um_fs;
if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
- printf("fs = %s\n", fs->fs_fsmnt);
- panic("update: rofs mod");
+ panic("%s: rofs mod, fs=%s", __func__, fs->fs_fsmnt);
}
fstrans_start(mp, FSTRANS_SHARED);
@@ -1920,16 +1967,15 @@
ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
{
struct ufid ufh;
- struct fs *fs;
+ int error;
if (fhp->fid_len != sizeof(struct ufid))
return EINVAL;
memcpy(&ufh, fhp, sizeof(ufh));
- fs = VFSTOUFS(mp)->um_fs;
- if (ufh.ufid_ino < UFS_ROOTINO ||
- ufh.ufid_ino >= fs->fs_ncg * fs->fs_ipg)
- return (ESTALE);
+ if ((error = ffs_checkrange(mp, ufh.ufid_ino)) != 0)
+ return error;
+
return (ufs_fhtovp(mp, &ufh, vpp));
}
Home |
Main Index |
Thread Index |
Old Index