Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!agate!howland.reston.ans.net!paladin.american.edu!news.univie.ac.at!fstgds15.tu-graz.ac.at!fstgds01.tu-graz.ac.at!not-for-mail From: chmr@edvz.tu-graz.ac.at (Christoph Robitschko) Newsgroups: comp.os.386bsd.bugs Subject: Patch for hanging console Date: 19 Apr 1993 12:13:00 +0200 Organization: Technical University of Graz, Austria Lines: 149 Message-ID: <1qttvcINNno2@fstgds01.tu-graz.ac.at> NNTP-Posting-Host: fstgds01.tu-graz.ac.at X-Newsreader: TIN [version 1.1 PL7] This patch fixes the hanging console problem. The problem was that the console can be accessed through two drivers (major device numbers), so the reference count on the vnode does not represent the actual use count of the console device. Because of this, the device close routine can be called even though the device is still open through the other major number, such hanging the device. To see the problem: Log in on the /dev/vga (for pccons) or /dev/tty01 (for syscons-0.*) device, and kill all processes that have /dev/console open (normally only syslogd). Your shell on /dev/vga will no longer accept keyboard input, so make sure you can log in over the network or another virtual screen. To re-enable the console, type "sleep 1000000 < /dev/console &". Alternatively, boot to single-user mode and type "echo > /dev/vga". My fix creates a temporary vnode for the device where the console is mapped to, and keeps a reference on it as long as /dev/console is open. The patch is based on patchkit-0.2.2 . Christoph === Cut here -- start of patch === *** /sys/i386/i386/cons.c.pk022 Mon Apr 19 10:46:08 1993 --- /sys/i386/i386/cons.c Mon Apr 19 10:52:58 1993 *************** *** 56,61 **** --- 56,62 ---- #include "sys/tty.h" #include "sys/file.h" #include "sys/conf.h" + #include "sys/vnode.h" #include "cons.h" *************** cninit() *** 105,118 **** --- 106,130 ---- (*cp->cn_init)(cp); } + static struct vnode *cnopenvp = NULLVP; + + cnopen(dev, flag, mode, p) dev_t dev; int flag, mode; struct proc *p; { + int error; + + if (cn_tab == NULL) return (0); dev = cn_tab->cn_dev; + if (cnopenvp == NULLVP) + if ((error = getdevvp(dev, &cnopenvp, VCHR))) { + printf("cnopen: getdevvp returned %d !\n", error); + return(error); + } return ((*cdevsw[major(dev)].d_open)(dev, flag, mode, p)); } *************** cnclose(dev, flag, mode, p) *** 121,130 **** int flag, mode; struct proc *p; { if (cn_tab == NULL) return (0); dev = cn_tab->cn_dev; ! return ((*cdevsw[major(dev)].d_close)(dev, flag, mode, p)); } cnread(dev, uio, flag) --- 133,153 ---- int flag, mode; struct proc *p; { + int error; + + if (cn_tab == NULL) return (0); dev = cn_tab->cn_dev; ! if (vcount(cnopenvp) <= 1) ! error = (*cdevsw[major(dev)].d_close)(dev, flag, mode, p); ! else ! error = 0; ! if (error == 0) { ! vrele(cnopenvp); ! cnopenvp = NULLVP; ! return(error); ! } } cnread(dev, uio, flag) *** /sys/kern/vfs_subr.c.01ori Mon Apr 19 10:53:55 1993 --- /sys/kern/vfs_subr.c Mon Apr 19 10:58:55 1993 *************** bdevvp(dev, vpp) *** 554,559 **** --- 554,573 ---- dev_t dev; struct vnode **vpp; { + return(getdevvp(dev, vpp, VBLK)); + } + + + /* + * Create a vnode for a device. + * Used by bdevvp (block device) for root file system etc., + * and by cnopen for console (character device). + */ + getdevvp(dev, vpp, type) + dev_t dev; + struct vnode **vpp; + enum vtype type; + { register struct vnode *vp; struct vnode *nvp; int error; *************** bdevvp(dev, vpp) *** 562,572 **** return (0); error = getnewvnode(VT_NON, (struct mount *)0, &spec_vnodeops, &nvp); if (error) { ! *vpp = 0; return (error); } vp = nvp; ! vp->v_type = VBLK; if (nvp = checkalias(vp, dev, (struct mount *)0)) { vput(vp); vp = nvp; --- 576,586 ---- return (0); error = getnewvnode(VT_NON, (struct mount *)0, &spec_vnodeops, &nvp); if (error) { ! *vpp = NULLVP; return (error); } vp = nvp; ! vp->v_type = type; if (nvp = checkalias(vp, dev, (struct mount *)0)) { vput(vp); vp = nvp; === End of patch ===