FreeBSD/Linux Kernel Cross Reference
sys/geom/geom_ctl.c
1 /*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9 * DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The names of the authors may not be used to endorse or promote
20 * products derived from this software without specific prior written
21 * permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * $FreeBSD: releng/5.0/sys/geom/geom_ctl.c 106518 2002-11-06 20:05:15Z phk $
36 */
37
38 #include "opt_geom.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/sysctl.h>
44 #include <sys/bio.h>
45 #include <sys/conf.h>
46 #include <sys/disk.h>
47 #include <sys/malloc.h>
48 #include <sys/sysctl.h>
49 #include <sys/stdint.h>
50
51 #include <sys/lock.h>
52 #include <sys/mutex.h>
53 #include <geom/geom.h>
54 #include <geom/geom_int.h>
55
56 static g_access_t g_ctl_access;
57 static g_start_t g_ctl_start;
58 static void g_ctl_init(void);
59 static d_ioctl_t g_ctl_ioctl;
60
61 struct g_class g_ctl_class = {
62 "GEOMCTL",
63 NULL,
64 NULL,
65 G_CLASS_INITIALIZER
66 };
67
68 DECLARE_GEOM_CLASS_INIT(g_ctl_class, g_ctl, g_ctl_init);
69
70 /*
71 * We cannot do create our geom.ctl geom/provider in g_ctl_init() because
72 * the event thread has to finish adding our class first and that doesn't
73 * happen until later. We know however, that the events are processed in
74 * FIFO order, so scheduling g_ctl_init2() with g_call_me() is safe.
75 */
76
77 static void
78 g_ctl_init2(void *p __unused)
79 {
80 struct g_geom *gp;
81 struct g_provider *pp;
82
83 g_topology_assert();
84 gp = g_new_geomf(&g_ctl_class, "geom.ctl");
85 gp->start = g_ctl_start;
86 gp->access = g_ctl_access;
87 pp = g_new_providerf(gp, "%s", gp->name);
88 pp->sectorsize = 512;
89 g_error_provider(pp, 0);
90 }
91
92 static void
93 g_ctl_init(void)
94 {
95 mtx_unlock(&Giant);
96 g_add_class(&g_ctl_class);
97 g_call_me(g_ctl_init2, NULL);
98 mtx_lock(&Giant);
99 }
100
101 /*
102 * We allow any kind of access. Access control is handled at the devfs
103 * level.
104 */
105
106 static int
107 g_ctl_access(struct g_provider *pp, int r, int w, int e)
108 {
109 int error;
110
111 g_trace(G_T_ACCESS, "g_ctl_access(%s, %d, %d, %d)",
112 pp->name, r, w, e);
113
114 g_topology_assert();
115 error = 0;
116 return (error);
117 }
118
119 static void
120 g_ctl_start(struct bio *bp)
121 {
122 struct g_ioctl *gio;
123 int error;
124
125 switch(bp->bio_cmd) {
126 case BIO_DELETE:
127 case BIO_READ:
128 case BIO_WRITE:
129 error = EOPNOTSUPP;
130 break;
131 case BIO_GETATTR:
132 case BIO_SETATTR:
133 if (strcmp(bp->bio_attribute, "GEOM::ioctl") ||
134 bp->bio_length != sizeof *gio) {
135 error = EOPNOTSUPP;
136 break;
137 }
138 gio = (struct g_ioctl *)bp->bio_data;
139 gio->func = g_ctl_ioctl;
140 error = EDIRIOCTL;
141 break;
142 default:
143 error = EOPNOTSUPP;
144 break;
145 }
146 g_io_deliver(bp, error);
147 return;
148 }
149
150 /*
151 * All the stuff above is really just needed to get to the stuff below
152 */
153
154 static int
155 g_ctl_ioctl_configgeom(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
156 {
157 struct geomconfiggeom *gcp;
158 struct g_configargs ga;
159 int error;
160
161 error = 0;
162 bzero(&ga, sizeof ga);
163 gcp = (struct geomconfiggeom *)data;
164 ga.class = g_idclass(&gcp->class);
165 if (ga.class == NULL)
166 return (EINVAL);
167 if (ga.class->config == NULL)
168 return (EOPNOTSUPP);
169 ga.geom = g_idgeom(&gcp->geom);
170 ga.provider = g_idprovider(&gcp->provider);
171 ga.len = gcp->len;
172 if (gcp->len > 64 * 1024)
173 return (EINVAL);
174 else if (gcp->len == 0) {
175 ga.ptr = NULL;
176 } else {
177 ga.ptr = g_malloc(gcp->len, M_WAITOK);
178 error = copyin(gcp->ptr, ga.ptr, gcp->len);
179 if (error) {
180 g_free(ga.ptr);
181 return (error);
182 }
183 }
184 ga.flag = gcp->flag;
185 error = ga.class->config(&ga);
186 if (gcp->len != 0)
187 copyout(ga.ptr, gcp->ptr, gcp->len); /* Ignore error */
188 gcp->class.u.id = (uintptr_t)ga.class;
189 gcp->class.len = 0;
190 gcp->geom.u.id = (uintptr_t)ga.geom;
191 gcp->geom.len = 0;
192 gcp->provider.u.id = (uintptr_t)ga.provider;
193 gcp->provider.len = 0;
194 return(error);
195 }
196
197 static int
198 g_ctl_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
199 {
200 int error;
201
202 DROP_GIANT();
203 g_topology_lock();
204 switch(cmd) {
205 case GEOMCONFIGGEOM:
206 error = g_ctl_ioctl_configgeom(dev, cmd, data, fflag, td);
207 break;
208 default:
209 error = ENOTTY;
210 break;
211 }
212 g_topology_unlock();
213 PICKUP_GIANT();
214 return (error);
215
216 }
Cache object: 74d5bd330682165e092528ce5ad7b11b
|