Subject: kern/22419: kernel panic if 'mknod x b 0 0' fails 'out of space'
To: None <gnats-bugs@gnats.netbsd.org>
From: None <dsl@netbsd.org>
List: netbsd-bugs
Date: 08/09/2003 19:58:34
>Number: 22419
>Category: kern
>Synopsis: kernel panic if 'mknod x b 0 0' fails 'out of space'
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Aug 09 18:55:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator: David Laight
>Release: NetBSD 1.6U
>Organization:
maybe some day
>Environment:
System: NetBSD snowdrop 1.6U NetBSD 1.6U (GENERIC) #100: Wed Jul 23 11:41:02 BST 2003 dsl@snowdrop:/bsd/obj/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
If mknod for a block device fails because there is no space
(either no inodes or no space to extend the directory) then the
kernel will panic something like:
ffs_full_fsync(c4c9db0c,0,0,4,0) at netbsd:ffs_full_fsync+0x1b
ffs_fsync(c4c9db0c,c4b679dc,0,c0345a5f,0) at netbsd:ffs_fsync+0x3c
VOP_FSYNC(c4b743e4,ffffffff,5,0,0) at netbsd:VOP_FSYNC+0x58
vinvalbuf(c4b743e4,1,ffffffff,c4b679dc,0) at netbsd:vinvalbuf+0x52
vclean(c4b743e4,8,c4b679dc,c03524ff,c4b75370) at netbsd:vclean+0x80
vgonel(c4b743e4,c4b679dc,c4b743e4,c05654e0,c4b743e4)
at netbsd:vgonel+0x46
vrecycle(c4b743e4,0,c4b679dc,0,c4b7441c) at netbsd:vrecycle+0x20
ufs_inactive(c4c9dc64,c095d000,c4c9dc8c,c0565420,c4c47058)
at netbsd:ufs_inactive+0x180
VOP_INACTIVE(c4b743e4,c4b679dc,c4c9dde0,c02f2d2b,c4c9dcd8)
at netbsd:VOP_INACTIVE+0x2e
vput(c4b743e4,c4b55400,ffffffff,2,c4c9de3c) at netbsd:vput+0xa2
ufs_makeinode(61a0,c4c47058,c4c9de9c,c4c9deb0,c4c47058)
at netbsd:ufs_makeinode+0x35e
ufs_mknod(c4c9de3c,c4b679dc,c4c9df80,c034a9ea,0)
at netbsd:ufs_mknod+0x2d
VOP_MKNOD(c4c47058,c4c9de9c,c4c9deb0,c4c9ded4,c4b35780)
at netbsd:VOP_MKNOD+0x3b
sys_mknod(c4b35780,c4c9df80,c4c9df78,c03b817b,8064048)
at netbsd:sys_mknod+0x1dd
syscall_plain(1f,1f,1f,1f,804a863) at netbsd:syscall_plain+0xab
The 'problem' is that vp->v_specinfo is NULL, but is indirected
as part of v_specmountpoint.
>How-To-Repeat:
Fill a small filesystem then try no make a block special device file.
>Fix:
Noting that ufs_makeinode() sets v_type = VNON before releasing
the vnode in the 'success' path, make ufs_makeinode do the same
in the failure path.
(Actually I'm sure it would be better fixed in the code that
frees/recycles the vnode...)
The patch below fixes ufs and by symmetry ext2fs.
I've re-ordered the tidyup in the error paths with the view
that the compiler might merge them with other error paths.
Index: ext2fs/ext2fs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_vnops.c,v
retrieving revision 1.48
diff -u -p -r1.48 ext2fs_vnops.c
--- ext2fs/ext2fs_vnops.c 2003/06/29 22:32:33 1.48
+++ ext2fs/ext2fs_vnops.c 2003/08/09 18:41:25
@@ -1407,11 +1407,12 @@ bad:
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
- PNBUF_PUT(cnp->cn_pnbuf);
- vput(dvp);
+ tvp->v_type = VNON; /* Stop explosion if VBLK */
ip->i_e2fs_nlink = 0;
ip->i_flag |= IN_CHANGE;
vput(tvp);
+ PNBUF_PUT(cnp->cn_pnbuf);
+ vput(dvp);
return (error);
}
Index: ufs/ufs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.102
diff -u -p -r1.102 ufs_vnops.c
--- ufs/ufs_vnops.c 2003/06/29 22:32:48 1.102
+++ ufs/ufs_vnops.c 2003/08/09 18:41:33
@@ -2085,9 +2085,9 @@ ufs_makeinode(int mode, struct vnode *dv
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, cnp->cn_cred, 0))) {
- PNBUF_PUT(cnp->cn_pnbuf);
VOP_VFREE(tvp, ip->i_number, mode);
vput(tvp);
+ PNBUF_PUT(cnp->cn_pnbuf);
vput(dvp);
return (error);
}
@@ -2132,8 +2132,6 @@ ufs_makeinode(int mode, struct vnode *dv
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
- PNBUF_PUT(cnp->cn_pnbuf);
- vput(dvp);
ip->i_ffs_effnlink = 0;
ip->i_nlink = 0;
DIP_ASSIGN(ip, nlink, 0);
@@ -2144,7 +2142,10 @@ ufs_makeinode(int mode, struct vnode *dv
#endif
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
+ tvp->v_type = VNON; /* explodes later if VBLK */
vput(tvp);
+ PNBUF_PUT(cnp->cn_pnbuf);
+ vput(dvp);
return (error);
}
>Release-Note:
>Audit-Trail:
>Unformatted:
and probably everything else for a long time