Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 05 Oct 2002 20:33:40 +0100
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        Poul-Henning Kamp <phk@critter.freebsd.dk>
Cc:        Robert Watson <rwatson@FreeBSD.ORG>, Greg 'groggy' Lehey <grog@FreeBSD.ORG>, current <freebsd-current@FreeBSD.ORG>
Subject:   Re: [ GEOM tests ] disklabel warnings and vinum drives lost 
Message-ID:   <200210052033.aa95708@salmon.maths.tcd.ie>
In-Reply-To: Your message of "Sat, 05 Oct 2002 08:15:04 %2B0200." <81130.1033798504@critter.freebsd.dk> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <81130.1033798504@critter.freebsd.dk>, Poul-Henning Kamp writes:
>Make that _three_ bugs:  vinum opens devices directly at the cdevsw
>level, bypassing in the process the vnodes and specfs.

Here is a patch that makes it use vn_open/vn_close/VOP_IOCTL,
bringing it much closer to the way ccd(4) does things. I have only
lightly tested this so far - I saw one problem where a md(4)
vnode-backed device got stuck in mddestroy(), but I haven't tracked
down if that is related (the md vnode was just a file on a vinum-backed
filesystem).

Ian

Index: vinumio.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/dev/vinum/vinumio.c,v
retrieving revision 1.76
diff -u -r1.76 vinumio.c
--- vinumio.c	5 Oct 2002 03:44:00 -0000	1.76
+++ vinumio.c	5 Oct 2002 14:12:56 -0000
@@ -51,33 +51,26 @@
 open_drive(struct drive *drive, struct thread *td, int verbose)
 {
     struct nameidata nd;
-    struct cdevsw *dsw;					    /* pointer to cdevsw entry */
-    int error;
+    int flags;
 
     if (drive->flags & VF_OPEN)				    /* open already, */
 	return EBUSY;					    /* don't do it again */
 
-    NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, drive->devicename,
-        curthread);
-    error = namei(&nd);
-    if (error)
-	return (error);
-    if (!vn_isdisk(nd.ni_vp, &error)) {
-	NDFREE(&nd, 0);
-	return (error);
-    }
-    drive->dev = udev2dev(nd.ni_vp->v_rdev->si_udev, 0);
-    NDFREE(&nd, 0);
-
-    if (drive->dev == NULL)				    /* didn't find anything */
-	return ENODEV;
-
-    drive->dev->si_iosize_max = DFLTPHYS;
-    dsw = devsw(drive->dev);
-    if (dsw == NULL)
-	drive->lasterror = ENOENT;
-    else
-	drive->lasterror = (dsw->d_open) (drive->dev, FWRITE | FREAD, 0, NULL);
+    drive->devvp = NULL;
+    NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, drive->devicename, td);
+    flags = FREAD | FWRITE;
+    drive->lasterror = vn_open(&nd, &flags, 0);
+    if (drive->lasterror == 0) {
+	(void) vn_isdisk(nd.ni_vp, &drive->lasterror);
+	if (drive->lasterror != 0 && vrefcnt(nd.ni_vp) > 1)
+	    drive->lasterror = EBUSY;
+	VOP_UNLOCK(nd.ni_vp, 0, td);
+	NDFREE(&nd, NDF_ONLY_PNBUF);
+	if (drive->lasterror == 0)
+	    drive->devvp = nd.ni_vp;
+	else
+	    (void) vn_close(nd.ni_vp, flags, td->td_ucred, td);
+    }
 
     if (drive->lasterror != 0) {			    /* failed */
 	drive->state = drive_down;			    /* just force it down */
@@ -85,8 +78,11 @@
 	    log(LOG_WARNING,
 		"vinum open_drive %s: failed with error %d\n",
 		drive->devicename, drive->lasterror);
-    } else
+    } else {
+	drive->dev = vn_todev(drive->devvp);
+	drive->dev->si_iosize_max = DFLTPHYS;
 	drive->flags |= VF_OPEN;			    /* we're open now */
+    }
 
     return drive->lasterror;
 }
