In message <[EMAIL PROTECTED]>, 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 [EMAIL PROTECTED] with "unsubscribe freebsd-current" in the body of the message