From owner-freebsd-bugs Fri Feb 13 16:50:07 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id QAA19989 for freebsd-bugs-outgoing; Fri, 13 Feb 1998 16:50:07 -0800 (PST) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: (from gnats@localhost) by hub.freebsd.org (8.8.8/8.8.8) id QAA19952; Fri, 13 Feb 1998 16:50:03 -0800 (PST) (envelope-from gnats) Date: Fri, 13 Feb 1998 16:50:03 -0800 (PST) Message-Id: <199802140050.QAA19952@hub.freebsd.org> To: freebsd-bugs Cc: From: Tor Egge Subject: re: kern/1067: panic: ufs_lock: recursive lock not expected, pid: 27195 Reply-To: Tor Egge Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org The following reply was made to PR kern/1067; it has been noted by GNATS. From: Tor Egge To: freebsd-gnats-submit@FreeBSD.ORG Cc: Subject: re: kern/1067: panic: ufs_lock: recursive lock not expected, pid: 27195 Date: Sat, 14 Feb 1998 01:42:10 +0100 By introducing a new vnode flag, the assignment of v_mountedhere can be delayed until the file system specific mount code has been successfully executed. This means that the exclusive lock on the vnode to be covered can be temporarily released by the generic mount code, and namei() operations in {ffs,msdosfs,cd9660,nullfs,union,umap}_mount can complete without panics due to unexpected recursive locks. The mount() system call should by default disallow mounts over existing mount points. An explicit mount option (SunOS 5.5.1 uses `-O') should be specified in order to allow mount over an existing mount point. Then mount /dev/fd0 / would give /dev/fd0 on /: Device busy while mount /mnt /mnt would give /mnt on /mnt: Block device required and mount -O /dev/fd0 / would succeed, mounting the floppy as the new root file system. Suggested fix for 3.0-CURRENT: Index: sys/sys/vnode.h =================================================================== RCS file: /home/ncvs/src/sys/sys/vnode.h,v retrieving revision 1.66 diff -u -r1.66 vnode.h --- vnode.h 1998/01/24 02:01:31 1.66 +++ vnode.h 1998/02/10 18:53:07 @@ -155,6 +155,7 @@ #define VDOOMED 0x40000 /* This vnode is being recycled */ #define VFREE 0x80000 /* This vnode is on the freelist */ #define VTBFREE 0x100000 /* This vnode is no the to be freelist */ +#define VMOUNT 0x200000 /* Mount in progress */ /* * Vnode attributes. A field value of VNOVAL represents a field whose value Index: sys/sys/mount.h =================================================================== RCS file: /home/ncvs/src/sys/sys/mount.h,v retrieving revision 1.54 diff -u -r1.54 mount.h --- mount.h 1998/02/05 17:27:42 1.54 +++ mount.h 1998/02/14 00:00:59 @@ -211,7 +211,9 @@ #define MNT_DELEXPORT 0x00020000 /* delete export host lists */ #define MNT_RELOAD 0x00040000 /* reload filesystem data */ #define MNT_FORCE 0x00080000 /* force unmount or readonly change */ -#define MNT_CMDFLAGS (MNT_UPDATE|MNT_DELEXPORT|MNT_RELOAD|MNT_FORCE) +#define MNT_OVERLAY 0x00200000 /* Allow mount over mount point */ +#define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \ + MNT_FORCE | MNT_OVERLAY ) /* * Internal filesystem control flags stored in mnt_kern_flag. * Index: sys/kern/vfs_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.92 diff -u -r1.92 vfs_syscalls.c --- vfs_syscalls.c 1998/02/08 01:41:33 1.92 +++ vfs_syscalls.c 1998/02/13 23:18:59 @@ -233,10 +233,24 @@ vput(vp); return (ENODEV); } - if (vp->v_mountedhere != NULL) { + if ((SCARG(uap, flags) & MNT_OVERLAY) == 0) { + simple_lock(&vp->v_interlock); + if ((vp->v_flag & VROOT) != 0) { + simple_unlock(&vp->v_interlock); + vput(vp); + return EBUSY; + } + simple_unlock(&vp->v_interlock); + } + simple_lock(&vp->v_interlock); + if ((vp->v_flag & VMOUNT) != 0 || + vp->v_mountedhere != NULL) { + simple_unlock(&vp->v_interlock); vput(vp); return (EBUSY); } + vp->v_flag |= VMOUNT; + simple_unlock(&vp->v_interlock); /* * Allocate and initialize the filesystem. @@ -252,9 +266,9 @@ mp->mnt_stat.f_type = vfsp->vfc_typenum; mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); - vp->v_mountedhere = mp; mp->mnt_vnodecovered = vp; mp->mnt_stat.f_owner = p->p_ucred->cr_uid; + VOP_UNLOCK(vp, 0, p); update: /* * Set the mount level flags. @@ -286,11 +300,16 @@ vfs_unbusy(mp, p); return (error); } + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* * Put the new filesystem on the mount list after root. */ cache_purge(vp); if (!error) { + simple_lock(&vp->v_interlock); + vp->v_flag &= ~VMOUNT; + vp->v_mountedhere = mp; + simple_unlock(&vp->v_interlock); simple_lock(&mountlist_slock); CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); simple_unlock(&mountlist_slock); @@ -300,7 +319,9 @@ if (error = VFS_START(mp, 0, p)) vrele(vp); } else { - mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; + simple_lock(&vp->v_interlock); + vp->v_flag &= ~VMOUNT; + simple_unlock(&vp->v_interlock); mp->mnt_vfc->vfc_refcount--; vfs_unbusy(mp, p); free((caddr_t)mp, M_MOUNT); Index: sbin/mount/mntopts.h =================================================================== RCS file: /home/ncvs/src/sbin/mount/mntopts.h,v retrieving revision 1.12 diff -u -r1.12 mntopts.h --- mntopts.h 1997/11/13 00:28:48 1.12 +++ mntopts.h 1998/02/14 00:02:31 @@ -61,6 +61,7 @@ #define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 } #define MOPT_RO { "ro", 0, MNT_RDONLY, 0 } #define MOPT_RW { "rw", 1, MNT_RDONLY, 0 } +#define MOPT_OVERLAY { "overlay", 0, MNT_OVERLAY, 0 } /* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */ #define MOPT_AUTO { "auto", 0, 0, 0 } @@ -83,7 +84,8 @@ MOPT_RDONLY, \ MOPT_UNION, \ MOPT_NOCLUSTERR, \ - MOPT_NOCLUSTERW + MOPT_NOCLUSTERW, \ + MOPT_OVERLAY void getmntopts __P((const char *, const struct mntopt *, int *, int *)); extern int getmnt_silent; Index: sbin/mount/mount.8 =================================================================== RCS file: /home/ncvs/src/sbin/mount/mount.8,v retrieving revision 1.21 diff -u -r1.21 mount.8 --- mount.8 1997/12/01 00:44:16 1.21 +++ mount.8 1998/02/14 00:08:01 @@ -40,13 +40,13 @@ .Nd mount file systems .Sh SYNOPSIS .Nm mount -.Op Fl adfpruvw +.Op Fl Oadfpruvw .Op Fl t Ar ufs | lfs | external_type .Nm mount -.Op Fl dfpruvw +.Op Fl Odfpruvw .Ar special | node .Nm mount -.Op Fl dfpruvw +.Op Fl Odfpruvw .Op Fl o Ar options .Op Fl t Ar ufs | lfs | external_type .Ar special node @@ -75,6 +75,10 @@ .Pp The options are as follows: .Bl -tag -width indent +.It Fl O +Allows mount on top of existing mount points. Without this option, +attempting to mount a file system over an existing mount point will +result in the error "Device busy". .It Fl a All the filesystems described in .Xr fstab 5 Index: sbin/mount/mount.c =================================================================== RCS file: /home/ncvs/src/sbin/mount/mount.c,v retrieving revision 1.21 diff -u -r1.21 mount.c --- mount.c 1997/11/13 00:28:49 1.21 +++ mount.c 1998/02/14 00:05:52 @@ -129,8 +129,11 @@ options = NULL; vfslist = NULL; vfstype = "ufs"; - while ((ch = getopt(argc, argv, "adfo:prwt:uv")) != -1) + while ((ch = getopt(argc, argv, "Oadfo:prwt:uv")) != -1) switch (ch) { + case 'O': + init_flags |= MNT_OVERLAY; + break; case 'a': all = 1; break; @@ -375,12 +378,15 @@ } optbuf = catopt(strdup(mntopts), options); - if (strcmp(name, "/") == 0) + if ((strcmp(name, "/") == 0) && + (flags & MNT_OVERLAY) == 0) flags |= MNT_UPDATE; if (flags & MNT_FORCE) optbuf = catopt(optbuf, "force"); if (flags & MNT_RDONLY) optbuf = catopt(optbuf, "ro"); + if (flags & MNT_OVERLAY) + optbuf = catopt(optbuf, "overlay"); /* * XXX * The mount_mfs (newfs) command uses -o to select the To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message