geom_vfs.c revision 140773
1144648Sdas/*-
2144648Sdas * Copyright (c) 2004 Poul-Henning Kamp
3144648Sdas * All rights reserved.
4144648Sdas *
5144648Sdas * Redistribution and use in source and binary forms, with or without
6144648Sdas * modification, are permitted provided that the following conditions
7144648Sdas * are met:
8144648Sdas * 1. Redistributions of source code must retain the above copyright
9144648Sdas *    notice, this list of conditions and the following disclaimer.
10144648Sdas * 2. Redistributions in binary form must reproduce the above copyright
11144648Sdas *    notice, this list of conditions and the following disclaimer in the
12144648Sdas *    documentation and/or other materials provided with the distribution.
13144648Sdas *
14144648Sdas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15144648Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16144648Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17144648Sdas * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18144648Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19144648Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20144648Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21144648Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22144648Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23144648Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24144648Sdas * SUCH DAMAGE.
25144648Sdas */
26144648Sdas
27144648Sdas#include <sys/cdefs.h>
28144648Sdas__FBSDID("$FreeBSD: head/sys/geom/geom_vfs.c 140773 2005-01-24 22:41:21Z phk $");
29144648Sdas
30175460Sdas#include <sys/param.h>
31175460Sdas#include <sys/systm.h>
32144648Sdas#include <sys/bio.h>
33144648Sdas#include <sys/kernel.h>
34144648Sdas#include <sys/malloc.h>
35144648Sdas#include <sys/vnode.h>
36144648Sdas
37144648Sdas#include <geom/geom.h>
38144648Sdas#include <geom/geom_vfs.h>
39144648Sdas
40144648Sdas/*
41144648Sdas * subroutines for use by filesystems.
42144648Sdas *
43144648Sdas * XXX: should maybe live somewhere else ?
44144648Sdas */
45144648Sdas#include <sys/buf.h>
46144648Sdas
47144648Sdasstatic struct buf_ops __g_vfs_bufops = {
48144648Sdas	.bop_name =	"GEOM_VFS",
49144648Sdas	.bop_write =	bufwrite,
50144648Sdas	.bop_strategy =	g_vfs_strategy,
51144648Sdas	.bop_sync =	bufsync,
52144648Sdas};
53144648Sdas
54144648Sdasstruct buf_ops *g_vfs_bufops = &__g_vfs_bufops;
55144648Sdas
56144648Sdasstatic struct g_class g_vfs_class = {
57144648Sdas	.name =		"VFS",
58144648Sdas	.version =	G_VERSION,
59144648Sdas	.orphan =	g_vfs_orphan,
60144648Sdas};
61144648Sdas
62144648SdasDECLARE_GEOM_CLASS(g_vfs_class, g_vfs);
63144648Sdas
64144648Sdasstatic void
65144648Sdasg_vfs_done(struct bio *bip)
66144648Sdas{
67144648Sdas	struct buf *bp;
68144648Sdas
69144648Sdas	if (bip->bio_error) {
70144648Sdas		printf("g_vfs_done():");
71144648Sdas		g_print_bio(bip);
72144648Sdas		printf("error = %d\n", bip->bio_error);
73144648Sdas	}
74144648Sdas	bp = bip->bio_caller2;
75144648Sdas	bp->b_error = bip->bio_error;
76144648Sdas	bp->b_ioflags = bip->bio_flags;
77144648Sdas	if (bip->bio_error)
78144648Sdas		bp->b_ioflags |= BIO_ERROR;
79144648Sdas	bp->b_resid = bp->b_bcount - bip->bio_completed;
80144648Sdas	g_destroy_bio(bip);
81144648Sdas	bufdone(bp);
82144648Sdas}
83144648Sdas
84144648Sdasvoid
85144648Sdasg_vfs_strategy(struct bufobj *bo, struct buf *bp)
86144648Sdas{
87144648Sdas	struct g_consumer *cp;
88144648Sdas	struct bio *bip;
89144648Sdas
90144648Sdas	cp = bo->bo_private;
91144648Sdas	G_VALID_CONSUMER(cp);
92144648Sdas
93144648Sdas	bip = g_alloc_bio();
94144648Sdas	bip->bio_cmd = bp->b_iocmd;
95144648Sdas	bip->bio_offset = bp->b_iooffset;
96144648Sdas	bip->bio_data = bp->b_data;
97144648Sdas	bip->bio_done = g_vfs_done;
98144648Sdas	bip->bio_caller2 = bp;
99144648Sdas	bip->bio_length = bp->b_bcount;
100144648Sdas	g_io_request(bip, cp);
101144648Sdas}
102144648Sdas
103144648Sdasvoid
104144648Sdasg_vfs_orphan(struct g_consumer *cp)
105144648Sdas{
106144648Sdas
107144648Sdas	/*
108144648Sdas	 * Don't do anything here yet.
109144648Sdas	 *
110144648Sdas	 * Ideally we should detach the consumer already now, but that
111144648Sdas	 * leads to a locking requirement in the I/O path to see if we have
112144648Sdas	 * a consumer or not.  Considering how ugly things are going to get
113144648Sdas	 * anyway as none of our filesystems are graceful about i/o errors,
114144648Sdas	 * this is not important right now.
115144648Sdas	 *
116144648Sdas	 * Down the road, this is the place where we could give the user
117144648Sdas	 * a "Abort, Retry or Ignore" option to replace the media again.
118144648Sdas	 */
119144648Sdas}
120144648Sdas
121144648Sdasint
122144648Sdasg_vfs_open(struct vnode *vp, struct g_consumer **cpp, const char *fsname, int wr)
123144648Sdas{
124144648Sdas	struct g_geom *gp;
125144648Sdas	struct g_provider *pp;
126144648Sdas	struct g_consumer *cp;
127144648Sdas	struct bufobj *bo;
128144648Sdas	int error;
129144648Sdas
130144648Sdas	g_topology_assert();
131144648Sdas
132144648Sdas	*cpp = NULL;
133144648Sdas	pp = g_dev_getprovider(vp->v_rdev);
134144648Sdas	if (pp == NULL)
135144648Sdas		return (ENOENT);
136144648Sdas	gp = g_new_geomf(&g_vfs_class, "%s.%s", fsname, pp->name);
137144648Sdas	cp = g_new_consumer(gp);
138144648Sdas	g_attach(cp, pp);
139144648Sdas	error = g_access(cp, 1, wr, 1);
140144648Sdas	if (error) {
141144648Sdas		g_wither_geom(gp, ENXIO);
142144648Sdas		return (error);
143144648Sdas	}
144144648Sdas	vnode_create_vobject(vp, pp->mediasize, curthread);
145144648Sdas	*cpp = cp;
146144648Sdas	bo = &vp->v_bufobj;
147144648Sdas	bo->bo_ops = g_vfs_bufops;
148144648Sdas	bo->bo_private = cp;
149144648Sdas	bo->bo_bsize = pp->sectorsize;
150144648Sdas
151144648Sdas	return (error);
152144648Sdas}
153144648Sdas