geom_vfs.c revision 140056
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 140056 2005-01-11 10:43:08Z phk $");
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>
36137034Sphk
37137034Sphk#include <geom/geom.h>
38137034Sphk#include <geom/geom_vfs.h>
39137034Sphk
40137034Sphk/*
41137034Sphk * subroutines for use by filesystems.
42137034Sphk *
43137034Sphk * XXX: should maybe live somewhere else ?
44137034Sphk */
45137034Sphk#include <sys/buf.h>
46137034Sphk
47137034Sphkstatic struct buf_ops __g_vfs_bufops = {
48137034Sphk	.bop_name =	"GEOM_VFS",
49137034Sphk	.bop_write =	bufwrite,
50137034Sphk	.bop_strategy =	g_vfs_strategy,
51140056Sphk	.bop_sync =	bufsync,
52137034Sphk};
53137034Sphk
54137034Sphkstruct buf_ops *g_vfs_bufops = &__g_vfs_bufops;
55137034Sphk
56137034Sphkstatic struct g_class g_vfs_class = {
57137034Sphk	.name =		"VFS",
58137034Sphk	.version =	G_VERSION,
59137034Sphk	.orphan =	g_vfs_orphan,
60137034Sphk};
61137034Sphk
62137034SphkDECLARE_GEOM_CLASS(g_vfs_class, g_vfs);
63137034Sphk
64137034Sphkstatic void
65137034Sphkg_vfs_done(struct bio *bip)
66137034Sphk{
67137034Sphk	struct buf *bp;
68137034Sphk
69137034Sphk	if (bip->bio_error) {
70137184Sphk		printf("g_vfs_done():");
71137034Sphk		g_print_bio(bip);
72137034Sphk		printf("error = %d\n", bip->bio_error);
73137034Sphk	}
74137034Sphk	bp = bip->bio_caller2;
75137034Sphk	bp->b_error = bip->bio_error;
76137034Sphk	bp->b_ioflags = bip->bio_flags;
77137034Sphk	if (bip->bio_error)
78137034Sphk		bp->b_ioflags |= BIO_ERROR;
79137034Sphk	bp->b_resid = bp->b_bcount - bip->bio_completed;
80137034Sphk	g_destroy_bio(bip);
81137034Sphk	mtx_lock(&Giant);
82137034Sphk	bufdone(bp);
83137034Sphk	mtx_unlock(&Giant);
84137034Sphk}
85137034Sphk
86137034Sphkvoid
87137034Sphkg_vfs_strategy(struct bufobj *bo, struct buf *bp)
88137034Sphk{
89137034Sphk	struct g_consumer *cp;
90137034Sphk	struct bio *bip;
91137034Sphk
92137034Sphk	cp = bo->bo_private;
93137034Sphk	G_VALID_CONSUMER(cp);
94137034Sphk
95137034Sphk	bip = g_alloc_bio();
96137034Sphk	bip->bio_cmd = bp->b_iocmd;
97137034Sphk	bip->bio_offset = bp->b_iooffset;
98137034Sphk	bip->bio_data = bp->b_data;
99137034Sphk	bip->bio_done = g_vfs_done;
100137034Sphk	bip->bio_caller2 = bp;
101137034Sphk	bip->bio_length = bp->b_bcount;
102137034Sphk	g_io_request(bip, cp);
103137034Sphk}
104137034Sphk
105137034Sphkvoid
106137034Sphkg_vfs_orphan(struct g_consumer *cp)
107137034Sphk{
108137034Sphk
109137034Sphk	/*
110137034Sphk	 * Don't do anything here yet.
111137034Sphk	 *
112137034Sphk	 * Ideally we should detach the consumer already now, but that
113137034Sphk	 * leads to a locking requirement in the I/O path to see if we have
114137034Sphk	 * a consumer or not.  Considering how ugly things are going to get
115137034Sphk	 * anyway as none of our filesystems are graceful about i/o errors,
116137034Sphk	 * this is not important right now.
117137034Sphk	 *
118137034Sphk	 * Down the road, this is the place where we could give the user
119137034Sphk	 * a "Abort, Retry or Ignore" option to replace the media again.
120137034Sphk	 */
121137034Sphk}
122137034Sphk
123137034Sphkint
124137034Sphkg_vfs_open(struct vnode *vp, struct g_consumer **cpp, const char *fsname, int wr)
125137034Sphk{
126137034Sphk	struct g_geom *gp;
127137034Sphk	struct g_provider *pp;
128137034Sphk	struct g_consumer *cp;
129137034Sphk	struct bufobj *bo;
130137034Sphk	int error;
131137034Sphk
132137034Sphk	g_topology_assert();
133137034Sphk
134137034Sphk	*cpp = NULL;
135137034Sphk	pp = g_dev_getprovider(vp->v_rdev);
136137034Sphk	if (pp == NULL)
137137034Sphk		return (ENOENT);
138137034Sphk	gp = g_new_geomf(&g_vfs_class, "%s.%s", fsname, pp->name);
139137034Sphk	cp = g_new_consumer(gp);
140137034Sphk	g_attach(cp, pp);
141137034Sphk	error = g_access(cp, 1, wr, 1);
142137034Sphk	if (error) {
143137034Sphk		g_wither_geom(gp, ENXIO);
144137034Sphk		return (error);
145137034Sphk	}
146137034Sphk	*cpp = cp;
147137034Sphk	bo = &vp->v_bufobj;
148137034Sphk	bo->bo_ops = g_vfs_bufops;
149137034Sphk	bo->bo_private = cp;
150137034Sphk	bo->bo_bsize = pp->sectorsize;
151137034Sphk
152137034Sphk	return (error);
153137034Sphk}
154