Deleted Added
full compact
geom_slice.c (107832) geom_slice.c (107953)
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 *
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: head/sys/geom/geom_slice.c 107832 2002-12-13 21:31:13Z phk $
35 * $FreeBSD: head/sys/geom/geom_slice.c 107953 2002-12-16 22:33:27Z phk $
36 */
37
38
39#include <sys/param.h>
40#include <sys/stdint.h>
41#ifndef _KERNEL
42#include <stdio.h>
43#include <unistd.h>
44#include <stdlib.h>
45#include <signal.h>
46#include <string.h>
47#include <err.h>
48#else
49#include <sys/systm.h>
50#include <sys/kernel.h>
51#include <sys/malloc.h>
52#include <sys/bio.h>
53#include <sys/sysctl.h>
54#include <sys/proc.h>
55#include <sys/kthread.h>
56#include <sys/lock.h>
57#include <sys/mutex.h>
58#endif
59#include <sys/errno.h>
60#include <sys/sbuf.h>
61#include <geom/geom.h>
62#include <geom/geom_slice.h>
63#include <machine/stdarg.h>
64
65static g_orphan_t g_slice_orphan;
66static g_access_t g_slice_access;
67static g_start_t g_slice_start;
68
69static struct g_slicer *
70g_slice_init(unsigned nslice, unsigned scsize)
71{
72 struct g_slicer *gsp;
73
74 gsp = g_malloc(sizeof *gsp, M_WAITOK | M_ZERO);
75 gsp->softc = g_malloc(scsize, M_WAITOK | M_ZERO);
76 gsp->slices = g_malloc(nslice * sizeof(struct g_slice),
77 M_WAITOK | M_ZERO);
78 gsp->nslice = nslice;
79 return (gsp);
80}
81
82static int
83g_slice_access(struct g_provider *pp, int dr, int dw, int de)
84{
36 */
37
38
39#include <sys/param.h>
40#include <sys/stdint.h>
41#ifndef _KERNEL
42#include <stdio.h>
43#include <unistd.h>
44#include <stdlib.h>
45#include <signal.h>
46#include <string.h>
47#include <err.h>
48#else
49#include <sys/systm.h>
50#include <sys/kernel.h>
51#include <sys/malloc.h>
52#include <sys/bio.h>
53#include <sys/sysctl.h>
54#include <sys/proc.h>
55#include <sys/kthread.h>
56#include <sys/lock.h>
57#include <sys/mutex.h>
58#endif
59#include <sys/errno.h>
60#include <sys/sbuf.h>
61#include <geom/geom.h>
62#include <geom/geom_slice.h>
63#include <machine/stdarg.h>
64
65static g_orphan_t g_slice_orphan;
66static g_access_t g_slice_access;
67static g_start_t g_slice_start;
68
69static struct g_slicer *
70g_slice_init(unsigned nslice, unsigned scsize)
71{
72 struct g_slicer *gsp;
73
74 gsp = g_malloc(sizeof *gsp, M_WAITOK | M_ZERO);
75 gsp->softc = g_malloc(scsize, M_WAITOK | M_ZERO);
76 gsp->slices = g_malloc(nslice * sizeof(struct g_slice),
77 M_WAITOK | M_ZERO);
78 gsp->nslice = nslice;
79 return (gsp);
80}
81
82static int
83g_slice_access(struct g_provider *pp, int dr, int dw, int de)
84{
85 int error, i;
85 int error;
86 u_int u;
86 struct g_geom *gp;
87 struct g_consumer *cp;
88 struct g_provider *pp2;
89 struct g_slicer *gsp;
90 struct g_slice *gsl, *gsl2;
91
92 gp = pp->geom;
93 cp = LIST_FIRST(&gp->consumer);
94 KASSERT (cp != NULL, ("g_slice_access but no consumer"));
95 gsp = gp->softc;
96 gsl = &gsp->slices[pp->index];
87 struct g_geom *gp;
88 struct g_consumer *cp;
89 struct g_provider *pp2;
90 struct g_slicer *gsp;
91 struct g_slice *gsl, *gsl2;
92
93 gp = pp->geom;
94 cp = LIST_FIRST(&gp->consumer);
95 KASSERT (cp != NULL, ("g_slice_access but no consumer"));
96 gsp = gp->softc;
97 gsl = &gsp->slices[pp->index];
97 for (i = 0; i < gsp->nslice; i++) {
98 gsl2 = &gsp->slices[i];
98 for (u = 0; u < gsp->nslice; u++) {
99 gsl2 = &gsp->slices[u];
99 if (gsl2->length == 0)
100 continue;
100 if (gsl2->length == 0)
101 continue;
101 if (i == pp->index)
102 if (u == pp->index)
102 continue;
103 if (gsl->offset + gsl->length <= gsl2->offset)
104 continue;
105 if (gsl2->offset + gsl2->length <= gsl->offset)
106 continue;
107 /* overlap */
108 pp2 = gsl2->provider;
109 if ((pp->acw + dw) > 0 && pp2->ace > 0)
110 return (EPERM);
111 if ((pp->ace + de) > 0 && pp2->acw > 0)
112 return (EPERM);
113 }
114 /* On first open, grab an extra "exclusive" bit */
115 if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0)
116 de++;
117 /* ... and let go of it on last close */
118 if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1)
119 de--;
120 error = g_access_rel(cp, dr, dw, de);
121 return (error);
122}
123
124void
125g_slice_finish_hot(struct bio *bp)
126{
127 struct bio *bp2;
128 struct g_geom *gp;
129 struct g_consumer *cp;
130 struct g_slicer *gsp;
131 struct g_slice *gsl;
103 continue;
104 if (gsl->offset + gsl->length <= gsl2->offset)
105 continue;
106 if (gsl2->offset + gsl2->length <= gsl->offset)
107 continue;
108 /* overlap */
109 pp2 = gsl2->provider;
110 if ((pp->acw + dw) > 0 && pp2->ace > 0)
111 return (EPERM);
112 if ((pp->ace + de) > 0 && pp2->acw > 0)
113 return (EPERM);
114 }
115 /* On first open, grab an extra "exclusive" bit */
116 if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0)
117 de++;
118 /* ... and let go of it on last close */
119 if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1)
120 de--;
121 error = g_access_rel(cp, dr, dw, de);
122 return (error);
123}
124
125void
126g_slice_finish_hot(struct bio *bp)
127{
128 struct bio *bp2;
129 struct g_geom *gp;
130 struct g_consumer *cp;
131 struct g_slicer *gsp;
132 struct g_slice *gsl;
132 int index;
133 int idx;
133
134 KASSERT(bp->bio_to != NULL, ("NULL bio_to in g_slice_finish_hot(%p)", bp));
135 KASSERT(bp->bio_from != NULL, ("NULL bio_from in g_slice_finish_hot(%p)", bp));
136 gp = bp->bio_to->geom;
137 gsp = gp->softc;
138 cp = LIST_FIRST(&gp->consumer);
139 KASSERT(cp != NULL, ("NULL consumer in g_slice_finish_hot(%p)", bp));
134
135 KASSERT(bp->bio_to != NULL, ("NULL bio_to in g_slice_finish_hot(%p)", bp));
136 KASSERT(bp->bio_from != NULL, ("NULL bio_from in g_slice_finish_hot(%p)", bp));
137 gp = bp->bio_to->geom;
138 gsp = gp->softc;
139 cp = LIST_FIRST(&gp->consumer);
140 KASSERT(cp != NULL, ("NULL consumer in g_slice_finish_hot(%p)", bp));
140 index = bp->bio_to->index;
141 gsl = &gsp->slices[index];
141 idx = bp->bio_to->index;
142 gsl = &gsp->slices[idx];
142
143 bp2 = g_clone_bio(bp);
144 if (bp2 == NULL) {
145 g_io_deliver(bp, ENOMEM);
146 return;
147 }
148 if (bp2->bio_offset + bp2->bio_length > gsl->length)
149 bp2->bio_length = gsl->length - bp2->bio_offset;
150 bp2->bio_done = g_std_done;
151 bp2->bio_offset += gsl->offset;
152 g_io_request(bp2, cp);
153 return;
154}
155
156static void
157g_slice_start(struct bio *bp)
158{
159 struct bio *bp2;
160 struct g_provider *pp;
161 struct g_geom *gp;
162 struct g_consumer *cp;
163 struct g_slicer *gsp;
164 struct g_slice *gsl, *gmp;
143
144 bp2 = g_clone_bio(bp);
145 if (bp2 == NULL) {
146 g_io_deliver(bp, ENOMEM);
147 return;
148 }
149 if (bp2->bio_offset + bp2->bio_length > gsl->length)
150 bp2->bio_length = gsl->length - bp2->bio_offset;
151 bp2->bio_done = g_std_done;
152 bp2->bio_offset += gsl->offset;
153 g_io_request(bp2, cp);
154 return;
155}
156
157static void
158g_slice_start(struct bio *bp)
159{
160 struct bio *bp2;
161 struct g_provider *pp;
162 struct g_geom *gp;
163 struct g_consumer *cp;
164 struct g_slicer *gsp;
165 struct g_slice *gsl, *gmp;
165 int index, error;
166 int idx, error;
166 u_int m_index;
167 off_t t;
168
169 pp = bp->bio_to;
170 gp = pp->geom;
171 gsp = gp->softc;
172 cp = LIST_FIRST(&gp->consumer);
167 u_int m_index;
168 off_t t;
169
170 pp = bp->bio_to;
171 gp = pp->geom;
172 gsp = gp->softc;
173 cp = LIST_FIRST(&gp->consumer);
173 index = pp->index;
174 gsl = &gsp->slices[index];
174 idx = pp->index;
175 gsl = &gsp->slices[idx];
175 switch(bp->bio_cmd) {
176 case BIO_READ:
177 case BIO_WRITE:
178 case BIO_DELETE:
179 if (bp->bio_offset > gsl->length) {
180 g_io_deliver(bp, EINVAL); /* XXX: EWHAT ? */
181 return;
182 }
183 /*
184 * Check if we collide with any hot spaces, and call the
185 * method once if so.
186 */
187 t = bp->bio_offset + gsl->offset;
188 for (m_index = 0; m_index < gsp->nhot; m_index++) {
189 gmp = &gsp->hot[m_index];
190 if (t >= gmp->offset + gmp->length)
191 continue;
192 if (t + bp->bio_length <= gmp->offset)
193 continue;
194 error = gsp->start(bp);
195 if (error == EJUSTRETURN)
196 return;
197 else if (error) {
198 g_io_deliver(bp, error);
199 return;
200 }
201 break;
202 }
203 bp2 = g_clone_bio(bp);
204 if (bp2 == NULL) {
205 g_io_deliver(bp, ENOMEM);
206 return;
207 }
208 if (bp2->bio_offset + bp2->bio_length > gsl->length)
209 bp2->bio_length = gsl->length - bp2->bio_offset;
210 bp2->bio_done = g_std_done;
211 bp2->bio_offset += gsl->offset;
212 g_io_request(bp2, cp);
213 return;
214 case BIO_GETATTR:
215 case BIO_SETATTR:
216 /* Give the real method a chance to override */
217 if (gsp->start(bp))
218 return;
219 if (!strcmp("GEOM::frontstuff", bp->bio_attribute)) {
220 t = gsp->cfrontstuff;
221 if (gsp->frontstuff > t)
222 t = gsp->frontstuff;
223 t -= gsl->offset;
224 if (t < 0)
225 t = 0;
226 if (t > gsl->length)
227 t = gsl->length;
228 g_handleattr_off_t(bp, "GEOM::frontstuff", t);
229 return;
230 }
231#ifdef _KERNEL
232 if (!strcmp("GEOM::kerneldump", bp->bio_attribute)) {
233 struct g_kerneldump *gkd;
234
235 gkd = (struct g_kerneldump *)bp->bio_data;
176 switch(bp->bio_cmd) {
177 case BIO_READ:
178 case BIO_WRITE:
179 case BIO_DELETE:
180 if (bp->bio_offset > gsl->length) {
181 g_io_deliver(bp, EINVAL); /* XXX: EWHAT ? */
182 return;
183 }
184 /*
185 * Check if we collide with any hot spaces, and call the
186 * method once if so.
187 */
188 t = bp->bio_offset + gsl->offset;
189 for (m_index = 0; m_index < gsp->nhot; m_index++) {
190 gmp = &gsp->hot[m_index];
191 if (t >= gmp->offset + gmp->length)
192 continue;
193 if (t + bp->bio_length <= gmp->offset)
194 continue;
195 error = gsp->start(bp);
196 if (error == EJUSTRETURN)
197 return;
198 else if (error) {
199 g_io_deliver(bp, error);
200 return;
201 }
202 break;
203 }
204 bp2 = g_clone_bio(bp);
205 if (bp2 == NULL) {
206 g_io_deliver(bp, ENOMEM);
207 return;
208 }
209 if (bp2->bio_offset + bp2->bio_length > gsl->length)
210 bp2->bio_length = gsl->length - bp2->bio_offset;
211 bp2->bio_done = g_std_done;
212 bp2->bio_offset += gsl->offset;
213 g_io_request(bp2, cp);
214 return;
215 case BIO_GETATTR:
216 case BIO_SETATTR:
217 /* Give the real method a chance to override */
218 if (gsp->start(bp))
219 return;
220 if (!strcmp("GEOM::frontstuff", bp->bio_attribute)) {
221 t = gsp->cfrontstuff;
222 if (gsp->frontstuff > t)
223 t = gsp->frontstuff;
224 t -= gsl->offset;
225 if (t < 0)
226 t = 0;
227 if (t > gsl->length)
228 t = gsl->length;
229 g_handleattr_off_t(bp, "GEOM::frontstuff", t);
230 return;
231 }
232#ifdef _KERNEL
233 if (!strcmp("GEOM::kerneldump", bp->bio_attribute)) {
234 struct g_kerneldump *gkd;
235
236 gkd = (struct g_kerneldump *)bp->bio_data;
236 gkd->offset += gsp->slices[index].offset;
237 if (gkd->length > gsp->slices[index].length)
238 gkd->length = gsp->slices[index].length;
237 gkd->offset += gsp->slices[idx].offset;
238 if (gkd->length > gsp->slices[idx].length)
239 gkd->length = gsp->slices[idx].length;
239 /* now, pass it on downwards... */
240 }
241#endif
242 bp2 = g_clone_bio(bp);
243 if (bp2 == NULL) {
244 g_io_deliver(bp, ENOMEM);
245 return;
246 }
247 bp2->bio_done = g_std_done;
248 g_io_request(bp2, cp);
249 break;
250 default:
251 g_io_deliver(bp, EOPNOTSUPP);
252 return;
253 }
254}
255
256void
240 /* now, pass it on downwards... */
241 }
242#endif
243 bp2 = g_clone_bio(bp);
244 if (bp2 == NULL) {
245 g_io_deliver(bp, ENOMEM);
246 return;
247 }
248 bp2->bio_done = g_std_done;
249 g_io_request(bp2, cp);
250 break;
251 default:
252 g_io_deliver(bp, EOPNOTSUPP);
253 return;
254 }
255}
256
257void
257g_slice_dumpconf(struct sbuf *sb, char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp)
258g_slice_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp)
258{
259 struct g_slicer *gsp;
260
261 gsp = gp->softc;
262 if (indent == NULL) {
263 sbuf_printf(sb, " i %u", pp->index);
264 sbuf_printf(sb, " o %ju",
265 (uintmax_t)gsp->slices[pp->index].offset);
266 return;
267 }
268 if (gp != NULL && (pp == NULL && cp == NULL)) {
269 sbuf_printf(sb, "%s<frontstuff>%ju</frontstuff>\n",
270 indent, (intmax_t)gsp->frontstuff);
271 }
272 if (pp != NULL) {
273 sbuf_printf(sb, "%s<index>%u</index>\n", indent, pp->index);
274 sbuf_printf(sb, "%s<length>%ju</length>\n",
275 indent, (uintmax_t)gsp->slices[pp->index].length);
276 sbuf_printf(sb, "%s<seclength>%ju</seclength>\n", indent,
277 (uintmax_t)gsp->slices[pp->index].length / 512);
278 sbuf_printf(sb, "%s<offset>%ju</offset>\n", indent,
279 (uintmax_t)gsp->slices[pp->index].offset);
280 sbuf_printf(sb, "%s<secoffset>%ju</secoffset>\n", indent,
281 (uintmax_t)gsp->slices[pp->index].offset / 512);
282 }
283}
284
285int
259{
260 struct g_slicer *gsp;
261
262 gsp = gp->softc;
263 if (indent == NULL) {
264 sbuf_printf(sb, " i %u", pp->index);
265 sbuf_printf(sb, " o %ju",
266 (uintmax_t)gsp->slices[pp->index].offset);
267 return;
268 }
269 if (gp != NULL && (pp == NULL && cp == NULL)) {
270 sbuf_printf(sb, "%s<frontstuff>%ju</frontstuff>\n",
271 indent, (intmax_t)gsp->frontstuff);
272 }
273 if (pp != NULL) {
274 sbuf_printf(sb, "%s<index>%u</index>\n", indent, pp->index);
275 sbuf_printf(sb, "%s<length>%ju</length>\n",
276 indent, (uintmax_t)gsp->slices[pp->index].length);
277 sbuf_printf(sb, "%s<seclength>%ju</seclength>\n", indent,
278 (uintmax_t)gsp->slices[pp->index].length / 512);
279 sbuf_printf(sb, "%s<offset>%ju</offset>\n", indent,
280 (uintmax_t)gsp->slices[pp->index].offset);
281 sbuf_printf(sb, "%s<secoffset>%ju</secoffset>\n", indent,
282 (uintmax_t)gsp->slices[pp->index].offset / 512);
283 }
284}
285
286int
286g_slice_config(struct g_geom *gp, u_int index, int how, off_t offset, off_t length, u_int sectorsize, char *fmt, ...)
287g_slice_config(struct g_geom *gp, u_int idx, int how, off_t offset, off_t length, u_int sectorsize, const char *fmt, ...)
287{
288 struct g_provider *pp;
289 struct g_slicer *gsp;
290 struct g_slice *gsl;
291 va_list ap;
292 struct sbuf *sb;
293 int error, acc;
294
295 g_trace(G_T_TOPOLOGY, "g_slice_config(%s, %d, %d)",
288{
289 struct g_provider *pp;
290 struct g_slicer *gsp;
291 struct g_slice *gsl;
292 va_list ap;
293 struct sbuf *sb;
294 int error, acc;
295
296 g_trace(G_T_TOPOLOGY, "g_slice_config(%s, %d, %d)",
296 gp->name, index, how);
297 gp->name, idx, how);
297 g_topology_assert();
298 gsp = gp->softc;
299 error = 0;
298 g_topology_assert();
299 gsp = gp->softc;
300 error = 0;
300 if (index >= gsp->nslice)
301 if (idx >= gsp->nslice)
301 return(EINVAL);
302 return(EINVAL);
302 gsl = &gsp->slices[index];
303 gsl = &gsp->slices[idx];
303 pp = gsl->provider;
304 if (pp != NULL)
305 acc = pp->acr + pp->acw + pp->ace;
306 else
307 acc = 0;
308 if (acc != 0 && how != G_SLICE_CONFIG_FORCE) {
309 if (length < gsl->length)
310 return(EBUSY);
311 if (offset != gsl->offset)
312 return(EBUSY);
313 }
314 /* XXX: check offset + length <= MEDIASIZE */
315 if (how == G_SLICE_CONFIG_CHECK)
316 return (0);
317 gsl->length = length;
318 gsl->offset = offset;
319 gsl->sectorsize = sectorsize;
320 if (length == 0) {
321 if (pp == NULL)
322 return (0);
323 if (bootverbose)
324 printf("GEOM: Deconfigure %s\n", pp->name);
325 g_orphan_provider(pp, ENXIO);
326 gsl->provider = NULL;
327 gsp->nprovider--;
328 return (0);
329 }
330 if (pp != NULL) {
331 if (bootverbose)
332 printf("GEOM: Reconfigure %s, start %jd length %jd end %jd\n",
333 pp->name, (intmax_t)offset, (intmax_t)length,
334 (intmax_t)(offset + length - 1));
335 pp->mediasize = gsl->length;
336 return (0);
337 }
338 va_start(ap, fmt);
339 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
340 sbuf_vprintf(sb, fmt, ap);
341 sbuf_finish(sb);
342 pp = g_new_providerf(gp, sbuf_data(sb));
343 if (bootverbose)
344 printf("GEOM: Configure %s, start %jd length %jd end %jd\n",
345 pp->name, (intmax_t)offset, (intmax_t)length,
346 (intmax_t)(offset + length - 1));
304 pp = gsl->provider;
305 if (pp != NULL)
306 acc = pp->acr + pp->acw + pp->ace;
307 else
308 acc = 0;
309 if (acc != 0 && how != G_SLICE_CONFIG_FORCE) {
310 if (length < gsl->length)
311 return(EBUSY);
312 if (offset != gsl->offset)
313 return(EBUSY);
314 }
315 /* XXX: check offset + length <= MEDIASIZE */
316 if (how == G_SLICE_CONFIG_CHECK)
317 return (0);
318 gsl->length = length;
319 gsl->offset = offset;
320 gsl->sectorsize = sectorsize;
321 if (length == 0) {
322 if (pp == NULL)
323 return (0);
324 if (bootverbose)
325 printf("GEOM: Deconfigure %s\n", pp->name);
326 g_orphan_provider(pp, ENXIO);
327 gsl->provider = NULL;
328 gsp->nprovider--;
329 return (0);
330 }
331 if (pp != NULL) {
332 if (bootverbose)
333 printf("GEOM: Reconfigure %s, start %jd length %jd end %jd\n",
334 pp->name, (intmax_t)offset, (intmax_t)length,
335 (intmax_t)(offset + length - 1));
336 pp->mediasize = gsl->length;
337 return (0);
338 }
339 va_start(ap, fmt);
340 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
341 sbuf_vprintf(sb, fmt, ap);
342 sbuf_finish(sb);
343 pp = g_new_providerf(gp, sbuf_data(sb));
344 if (bootverbose)
345 printf("GEOM: Configure %s, start %jd length %jd end %jd\n",
346 pp->name, (intmax_t)offset, (intmax_t)length,
347 (intmax_t)(offset + length - 1));
347 pp->index = index;
348 pp->index = idx;
348 pp->mediasize = gsl->length;
349 pp->sectorsize = gsl->sectorsize;
350 gsl->provider = pp;
351 gsp->nprovider++;
352 g_error_provider(pp, 0);
353 sbuf_delete(sb);
354 return(0);
355}
356
357int
349 pp->mediasize = gsl->length;
350 pp->sectorsize = gsl->sectorsize;
351 gsl->provider = pp;
352 gsp->nprovider++;
353 g_error_provider(pp, 0);
354 sbuf_delete(sb);
355 return(0);
356}
357
358int
358g_slice_conf_hot(struct g_geom *gp, u_int index, off_t offset, off_t length)
359g_slice_conf_hot(struct g_geom *gp, u_int idx, off_t offset, off_t length)
359{
360 struct g_slicer *gsp;
361 struct g_slice *gsl, *gsl2;
362
363 g_trace(G_T_TOPOLOGY, "g_slice_conf_hot()");
364 g_topology_assert();
365 gsp = gp->softc;
366 gsl = gsp->hot;
360{
361 struct g_slicer *gsp;
362 struct g_slice *gsl, *gsl2;
363
364 g_trace(G_T_TOPOLOGY, "g_slice_conf_hot()");
365 g_topology_assert();
366 gsp = gp->softc;
367 gsl = gsp->hot;
367 if(index >= gsp->nhot) {
368 gsl2 = g_malloc((index + 1) * sizeof *gsl2, M_WAITOK | M_ZERO);
368 if(idx >= gsp->nhot) {
369 gsl2 = g_malloc((idx + 1) * sizeof *gsl2, M_WAITOK | M_ZERO);
369 if (gsp->hot != NULL)
370 bcopy(gsp->hot, gsl2, gsp->nhot * sizeof *gsl2);
371 gsp->hot = gsl2;
372 if (gsp->hot != NULL)
373 g_free(gsl);
374 gsl = gsl2;
370 if (gsp->hot != NULL)
371 bcopy(gsp->hot, gsl2, gsp->nhot * sizeof *gsl2);
372 gsp->hot = gsl2;
373 if (gsp->hot != NULL)
374 g_free(gsl);
375 gsl = gsl2;
375 gsp->nhot = index + 1;
376 gsp->nhot = idx + 1;
376 }
377 if (bootverbose)
378 printf("GEOM: Add %s hot[%d] start %jd length %jd end %jd\n",
377 }
378 if (bootverbose)
379 printf("GEOM: Add %s hot[%d] start %jd length %jd end %jd\n",
379 gp->name, index, (intmax_t)offset, (intmax_t)length,
380 gp->name, idx, (intmax_t)offset, (intmax_t)length,
380 (intmax_t)(offset + length - 1));
381 (intmax_t)(offset + length - 1));
381 gsl[index].offset = offset;
382 gsl[index].length = length;
382 gsl[idx].offset = offset;
383 gsl[idx].length = length;
383 return (0);
384}
385
386struct g_provider *
384 return (0);
385}
386
387struct g_provider *
387g_slice_addslice(struct g_geom *gp, int index, off_t offset, off_t length, u_int sectorsize, char *fmt, ...)
388g_slice_addslice(struct g_geom *gp, int idx, off_t offset, off_t length, u_int sectorsize, const char *fmt, ...)
388{
389 struct g_provider *pp;
390 struct g_slicer *gsp;
391 va_list ap;
392 struct sbuf *sb;
393
394 g_trace(G_T_TOPOLOGY, "g_slice_addslice()");
395 g_topology_assert();
396 gsp = gp->softc;
397 va_start(ap, fmt);
398 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
399 sbuf_vprintf(sb, fmt, ap);
400 sbuf_finish(sb);
401 pp = g_new_providerf(gp, sbuf_data(sb));
402
389{
390 struct g_provider *pp;
391 struct g_slicer *gsp;
392 va_list ap;
393 struct sbuf *sb;
394
395 g_trace(G_T_TOPOLOGY, "g_slice_addslice()");
396 g_topology_assert();
397 gsp = gp->softc;
398 va_start(ap, fmt);
399 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
400 sbuf_vprintf(sb, fmt, ap);
401 sbuf_finish(sb);
402 pp = g_new_providerf(gp, sbuf_data(sb));
403
403 pp->index = index;
404 gsp->slices[index].length = length;
405 gsp->slices[index].offset = offset;
406 gsp->slices[index].provider = pp;
407 gsp->slices[index].sectorsize = sectorsize;
408 pp->mediasize = gsp->slices[index].length;
409 pp->sectorsize = gsp->slices[index].sectorsize;
404 pp->index = idx;
405 gsp->slices[idx].length = length;
406 gsp->slices[idx].offset = offset;
407 gsp->slices[idx].provider = pp;
408 gsp->slices[idx].sectorsize = sectorsize;
409 pp->mediasize = gsp->slices[idx].length;
410 pp->sectorsize = gsp->slices[idx].sectorsize;
410 sbuf_delete(sb);
411 if (bootverbose)
412 printf("GEOM: Add %s, start %jd length %jd end %jd\n",
413 pp->name, (intmax_t)offset, (intmax_t)length,
414 (intmax_t)(offset + length - 1));
415 return(pp);
416}
417
418struct g_geom *
419g_slice_new(struct g_class *mp, u_int slices, struct g_provider *pp, struct g_consumer **cpp, void *extrap, int extra, g_slice_start_t *start)
420{
421 struct g_geom *gp;
422 struct g_slicer *gsp;
423 struct g_consumer *cp;
424 void **vp;
425 int error, i;
426
427 g_topology_assert();
428 vp = (void **)extrap;
429 gp = g_new_geomf(mp, "%s", pp->name);
430 gsp = g_slice_init(slices, extra);
431 gsp->start = start;
432 gp->access = g_slice_access;
433 gp->orphan = g_slice_orphan;
434 gp->softc = gsp;
435 gp->start = g_slice_start;
436 gp->spoiled = g_std_spoiled;
437 gp->dumpconf = g_slice_dumpconf;
438 cp = g_new_consumer(gp);
439 error = g_attach(cp, pp);
440 if (error == 0)
441 error = g_access_rel(cp, 1, 0, 0);
442 if (error) {
443 if (cp->provider != NULL)
444 g_detach(cp);
445 g_destroy_consumer(cp);
446 g_free(gsp->slices);
447 g_free(gp->softc);
448 g_destroy_geom(gp);
449 return (NULL);
450 }
451 /* Find out if there are any magic bytes on the consumer */
452 i = sizeof gsp->cfrontstuff;
453 error = g_io_getattr("GEOM::frontstuff", cp, &i, &gsp->cfrontstuff);
454 if (error)
455 gsp->cfrontstuff = 0;
456 *vp = gsp->softc;
457 *cpp = cp;
458 return (gp);
459}
460
461static void
462g_slice_orphan(struct g_consumer *cp)
463{
464 struct g_geom *gp;
465 struct g_provider *pp;
466 int error;
467
468 g_trace(G_T_TOPOLOGY, "g_slice_orphan(%p/%s)", cp, cp->provider->name);
469 g_topology_assert();
470 KASSERT(cp->provider->error != 0,
471 ("g_slice_orphan with error == 0"));
472
473 gp = cp->geom;
474 /* XXX: Not good enough we leak the softc and its suballocations */
475 gp->flags |= G_GEOM_WITHER;
476 error = cp->provider->error;
477 LIST_FOREACH(pp, &gp->provider, provider)
478 g_orphan_provider(pp, error);
479 return;
480}
411 sbuf_delete(sb);
412 if (bootverbose)
413 printf("GEOM: Add %s, start %jd length %jd end %jd\n",
414 pp->name, (intmax_t)offset, (intmax_t)length,
415 (intmax_t)(offset + length - 1));
416 return(pp);
417}
418
419struct g_geom *
420g_slice_new(struct g_class *mp, u_int slices, struct g_provider *pp, struct g_consumer **cpp, void *extrap, int extra, g_slice_start_t *start)
421{
422 struct g_geom *gp;
423 struct g_slicer *gsp;
424 struct g_consumer *cp;
425 void **vp;
426 int error, i;
427
428 g_topology_assert();
429 vp = (void **)extrap;
430 gp = g_new_geomf(mp, "%s", pp->name);
431 gsp = g_slice_init(slices, extra);
432 gsp->start = start;
433 gp->access = g_slice_access;
434 gp->orphan = g_slice_orphan;
435 gp->softc = gsp;
436 gp->start = g_slice_start;
437 gp->spoiled = g_std_spoiled;
438 gp->dumpconf = g_slice_dumpconf;
439 cp = g_new_consumer(gp);
440 error = g_attach(cp, pp);
441 if (error == 0)
442 error = g_access_rel(cp, 1, 0, 0);
443 if (error) {
444 if (cp->provider != NULL)
445 g_detach(cp);
446 g_destroy_consumer(cp);
447 g_free(gsp->slices);
448 g_free(gp->softc);
449 g_destroy_geom(gp);
450 return (NULL);
451 }
452 /* Find out if there are any magic bytes on the consumer */
453 i = sizeof gsp->cfrontstuff;
454 error = g_io_getattr("GEOM::frontstuff", cp, &i, &gsp->cfrontstuff);
455 if (error)
456 gsp->cfrontstuff = 0;
457 *vp = gsp->softc;
458 *cpp = cp;
459 return (gp);
460}
461
462static void
463g_slice_orphan(struct g_consumer *cp)
464{
465 struct g_geom *gp;
466 struct g_provider *pp;
467 int error;
468
469 g_trace(G_T_TOPOLOGY, "g_slice_orphan(%p/%s)", cp, cp->provider->name);
470 g_topology_assert();
471 KASSERT(cp->provider->error != 0,
472 ("g_slice_orphan with error == 0"));
473
474 gp = cp->geom;
475 /* XXX: Not good enough we leak the softc and its suballocations */
476 gp->flags |= G_GEOM_WITHER;
477 error = cp->provider->error;
478 LIST_FOREACH(pp, &gp->provider, provider)
479 g_orphan_provider(pp, error);
480 return;
481}