geom_vfs.c revision 166193
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 166193 2007-01-23 10:01:19Z kib $"); 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 74137034Sphk if (bip->bio_error) { 75137184Sphk printf("g_vfs_done():"); 76137034Sphk g_print_bio(bip); 77137034Sphk printf("error = %d\n", bip->bio_error); 78137034Sphk } 79137034Sphk bp = bip->bio_caller2; 80137034Sphk bp->b_error = bip->bio_error; 81137034Sphk bp->b_ioflags = bip->bio_flags; 82137034Sphk if (bip->bio_error) 83137034Sphk bp->b_ioflags |= BIO_ERROR; 84137034Sphk bp->b_resid = bp->b_bcount - bip->bio_completed; 85137034Sphk g_destroy_bio(bip); 86140940Sjeff vfslocked = VFS_LOCK_GIANT(((struct mount *)NULL)); 87137034Sphk bufdone(bp); 88140940Sjeff VFS_UNLOCK_GIANT(vfslocked); 89137034Sphk} 90137034Sphk 91137034Sphkvoid 92137034Sphkg_vfs_strategy(struct bufobj *bo, struct buf *bp) 93137034Sphk{ 94137034Sphk struct g_consumer *cp; 95137034Sphk struct bio *bip; 96137034Sphk 97137034Sphk cp = bo->bo_private; 98137034Sphk G_VALID_CONSUMER(cp); 99137034Sphk 100137034Sphk bip = g_alloc_bio(); 101137034Sphk bip->bio_cmd = bp->b_iocmd; 102137034Sphk bip->bio_offset = bp->b_iooffset; 103137034Sphk bip->bio_data = bp->b_data; 104137034Sphk bip->bio_done = g_vfs_done; 105137034Sphk bip->bio_caller2 = bp; 106137034Sphk bip->bio_length = bp->b_bcount; 107137034Sphk g_io_request(bip, cp); 108137034Sphk} 109137034Sphk 110141624Sphkstatic void 111137034Sphkg_vfs_orphan(struct g_consumer *cp) 112137034Sphk{ 113137034Sphk 114137034Sphk /* 115137034Sphk * Don't do anything here yet. 116137034Sphk * 117137034Sphk * Ideally we should detach the consumer already now, but that 118137034Sphk * leads to a locking requirement in the I/O path to see if we have 119137034Sphk * a consumer or not. Considering how ugly things are going to get 120137034Sphk * anyway as none of our filesystems are graceful about i/o errors, 121137034Sphk * this is not important right now. 122137034Sphk * 123137034Sphk * Down the road, this is the place where we could give the user 124137034Sphk * a "Abort, Retry or Ignore" option to replace the media again. 125137034Sphk */ 126137034Sphk} 127137034Sphk 128137034Sphkint 129137034Sphkg_vfs_open(struct vnode *vp, struct g_consumer **cpp, const char *fsname, int wr) 130137034Sphk{ 131137034Sphk struct g_geom *gp; 132137034Sphk struct g_provider *pp; 133137034Sphk struct g_consumer *cp; 134137034Sphk struct bufobj *bo; 135156201Sjeff int vfslocked; 136137034Sphk int error; 137137034Sphk 138137034Sphk g_topology_assert(); 139137034Sphk 140137034Sphk *cpp = NULL; 141137034Sphk pp = g_dev_getprovider(vp->v_rdev); 142137034Sphk if (pp == NULL) 143137034Sphk return (ENOENT); 144137034Sphk gp = g_new_geomf(&g_vfs_class, "%s.%s", fsname, pp->name); 145137034Sphk cp = g_new_consumer(gp); 146137034Sphk g_attach(cp, pp); 147137034Sphk error = g_access(cp, 1, wr, 1); 148137034Sphk if (error) { 149137034Sphk g_wither_geom(gp, ENXIO); 150137034Sphk return (error); 151137034Sphk } 152156201Sjeff vfslocked = VFS_LOCK_GIANT(vp->v_mount); 153140773Sphk vnode_create_vobject(vp, pp->mediasize, curthread); 154156201Sjeff VFS_UNLOCK_GIANT(vfslocked); 155137034Sphk *cpp = cp; 156137034Sphk bo = &vp->v_bufobj; 157137034Sphk bo->bo_ops = g_vfs_bufops; 158137034Sphk bo->bo_private = cp; 159137034Sphk bo->bo_bsize = pp->sectorsize; 160142079Sphk gp->softc = bo; 161137034Sphk 162137034Sphk return (error); 163137034Sphk} 164140822Sphk 165140822Sphkvoid 166140822Sphkg_vfs_close(struct g_consumer *cp, struct thread *td) 167140822Sphk{ 168140822Sphk struct g_geom *gp; 169142079Sphk struct bufobj *bo; 170140822Sphk 171140822Sphk g_topology_assert(); 172140822Sphk 173140822Sphk gp = cp->geom; 174142079Sphk bo = gp->softc; 175142079Sphk bufobj_invalbuf(bo, V_SAVE, td, 0, 0); 176140822Sphk g_wither_geom_close(gp, ENXIO); 177140822Sphk} 178