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