diff options
author | bde <bde@FreeBSD.org> | 1994-12-16 16:50:15 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1994-12-16 16:50:15 +0000 |
commit | a867a90930bc7dfaa862aa7dcda4696c3b091efa (patch) | |
tree | 8d4433650a0c4324ee1de0015f74d4e9238773a6 /sys/dev/vn | |
parent | 54d4f4b5e94e0fe5c80e5b74c134cf9d498adc3f (diff) | |
download | FreeBSD-src-a867a90930bc7dfaa862aa7dcda4696c3b091efa.zip FreeBSD-src-a867a90930bc7dfaa862aa7dcda4696c3b091efa.tar.gz |
Continue implementing disk slices and labels for the vn driver. Everything
is supposed to work except "media removal" (shutting down the vn driver)
while some partitions are open.
Fix some errnos: return ENOTTY, not ENXIO for unknown ioctls; return
ENODEV, not ENXIO for the unsupported dump operation.
Diffstat (limited to 'sys/dev/vn')
-rw-r--r-- | sys/dev/vn/vn.c | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/sys/dev/vn/vn.c b/sys/dev/vn/vn.c index f060796..f7cc61a 100644 --- a/sys/dev/vn/vn.c +++ b/sys/dev/vn/vn.c @@ -78,6 +78,7 @@ #ifdef TEST_LABELLING #include <sys/disklabel.h> #include <sys/diskslice.h> +#include <sys/stat.h> #endif #include <miscfs/specfs/specdev.h> @@ -125,7 +126,7 @@ int numvnd; /* * XXX these decls should be static (without __P(())) or elsewhere. */ -void vnattach __P((int num)); +int vnclose __P((dev_t dev, int flags, int mode, struct proc *p)); int vnopen __P((dev_t dev, int flags, int mode, struct proc *p)); void vnstrategy __P((struct buf *bp)); void vnstart __P((struct vn_softc *vn)); @@ -191,10 +192,9 @@ vnopen(dev_t dev, int flags, int mode, struct proc *p) } #ifdef TEST_LABELLING if (vn->sc_flags & VNF_INITED) { - int error; struct disklabel label; - /* Build label for whole disk. */ + /* Build label for whole disk. */ bzero(&label, sizeof label); label.d_secsize = DEV_BSIZE; label.d_nsectors = vn->sc_size; @@ -204,13 +204,12 @@ vnopen(dev_t dev, int flags, int mode, struct proc *p) label.d_secperunit = label.d_partitions[RAW_PART].p_size = label.d_nsectors; - error = dsopen("vn", dev, mode, &vn->sc_slices, &label, - vnstrategy, (ds_setgeom_t *)NULL); -#if 0 - /* XXX temporary */ - return (error); -#endif + return (dsopen("vn", dev, mode, &vn->sc_slices, &label, + vnstrategy, (ds_setgeom_t *)NULL)); } + if (dkslice(dev) != WHOLE_DISK_SLICE || dkpart(dev) != RAW_PART || + mode != S_IFCHR) + return (ENXIO); #endif /* TEST_LABELLING */ return(0); } @@ -460,12 +459,14 @@ vnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) if (unit >= numvnd) return (ENXIO); vn = vn_softc[unit]; - if (vn->sc_slices) { - error = dsioctl(dev, cmd, data, flag, vn->sc_slices, vnstrategy, - (ds_setgeom_t *)NULL); + if (vn->sc_slices != NULL) { + error = dsioctl(dev, cmd, data, flag, vn->sc_slices, + vnstrategy, (ds_setgeom_t *)NULL); if (error != -1) return (error); } + if (dkslice(dev) != WHOLE_DISK_SLICE || dkpart(dev) != RAW_PART) + return (ENOTTY); #endif error = suser(p->p_ucred, &p->p_acflag); @@ -508,6 +509,18 @@ vnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) vnthrottle(vn, vn->sc_vp); vio->vn_size = dbtob(vn->sc_size); vn->sc_flags |= VNF_INITED; +#ifdef TEST_LABELLING + /* + * Reopen so that `ds' knows which devices are open. If + * this is the first VNIOCSET, then we've guaranteed that + * the device is the cdev and that no other slices or + * labels are open. Otherwise, we rely on VNIOCCLR not + * being abused. + */ + error = vnopen(dev, flag, S_IFCHR, p); + if (error) + vnclear(vn); +#endif #ifdef DEBUG if (vndebug & VDB_INIT) printf("vnioctl: SET vp %x size %x\n", @@ -518,6 +531,14 @@ vnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case VNIOCCLR: if ((vn->sc_flags & VNF_INITED) == 0) return(ENXIO); + /* + * XXX handle i/o in progress. Return EBUSY, or wait, or + * flush the i/o. + * XXX handle multiple opens of the device. Return EBUSY, + * or revoke the fd's. + * How are these problems handled for removable and failing + * hardware devices? + */ vnclear(vn); #ifdef DEBUG if (vndebug & VDB_INIT) @@ -526,7 +547,7 @@ vnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) break; default: - return(ENXIO); + return (ENOTTY); } return(0); } @@ -606,14 +627,15 @@ vnclear(struct vn_softc *vn) #endif vn->sc_flags &= ~VNF_INITED; if (vp == (struct vnode *)0) - panic("vnioctl: null vp"); + panic("vnclear: null vp"); (void) vn_close(vp, FREAD|FWRITE, vn->sc_cred, p); crfree(vn->sc_cred); vn->sc_vp = (struct vnode *)0; vn->sc_cred = (struct ucred *)0; vn->sc_size = 0; #ifdef TEST_LABELLING - vn->sc_slices = NULL; /* XXX temportary; leaks memory, maybe worse */ + if (vn->sc_slices != NULL) + dsgone(&vn->sc_slices); #endif } @@ -632,6 +654,6 @@ vnsize(dev_t dev) int vndump(dev_t dev) { - return(ENXIO); + return (ENODEV); } #endif |