The patch appears to work for me on 3.9 i386, and I do need your comments on it. Thank you, Joachim.
--- sys/dev/vnd.c.orig Fri Sep 8 03:41:21 2006 +++ sys/dev/vnd.c Sat Sep 9 05:09:38 2006 @@ -142,7 +142,10 @@ #define VNF_HAVELABEL 0x0400 #define VNF_BUSY 0x0800 #define VNF_SIMPLE 0x1000 +#define VNF_READONLY 0x2000 +#define FLG(vnd) (vnd->sc_flags & VNF_READONLY ? FREAD : FREAD|FWRITE) + struct vnd_softc *vnd_softc; int numvnd = 0; @@ -231,6 +234,9 @@ return (ENXIO); sc = &vnd_softc[unit]; + if (flags & FWRITE && sc->sc_flags & VNF_READONLY) + return (EROFS); + if ((error = vndlock(sc)) != 0) return (error); @@ -817,14 +823,15 @@ * have to worry about them. */ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vnd_file, p); - if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) { + vnd->sc_flags &= ~VNF_READONLY; + if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0 && (error != EROFS || (vnd->sc_flags |= VNF_READONLY, (error = vn_open(&nd, FREAD, 0)) != 0))) { vndunlock(vnd); return (error); } error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p); if (error) { VOP_UNLOCK(nd.ni_vp, 0, p); - (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p); + (void) vn_close(nd.ni_vp, FLG(vnd), p->p_ucred, p); vndunlock(vnd); return (error); } @@ -832,7 +839,7 @@ vnd->sc_vp = nd.ni_vp; vnd->sc_size = btodb(vattr.va_size); /* note truncation */ if ((error = vndsetcred(vnd, p->p_ucred)) != 0) { - (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p); + (void) vn_close(nd.ni_vp, FLG(vnd), p->p_ucred, p); vndunlock(vnd); return (error); } @@ -845,7 +852,7 @@ if ((error = copyin(vio->vnd_key, key, vio->vnd_keylen)) != 0) { - (void) vn_close(nd.ni_vp, FREAD|FWRITE, + (void) vn_close(nd.ni_vp, FLG(vnd), p->p_ucred, p); vndunlock(vnd); return (error); @@ -1082,7 +1089,7 @@ vnd->sc_flags &= ~VNF_INITED; if (vp == (struct vnode *)0) panic("vndioctl: null vp"); - (void) vn_close(vp, FREAD|FWRITE, vnd->sc_cred, p); + (void) vn_close(vp, FLG(vnd), vnd->sc_cred, p); crfree(vnd->sc_cred); vnd->sc_vp = (struct vnode *)0; vnd->sc_cred = (struct ucred *)0; --- usr.sbin/vnconfig/vnconfig.c.orig Sat Sep 9 04:37:15 2006 +++ usr.sbin/vnconfig/vnconfig.c Sat Sep 9 04:59:25 2006 @@ -159,7 +159,7 @@ char *rdev; int rv; - if (opendev(dev, O_RDWR, OPENDEV_PART, &rdev) < 0) + if (opendev(dev, O_RDONLY, OPENDEV_PART, &rdev) < 0) err(4, "%s", rdev); f = fopen(rdev, "rw"); if (f == NULL) {