@@ -145,6 +141,9 @@
 int
 init_drive(struct drive *drive, int verbose)
 {
+    struct thread *td;
+
+    td = curthread;
     if (drive->devicename[0] != '/') {
 	drive->lasterror = EINVAL;
 	log(LOG_ERR, "vinum: Can't open drive without drive name\n");
@@ -154,17 +153,17 @@
     if (drive->lasterror)
 	return drive->lasterror;
 
-    drive->lasterror = (*devsw(drive->dev)->d_ioctl) (drive->dev,
+    drive->lasterror = VOP_IOCTL(drive->devvp,
 	DIOCGSECTORSIZE,
 	(caddr_t) & drive->sectorsize,
 	FREAD,
-	curthread);
+	td->td_ucred, td);
     if (drive->lasterror == 0)
-	    drive->lasterror = (*devsw(drive->dev)->d_ioctl) (drive->dev,
+	    drive->lasterror = VOP_IOCTL(drive->devvp,
 		DIOCGMEDIASIZE,
 		(caddr_t) & drive->mediasize,
 		FREAD,
-		curthread);
+		td->td_ucred, td);
     if (drive->lasterror) {
 	if (verbose)
 	    log(LOG_WARNING,
@@ -211,14 +210,16 @@
 void
 close_locked_drive(struct drive *drive)
 {
+    struct thread *td;
     int error;
 
+    td = curthread;
     /*
      * If we can't access the drive, we can't flush
      * the queues, which spec_close() will try to
      * do.  Get rid of them here first.
      */
-    error = (*devsw(drive->dev)->d_close) (drive->dev, 0, 0, NULL);
+    error = vn_close(drive->devvp, FREAD | FWRITE, td->td_ucred, td);
     drive->flags &= ~VF_OPEN;				    /* no longer open */
     if (drive->lasterror == 0)
 	drive->lasterror = error;
@@ -561,11 +562,13 @@
     int error;
     int written_config;					    /* set when we first write the config to disk */
     int driveno;
+    struct thread *td;
     struct drive *drive;				    /* point to current drive info */
     struct vinum_hdr *vhdr;				    /* and as header */
     char *config;					    /* point to config data */
     int wlabel_on;					    /* to set writing label on/off */
 
+    td = curthread;
     /* don't save the configuration while we're still working on it */
     if (vinum_conf.flags & VF_CONFIGURING)
 	return;
@@ -615,22 +618,22 @@
 		if ((drive->state != drive_unallocated)
 		    && (drive->state != drive_referenced)) { /* and it's a real drive */
 		    wlabel_on = 1;			    /* enable writing the label */
-		    (void) (*devsw(drive->dev)->d_ioctl) (drive->dev, /* make the label writeable */
+		    (void) VOP_IOCTL(drive->devvp, /* make the label writeable */
 			DIOCWLABEL,
 			(caddr_t) & wlabel_on,
 			FWRITE,
-			curthread);
+			td->td_ucred, td);
 		    error = write_drive(drive, (char *) vhdr, VINUMHEADERLEN, VINUM_LABEL_OFFSET);
 		    if (error == 0)
 			error = write_drive(drive, config, MAXCONFIG, VINUM_CONFIG_OFFSET); /* first config copy */
 		    if (error == 0)
 			error = write_drive(drive, config, MAXCONFIG, VINUM_CONFIG_OFFSET + MAXCONFIG);	/* second copy */
 		    wlabel_on = 0;			    /* enable writing the label */
-		    (void) (*devsw(drive->dev)->d_ioctl) (drive->dev, /* make the label non-writeable again */
+		    (void) VOP_IOCTL(drive->devvp, /* make the label non-writeable again */
 			    DIOCWLABEL,
 			    (caddr_t) & wlabel_on,
 			    FWRITE,
-			    curthread);
+			    td->td_ucred, td);
 		    unlockdrive(drive);
 		    if (error) {
 			log(LOG_ERR,
Index: vinumobj.h
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/dev/vinum/vinumobj.h,v
retrieving revision 1.6
diff -u -r1.6 vinumobj.h
--- vinumobj.h	16 May 2002 21:23:45 -0000	1.6
+++ vinumobj.h	5 Oct 2002 14:07:47 -0000
@@ -178,6 +178,7 @@
 #ifdef _KERNEL
     u_int sectorsize;
     off_t mediasize;
+    struct vnode *devvp;				    /* device vnode */
     dev_t dev;						    /* device information */
 #ifdef VINUMDEBUG
     char lockfilename[16];				    /* name of file from which we were locked */


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




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