Subject: kern/3811: vnconfig hangs if target file is less than 2048 512-bytes
To: None <gnats-bugs@gnats.netbsd.org>
From: None <enami@ba2.so-net.or.jp>
List: netbsd-bugs
Date: 06/29/1997 13:02:48
>Number:         3811
>Category:       kern
>Synopsis:       vnconfig hangs if target file is less than 2048 512-bytes block and configured without geomspec.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Jun 28 21:35:02 1997
>Last-Modified:
>Originator:     enami tsugutomo
>Organization:
>Release:        NetBSD-current 1997 June 27
>Environment:
System: NetBSD pavlov.enami.ba2.so-net.or.jp 1.2G NetBSD 1.2G (PAVLOV) #299: Sat Jun 28 11:55:32 JST 1997 enami@pavlov.enami.ba2.so-net.or.jp:/b/netbsd/kernel/compile/PAVLOV i386


>Description:
	vnconfig hangs if target file is less than 2048 512-bytes block
	and tried to config without specifiying geomspec.

>How-To-Repeat:
	Here is log done on NetBSD/i386.

Script started on Sun Jun 29 12:22:22 1997
king-show# cd /var/tmp
king-show# dd if=/dev/zero of=tako bs=100k count=10
10+0 records in
10+0 records out
1024000 bytes transferred in 1 secs (1024000 bytes/sec)
king-show# ls -l tako
-rw-r--r--  1 root  wheel  1024000 Jun 29 12:22 tako
king-show# date
Sun Jun 29 12:23:04 JST 1997
king-show# vnconfig -v -c /dev/vnd0d /var/tmp/tako
vnconfig: VNDIOCSET: Invalid argument
^C
king-show# date
Sun Jun 29 12:26:28 JST 1997

>Fix:
	vnconfig hangs during closing vnd.  It is because ioctl bail out
	without unlocking vnd if target file is shorter than 2048 512-byte
	block.

	Just add missing vndunlock() before following return:

			if (vnd->sc_size < (32 * 64))
				return (EINVAL);

	or is it better to centerize unlock like this?

Index: vnd.c
===================================================================
RCS file: /a/cvsroot/NetBSD/src/sys/dev/vnd.c,v
retrieving revision 1.1.1.12
diff -u -r1.1.1.12 vnd.c
--- vnd.c	1997/06/28 00:07:53	1.1.1.12
+++ vnd.c	1997/06/29 03:15:53
@@ -704,16 +704,14 @@
 		 * have to worry about them.
 		 */
 		NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vnd_file, p);
-		if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
-			vndunlock(vnd);
-			return(error);
-		}
+		if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0)
+			goto bad;
+
 		error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
 		if (error) {
 			VOP_UNLOCK(nd.ni_vp);
 			(void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
-			vndunlock(vnd);
-			return(error);
+			goto bad;
 		}
 		VOP_UNLOCK(nd.ni_vp);
 		vnd->sc_vp = nd.ni_vp;
@@ -737,8 +735,8 @@
 			    (vnd->sc_geom.vng_secsize % DEV_BSIZE) != 0) {
 				(void) vn_close(nd.ni_vp, FREAD|FWRITE,
 				    p->p_ucred, p);
-				vndunlock(vnd);
-				return (EINVAL);
+				error = EINVAL;
+				goto bad;
 			}
 
 			/*
@@ -757,16 +755,18 @@
 			if (vnd->sc_size < geomsize) {
 				(void) vn_close(nd.ni_vp, FREAD|FWRITE,
 				    p->p_ucred, p);
-				vndunlock(vnd);
-				return (EINVAL);
+				error = EINVAL;
+				goto bad;
 			}
 		} else {
 			/*
 			 * Size must be at least 2048 DEV_BSIZE blocks
 			 * (1M) in order to use this geometry.
 			 */
-			if (vnd->sc_size < (32 * 64))
-				return (EINVAL);
+			if (vnd->sc_size < (32 * 64)) {
+				error = EINVAL;
+				goto bad;
+			}
 
 			vnd->sc_geom.vng_secsize = DEV_BSIZE;
 			vnd->sc_geom.vng_nsectors = 32;
@@ -788,8 +788,7 @@
 
 		if ((error = vndsetcred(vnd, p->p_ucred)) != 0) {
 			(void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
-			vndunlock(vnd);
-			return(error);
+			goto bad;
 		}
 		vndthrottle(vnd, vnd->sc_vp);
 		vio->vnd_size = dbtob(vnd->sc_size);
@@ -813,8 +812,6 @@
 		/* Try and read the disklabel. */
 		vndgetdisklabel(dev);
 
-		vndunlock(vnd);
-
 		break;
 
 	case VNDIOCCLR:
@@ -831,8 +828,8 @@
 		if ((vnd->sc_dkdev.dk_openmask & ~pmask) ||
 		    ((vnd->sc_dkdev.dk_bopenmask & pmask) &&
 		    (vnd->sc_dkdev.dk_copenmask & pmask))) {
-			vndunlock(vnd);
-			return (EBUSY);
+			error = EBUSY;
+			goto bad;
 		}
 
 		vndclear(vnd);
@@ -844,19 +841,17 @@
 		/* Detatch the disk. */
 		disk_detach(&vnd->sc_dkdev);
 
-		vndunlock(vnd);
-
 		break;
 
 	case DIOCGDINFO:
 		*(struct disklabel *)data = *(vnd->sc_dkdev.dk_label);
-		break;
+		return (0);
 
 	case DIOCGPART:
 		((struct partinfo *)data)->disklab = vnd->sc_dkdev.dk_label;
 		((struct partinfo *)data)->part =
 		    &vnd->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
-		break;
+		return (0);
 
 	case DIOCWDINFO:
 	case DIOCSDINFO:
@@ -876,10 +871,6 @@
 
 		vnd->sc_flags &= ~VNF_LABELLING;
 
-		vndunlock(vnd);
-
-		if (error)
-			return (error);
 		break;
 
 	case DIOCWLABEL:
@@ -887,13 +878,15 @@
 			vnd->sc_flags |= VNF_WLABEL;
 		else
 			vnd->sc_flags &= ~VNF_WLABEL;
-		break;
+		return (0);
 
 	default:
 		return (ENOTTY);
 	}
 
-	return (0);
+ bad:
+	vndunlock(vnd);
+	return (error);
 }
 
 /*
>Audit-Trail:
>Unformatted: