geom_vfs.c revision 223900
1137034Sphk/*- 2137034Sphk * Copyright (c) 2004 Poul-Henning Kamp 3137034Sphk * All rights reserved. 4137034Sphk * 5137034Sphk * Redistribution and use in source and binary forms, with or without 6137034Sphk * modification, are permitted provided that the following conditions 7137034Sphk * are met: 8137034Sphk * 1. Redistributions of source code must retain the above copyright 9137034Sphk * notice, this list of conditions and the following disclaimer. 10137034Sphk * 2. Redistributions in binary form must reproduce the above copyright 11137034Sphk * notice, this list of conditions and the following disclaimer in the 12137034Sphk * documentation and/or other materials provided with the distribution. 13137034Sphk * 14137034Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15137034Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16137034Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17137034Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18137034Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19137034Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20137034Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21137034Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22137034Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23137034Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24137034Sphk * SUCH DAMAGE. 25137034Sphk */ 26137034Sphk 27137034Sphk#include <sys/cdefs.h> 28137034Sphk__FBSDID("$FreeBSD: head/sys/geom/geom_vfs.c 223900 2011-07-10 00:41:31Z mckusick $"); 29137034Sphk 30137034Sphk#include <sys/param.h> 31137034Sphk#include <sys/systm.h> 32137034Sphk#include <sys/bio.h> 33137034Sphk#include <sys/kernel.h> 34137034Sphk#include <sys/malloc.h> 35137034Sphk#include <sys/vnode.h> 36140940Sjeff#include <sys/mount.h> /* XXX Temporary for VFS_LOCK_GIANT */ 37137034Sphk 38137034Sphk#include <geom/geom.h> 39137034Sphk#include <geom/geom_vfs.h> 40137034Sphk 41137034Sphk/* 42137034Sphk * subroutines for use by filesystems. 43137034Sphk * 44137034Sphk * XXX: should maybe live somewhere else ? 45137034Sphk */ 46137034Sphk#include <sys/buf.h> 47137034Sphk 48137034Sphkstatic struct buf_ops __g_vfs_bufops = { 49137034Sphk .bop_name = "GEOM_VFS", 50137034Sphk .bop_write = bufwrite, 51137034Sphk .bop_strategy = g_vfs_strategy, 52140056Sphk .bop_sync = bufsync, 53166193Skib .bop_bdflush = bufbdflush 54137034Sphk}; 55137034Sphk 56137034Sphkstruct buf_ops *g_vfs_bufops = &__g_vfs_bufops; 57137034Sphk 58141624Sphkstatic g_orphan_t g_vfs_orphan; 59141624Sphk 60137034Sphkstatic struct g_class g_vfs_class = { 61137034Sphk .name = "VFS", 62137034Sphk .version = G_VERSION, 63137034Sphk .orphan = g_vfs_orphan, 64137034Sphk}; 65137034Sphk 66137034SphkDECLARE_GEOM_CLASS(g_vfs_class, g_vfs); 67137034Sphk 68137034Sphkstatic void 69137034Sphkg_vfs_done(struct bio *bip) 70137034Sphk{ 71137034Sphk struct buf *bp; 72140940Sjeff int vfslocked; 73137034Sphk 74187053Strasz /* 75187053Strasz * Provider ('bio_to') could have withered away sometime 76187053Strasz * between incrementing the 'nend' in g_io_deliver() and now, 77187053Strasz * making 'bio_to' a dangling pointer. We cannot do that 78187053Strasz * in g_wither_geom(), as it would require going over 79187053Strasz * the 'g_bio_run_up' list, resetting the pointer. 80187053Strasz */ 81187053Strasz if (bip->bio_from->provider == NULL) 82187053Strasz bip->bio_to = NULL; 83187053Strasz 84137034Sphk if (bip->bio_error) { 85137184Sphk printf("g_vfs_done():"); 86137034Sphk g_print_bio(bip); 87137034Sphk printf("error = %d\n", bip->bio_error); 88137034Sphk } 89137034Sphk bp = bip->bio_caller2; 90137034Sphk bp->b_error = bip->bio_error; 91137034Sphk bp->b_ioflags = bip->bio_flags; 92137034Sphk if (bip->bio_error) 93137034Sphk bp->b_ioflags |= BIO_ERROR; 94137034Sphk bp->b_resid = bp->b_bcount - bip->bio_completed; 95137034Sphk g_destroy_bio(bip); 96140940Sjeff vfslocked = VFS_LOCK_GIANT(((struct mount *)NULL)); 97137034Sphk bufdone(bp); 98140940Sjeff VFS_UNLOCK_GIANT(vfslocked); 99137034Sphk} 100137034Sphk 101137034Sphkvoid 102137034Sphkg_vfs_strategy(struct bufobj *bo, struct buf *bp) 103137034Sphk{ 104137034Sphk struct g_consumer *cp; 105137034Sphk struct bio *bip; 106186188Strasz int vfslocked; 107137034Sphk 108137034Sphk cp = bo->bo_private; 109195257Strasz /* G_VALID_CONSUMER(cp); We likely lack topology lock */ 110137034Sphk 111186188Strasz /* 112218909Sbrucec * If the provider has orphaned us, just return EXIO. 113186188Strasz */ 114186188Strasz if (cp->provider == NULL) { 115186188Strasz bp->b_error = ENXIO; 116186188Strasz bp->b_ioflags |= BIO_ERROR; 117186188Strasz vfslocked = VFS_LOCK_GIANT(((struct mount *)NULL)); 118186188Strasz bufdone(bp); 119186188Strasz VFS_UNLOCK_GIANT(vfslocked); 120186188Strasz return; 121186188Strasz } 122186188Strasz 123137034Sphk bip = g_alloc_bio(); 124137034Sphk bip->bio_cmd = bp->b_iocmd; 125137034Sphk bip->bio_offset = bp->b_iooffset; 126137034Sphk bip->bio_data = bp->b_data; 127137034Sphk bip->bio_done = g_vfs_done; 128137034Sphk bip->bio_caller2 = bp; 129137034Sphk bip->bio_length = bp->b_bcount; 130137034Sphk g_io_request(bip, cp); 131137034Sphk} 132137034Sphk 133141624Sphkstatic void 134137034Sphkg_vfs_orphan(struct g_consumer *cp) 135137034Sphk{ 136186188Strasz struct g_geom *gp; 137137034Sphk 138186188Strasz g_topology_assert(); 139186188Strasz 140186188Strasz gp = cp->geom; 141186188Strasz g_trace(G_T_TOPOLOGY, "g_vfs_orphan(%p(%s))", cp, gp->name); 142186188Strasz if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0) 143186188Strasz g_access(cp, -cp->acr, -cp->acw, -cp->ace); 144186188Strasz g_detach(cp); 145186188Strasz 146137034Sphk /* 147187053Strasz * Do not destroy the geom. Filesystem will do that during unmount. 148137034Sphk */ 149137034Sphk} 150137034Sphk 151137034Sphkint 152137034Sphkg_vfs_open(struct vnode *vp, struct g_consumer **cpp, const char *fsname, int wr) 153137034Sphk{ 154137034Sphk struct g_geom *gp; 155137034Sphk struct g_provider *pp; 156137034Sphk struct g_consumer *cp; 157137034Sphk struct bufobj *bo; 158156201Sjeff int vfslocked; 159137034Sphk int error; 160137034Sphk 161137034Sphk g_topology_assert(); 162137034Sphk 163137034Sphk *cpp = NULL; 164206130Savg bo = &vp->v_bufobj; 165206130Savg if (bo->bo_private != vp) 166206130Savg return (EBUSY); 167206130Savg 168137034Sphk pp = g_dev_getprovider(vp->v_rdev); 169137034Sphk if (pp == NULL) 170137034Sphk return (ENOENT); 171137034Sphk gp = g_new_geomf(&g_vfs_class, "%s.%s", fsname, pp->name); 172137034Sphk cp = g_new_consumer(gp); 173137034Sphk g_attach(cp, pp); 174223900Smckusick error = g_access(cp, 1, wr, wr); 175137034Sphk if (error) { 176137034Sphk g_wither_geom(gp, ENXIO); 177137034Sphk return (error); 178137034Sphk } 179156201Sjeff vfslocked = VFS_LOCK_GIANT(vp->v_mount); 180140773Sphk vnode_create_vobject(vp, pp->mediasize, curthread); 181156201Sjeff VFS_UNLOCK_GIANT(vfslocked); 182137034Sphk *cpp = cp; 183206130Savg cp->private = vp; 184137034Sphk bo->bo_ops = g_vfs_bufops; 185137034Sphk bo->bo_private = cp; 186206097Savg bo->bo_bsize = pp->sectorsize; 187142079Sphk gp->softc = bo; 188137034Sphk 189137034Sphk return (error); 190137034Sphk} 191140822Sphk 192140822Sphkvoid 193183754Sattiliog_vfs_close(struct g_consumer *cp) 194140822Sphk{ 195140822Sphk struct g_geom *gp; 196142079Sphk struct bufobj *bo; 197140822Sphk 198140822Sphk g_topology_assert(); 199140822Sphk 200140822Sphk gp = cp->geom; 201142079Sphk bo = gp->softc; 202183754Sattilio bufobj_invalbuf(bo, V_SAVE, 0, 0); 203206130Savg bo->bo_private = cp->private; 204140822Sphk g_wither_geom_close(gp, ENXIO); 205140822Sphk} 206