geom_ctl.c revision 105068
1105068Sphk/*-
2105068Sphk * Copyright (c) 2002 Poul-Henning Kamp
3105068Sphk * Copyright (c) 2002 Networks Associates Technology, Inc.
4105068Sphk * All rights reserved.
5105068Sphk *
6105068Sphk * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7105068Sphk * and NAI Labs, the Security Research Division of Network Associates, Inc.
8105068Sphk * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9105068Sphk * DARPA CHATS research program.
10105068Sphk *
11105068Sphk * Redistribution and use in source and binary forms, with or without
12105068Sphk * modification, are permitted provided that the following conditions
13105068Sphk * are met:
14105068Sphk * 1. Redistributions of source code must retain the above copyright
15105068Sphk *    notice, this list of conditions and the following disclaimer.
16105068Sphk * 2. Redistributions in binary form must reproduce the above copyright
17105068Sphk *    notice, this list of conditions and the following disclaimer in the
18105068Sphk *    documentation and/or other materials provided with the distribution.
19105068Sphk * 3. The names of the authors may not be used to endorse or promote
20105068Sphk *    products derived from this software without specific prior written
21105068Sphk *    permission.
22105068Sphk *
23105068Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24105068Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25105068Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26105068Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27105068Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28105068Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29105068Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30105068Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31105068Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32105068Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33105068Sphk * SUCH DAMAGE.
34105068Sphk *
35105068Sphk * $FreeBSD: head/sys/geom/geom_ctl.c 105068 2002-10-13 20:33:33Z phk $
36105068Sphk */
37105068Sphk
38105068Sphk#include "opt_geom.h"
39105068Sphk
40105068Sphk#include <sys/param.h>
41105068Sphk#include <sys/systm.h>
42105068Sphk#include <sys/kernel.h>
43105068Sphk#include <sys/sysctl.h>
44105068Sphk#include <sys/bio.h>
45105068Sphk#include <sys/conf.h>
46105068Sphk#include <sys/disk.h>
47105068Sphk#include <sys/malloc.h>
48105068Sphk#include <sys/sysctl.h>
49105068Sphk#include <sys/stdint.h>
50105068Sphk
51105068Sphk#include <sys/lock.h>
52105068Sphk#include <sys/mutex.h>
53105068Sphk#include <geom/geom.h>
54105068Sphk#include <geom/geom_int.h>
55105068Sphk
56105068Sphkstatic g_access_t g_ctl_access;
57105068Sphkstatic g_start_t g_ctl_start;
58105068Sphkstatic void g_ctl_init(void);
59105068Sphkstatic d_ioctl_t g_ctl_ioctl;
60105068Sphk
61105068Sphkstruct g_class g_ctl_class = {
62105068Sphk	"GEOMCTL",
63105068Sphk	NULL,
64105068Sphk	NULL,
65105068Sphk	G_CLASS_INITIALIZER
66105068Sphk};
67105068Sphk
68105068SphkDECLARE_GEOM_CLASS_INIT(g_ctl_class, g_ctl, g_ctl_init);
69105068Sphk
70105068Sphk/*
71105068Sphk * We cannot do create our geom.ctl geom/provider in g_ctl_init() because
72105068Sphk * the event thread has to finish adding our class first and that doesn't
73105068Sphk * happen until later.  We know however, that the events are processed in
74105068Sphk * FIFO order, so scheduling g_ctl_init2() with g_call_me() is safe.
75105068Sphk */
76105068Sphk
77105068Sphkstatic void
78105068Sphkg_ctl_init2(void *p __unused)
79105068Sphk{
80105068Sphk	struct g_geom *gp;
81105068Sphk	struct g_provider *pp;
82105068Sphk
83105068Sphk	g_topology_assert();
84105068Sphk	gp = g_new_geomf(&g_ctl_class, "geom.ctl");
85105068Sphk	gp->start = g_ctl_start;
86105068Sphk	gp->access = g_ctl_access;
87105068Sphk	pp = g_new_providerf(gp, "%s", gp->name);
88105068Sphk	g_error_provider(pp, 0);
89105068Sphk}
90105068Sphk
91105068Sphkstatic void
92105068Sphkg_ctl_init(void)
93105068Sphk{
94105068Sphk	mtx_unlock(&Giant);
95105068Sphk	g_add_class(&g_ctl_class);
96105068Sphk	g_call_me(g_ctl_init2, NULL);
97105068Sphk	mtx_lock(&Giant);
98105068Sphk}
99105068Sphk
100105068Sphk/*
101105068Sphk * We allow any kind of access.  Access control is handled at the devfs
102105068Sphk * level.
103105068Sphk */
104105068Sphk
105105068Sphkstatic int
106105068Sphkg_ctl_access(struct g_provider *pp, int r, int w, int e)
107105068Sphk{
108105068Sphk	int error;
109105068Sphk
110105068Sphk	g_trace(G_T_ACCESS, "g_ctl_access(%s, %d, %d, %d)",
111105068Sphk	    pp->name, r, w, e);
112105068Sphk
113105068Sphk	g_topology_assert();
114105068Sphk	error = 0;
115105068Sphk	return (error);
116105068Sphk}
117105068Sphk
118105068Sphkstatic void
119105068Sphkg_ctl_start(struct bio *bp)
120105068Sphk{
121105068Sphk	struct g_ioctl *gio;
122105068Sphk	int error;
123105068Sphk
124105068Sphk	switch(bp->bio_cmd) {
125105068Sphk	case BIO_DELETE:
126105068Sphk	case BIO_READ:
127105068Sphk	case BIO_WRITE:
128105068Sphk		error = EOPNOTSUPP;
129105068Sphk		break;
130105068Sphk	case BIO_GETATTR:
131105068Sphk	case BIO_SETATTR:
132105068Sphk		if (strcmp(bp->bio_attribute, "GEOM::ioctl") ||
133105068Sphk		    bp->bio_length != sizeof *gio) {
134105068Sphk			error = EOPNOTSUPP;
135105068Sphk			break;
136105068Sphk		}
137105068Sphk		gio = (struct g_ioctl *)bp->bio_data;
138105068Sphk		gio->func = g_ctl_ioctl;
139105068Sphk		error = EDIRIOCTL;
140105068Sphk		break;
141105068Sphk	default:
142105068Sphk		error = EOPNOTSUPP;
143105068Sphk		break;
144105068Sphk	}
145105068Sphk	g_io_deliver(bp, error);
146105068Sphk	return;
147105068Sphk}
148105068Sphk
149105068Sphk/*
150105068Sphk * All the stuff above is really just needed to get to this one.
151105068Sphk */
152105068Sphk
153105068Sphkstatic int
154105068Sphkg_ctl_ioctl_getconf(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
155105068Sphk{
156105068Sphk	struct geomgetconf *gcp;
157105068Sphk	struct sbuf *sb;
158105068Sphk	int error;
159105068Sphk	u_int l;
160105068Sphk
161105068Sphk	gcp = (struct geomgetconf *)data;
162105068Sphk	sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
163105068Sphk	sbuf_clear(sb);
164105068Sphk	g_confxml(sb);
165105068Sphk	l = sbuf_len(sb) + 1;
166105068Sphk	if (l > gcp->len)
167105068Sphk		error = ENOMEM;
168105068Sphk	else
169105068Sphk		error = copyout(sbuf_data(sb), gcp->ptr, l);
170105068Sphk	sbuf_delete(sb);
171105068Sphk	return(error);
172105068Sphk}
173105068Sphk
174105068Sphkstatic int
175105068Sphkg_ctl_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
176105068Sphk{
177105068Sphk	int error;
178105068Sphk
179105068Sphk	DROP_GIANT();
180105068Sphk	g_topology_lock();
181105068Sphk	switch(cmd) {
182105068Sphk	case GEOMGETCONF:
183105068Sphk		error = g_ctl_ioctl_getconf(dev, cmd, data, fflag, td);
184105068Sphk		break;
185105068Sphk	default:
186105068Sphk		error = ENOTTY;
187105068Sphk		break;
188105068Sphk	}
189105068Sphk	g_topology_unlock();
190105068Sphk	PICKUP_GIANT();
191105068Sphk	return (error);
192105068Sphk
193105068Sphk}
194