Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Feb 1998 16:50:03 -0800 (PST)
From:      Tor Egge <Tor.Egge@idi.ntnu.no>
To:        freebsd-bugs
Subject:   re: kern/1067: panic: ufs_lock: recursive lock not expected, pid: 27195
Message-ID:  <199802140050.QAA19952@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/1067; it has been noted by GNATS.

From: Tor Egge <Tor.Egge@idi.ntnu.no>
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199802140050.QAA19952>