Index: geom_vfs.c =================================================================== RCS file: /usr/repo/src/sys/geom/geom_vfs.c,v retrieving revision 1.9 diff -u -p -r1.9 geom_vfs.c --- geom_vfs.c 19 Feb 2005 11:44:56 -0000 1.9 +++ geom_vfs.c 22 Aug 2005 00:40:24 -0000 @@ -136,26 +136,41 @@ g_vfs_open(struct vnode *vp, struct g_co g_topology_assert(); *cpp = NULL; - pp = g_dev_getprovider(vp->v_rdev); - if (pp == NULL) - return (ENOENT); - gp = g_new_geomf(&g_vfs_class, "%s.%s", fsname, pp->name); - cp = g_new_consumer(gp); - g_attach(cp, pp); - error = g_access(cp, 1, wr, 1); - if (error) { - g_wither_geom(gp, ENXIO); - return (error); + bo = &vp->v_bufobj; + /* Is this first mount? */ + if (bo->bo_private == vp) { + pp = g_dev_getprovider(vp->v_rdev); + if (pp == NULL) + return (ENOENT); + gp = g_new_geomf(&g_vfs_class, "%s.%s", fsname, pp->name); + cp = g_new_consumer(gp); + g_attach(cp, pp); + error = g_access(cp, 1, wr, 1); + if (error) { + g_wither_geom(gp, ENXIO); + return (error); + } + cp->private = vp; + vnode_create_vobject(vp, pp->mediasize, curthread); + bo = &vp->v_bufobj; + bo->bo_ops = g_vfs_bufops; + bo->bo_private = cp; + bo->bo_bsize = pp->sectorsize; + gp->softc = bo; + } else { + cp = bo->bo_private; + /* + * Don't allow for mount when already mounted R/W. + * Don't allow for R/W mount when already mounted. + */ + if (cp->acw > 0 || wr) + return (EPERM); + error = g_access(cp, 1, wr, 1); + if (error) + return (error); } - vnode_create_vobject(vp, pp->mediasize, curthread); *cpp = cp; - bo = &vp->v_bufobj; - bo->bo_ops = g_vfs_bufops; - bo->bo_private = cp; - bo->bo_bsize = pp->sectorsize; - gp->softc = bo; - - return (error); + return (0); } void @@ -168,6 +183,20 @@ g_vfs_close(struct g_consumer *cp, struc gp = cp->geom; bo = gp->softc; - bufobj_invalbuf(bo, V_SAVE, td, 0, 0); - g_wither_geom_close(gp, ENXIO); + /* Is this last close? */ + if (cp->acr == 1) { + /* + * Put device vnode back into bo_private, so we can mount this + * file system later and first mount will be detected properly. + */ + bo->bo_private = cp->private; + bufobj_invalbuf(bo, V_SAVE, td, 0, 0); + g_wither_geom_close(gp, ENXIO); + } else { + /* It could be open only for reading here. */ + KASSERT(cp->acr > 1 && cp->acw == 0 && cp->ace > 0, + ("Invalid access for %s (r%dw%de%d).", cp->provider->name, + cp->acr, cp->acw, cp->ace)); + g_access(cp, -1, 0, -1); + } }