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
--- 18 unchanged lines hidden (view full) ---
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_disk.c 111220 2003-02-21 19:00:48Z 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>
--- 47 unchanged lines hidden (view full) ---
91 return;
92 mtx_unlock(&Giant);
93}
94
95static int
96g_disk_access(struct g_provider *pp, int r, int w, int e)
97{
98 struct disk *dp;
99 dev_t dev;
100 int error;
101
102 g_trace(G_T_ACCESS, "g_disk_access(%s, %d, %d, %d)",
103 pp->name, r, w, e);
104 g_topology_assert();
105 r += pp->acr;
106 w += pp->acw;
107 e += pp->ace;
108 dp = pp->geom->softc;
109 dev = dp->d_dev;
110 error = 0;
111 if ((pp->acr + pp->acw + pp->ace) == 0 && (r + w + e) > 0) {
112 if (dp->d_open != NULL || dp->d_copen != NULL) {
113 g_disk_lock_giant(dp);
114 if (dp->d_open != NULL)
115 error = dp->d_open(dp);
116 else
117 error = dp->d_copen(dev, FREAD|FWRITE, 0, NULL);
118 if (error != 0)
119 printf("Opened disk %s -> %d\n",
120 pp->name, error);
121 g_disk_unlock_giant(dp);
122 }
123 pp->mediasize = dp->d_mediasize;
124 pp->sectorsize = dp->d_sectorsize;
125 dp->d_flags |= DISKFLAG_OPEN;
126 if (dp->d_maxsize == 0 && dp->d_dev->si_iosize_max != 0)
127 dp->d_maxsize = dp->d_dev->si_iosize_max;
128 if (dp->d_maxsize == 0) {
129 printf("WARNING: Disk drive %s%d has no d_maxsize\n",
130 dp->d_name, dp->d_unit);
131 dp->d_maxsize = DFLTPHYS;
132 }
133 } else if ((pp->acr + pp->acw + pp->ace) > 0 && (r + w + e) == 0) {
134 if (dp->d_close != NULL || dp->d_cclose != NULL) {
135 g_disk_lock_giant(dp);
136 if (dp->d_close != NULL)
137 error = dp->d_close(dp);
138 else
139 error = dp->d_cclose(dev, FREAD|FWRITE, 0, NULL);
140 if (error != 0)
141 printf("Closed disk %s -> %d\n",
142 pp->name, error);
143 g_disk_unlock_giant(dp);
144 }
145 dp->d_flags &= ~DISKFLAG_OPEN;
146 }
147 return (error);
--- 31 unchanged lines hidden (view full) ---
179 g_std_done(bp);
180 mtx_unlock(&g_disk_done_mtx);
181}
182
183static void
184g_disk_start(struct bio *bp)
185{
186 struct bio *bp2, *bp3;
187 dev_t dev;
188 struct disk *dp;
189 struct g_ioctl *gio;
190 int error;
191 off_t off;
192
193 dp = bp->bio_to->geom->softc;
194 dev = dp->d_dev;
195 error = EJUSTRETURN;
196 switch(bp->bio_cmd) {
197 case BIO_DELETE:
198 if (!(dp->d_flags & DISKFLAG_CANDELETE)) {
199 error = 0;
200 break;
201 }
202 /* fall-through */
--- 24 unchanged lines hidden (view full) ---
227 bp3 = g_clone_bio(bp);
228 if (bp3 == NULL)
229 bp->bio_error = ENOMEM;
230 }
231 bp2->bio_done = g_disk_done;
232 bp2->bio_blkno = bp2->bio_offset >> DEV_BSHIFT;
233 bp2->bio_pblkno = bp2->bio_offset / dp->d_sectorsize;
234 bp2->bio_bcount = bp2->bio_length;
235 bp2->bio_dev = dev;
236 bp2->bio_disk = dp;
237 g_disk_lock_giant(dp);
238 dp->d_strategy(bp2);
239 g_disk_unlock_giant(dp);
240 bp2 = bp3;
241 bp3 = NULL;
242 } while (bp2 != NULL);
243 break;
244 case BIO_GETATTR:
245 if (g_handleattr_int(bp, "GEOM::fwsectors", dp->d_fwsectors))
246 break;
247 else if (g_handleattr_int(bp, "GEOM::fwheads", dp->d_fwheads))
248 break;
249 else if (g_handleattr_off_t(bp, "GEOM::frontstuff", 0))
250 break;
251 else if (!strcmp(bp->bio_attribute, "GEOM::kerneldump"))
252 g_disk_kerneldump(bp, dp);
253 else if ((dp->d_ioctl != NULL || dp->d_cioctl != NULL) &&
254 !strcmp(bp->bio_attribute, "GEOM::ioctl") &&
255 bp->bio_length == sizeof *gio) {
256 gio = (struct g_ioctl *)bp->bio_data;
257 if (dp->d_ioctl != NULL) {
258 gio->func = (d_ioctl_t *)(dp->d_ioctl);
259 gio->dev = dp;
260 } else {
261 gio->func = dp->d_cioctl;
262 gio->dev = dp->d_dev;
263 }
264 error = EDIRIOCTL;
265 } else
266 error = ENOIOCTL;
267 break;
268 case BIO_SETATTR:
269 if (!strcmp(bp->bio_attribute, "GEOM::ioctl") &&
270 bp->bio_length == sizeof *gio) {
271 gio = (struct g_ioctl *)bp->bio_data;
272 gio->func = devsw(dp->d_dev)->d_ioctl;
273 gio->dev = dp->d_dev;
274 error = EDIRIOCTL;
275 } else
276 error = ENOIOCTL;
277 break;
278 default:
279 error = EOPNOTSUPP;
280 break;
281 }
282 if (error != EJUSTRETURN)
283 g_io_deliver(bp, error);
284 return;
--- 42 unchanged lines hidden (view full) ---
327 pp->stripesize = dp->d_stripesize;
328 g_error_provider(pp, 0);
329 if (bootverbose)
330 printf("GEOM: new disk %s\n", gp->name);
331}
332
333
334
335dev_t
336disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, void * unused __unused)
337{
338 dev_t dev;
339
340 dev = g_malloc(sizeof *dev, M_WAITOK | M_ZERO);
341 dp->d_unit = unit;
342 dp->d_dev = dev;
343 dp->d_flags = flags;
344 dp->d_devsw = cdevsw;
345 dev->si_devsw = cdevsw;
346 if (cdevsw != NULL) {
347 dp->d_copen = cdevsw->d_open;
348 dp->d_cclose = cdevsw->d_close;
349 dp->d_cioctl = cdevsw->d_ioctl;
350 dp->d_strategy = cdevsw->d_strategy;
351 dp->d_dump = cdevsw->d_dump;
352 dp->d_name = cdevsw->d_name;
353 }
354 KASSERT(dp->d_strategy != NULL, ("disk_create need d_strategy"));
355 KASSERT(dp->d_name != NULL, ("disk_create need d_name"));
356 KASSERT(*dp->d_name != 0, ("disk_create need d_name"));
357 KASSERT(strlen(dp->d_name) < SPECNAMELEN - 4, ("disk name too long"));
358 dev->si_disk = dp;
359 dev->si_udev = 0x10002; /* XXX: Needed ? */
360 dev->si_name = dev->__si_namebuf;
361 sprintf(dev->si_name, "%s%d", dp->d_name, unit);
362 g_call_me(g_disk_create, dp);
363 return (dev);
364}
365
366void
367disk_destroy(struct disk *dp)
368{
369 struct g_geom *gp;
370
371 gp = dp->d_geom;
372 g_free(dp->d_dev);
373 gp->flags |= G_GEOM_WITHER;
374 gp->softc = NULL;
375 g_orphan_provider(LIST_FIRST(&gp->provider), ENXIO);
376}
377
378static void
379g_kern_disks(void *p)
380{
--- 35 unchanged lines hidden ---
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
--- 18 unchanged lines hidden (view full) ---
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_disk.c 111220 2003-02-21 19:00:48Z 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>
--- 47 unchanged lines hidden (view full) ---
91 return;
92 mtx_unlock(&Giant);
93}
94
95static int
96g_disk_access(struct g_provider *pp, int r, int w, int e)
97{
98 struct disk *dp;
99 dev_t dev;
100 int error;
101
102 g_trace(G_T_ACCESS, "g_disk_access(%s, %d, %d, %d)",
103 pp->name, r, w, e);
104 g_topology_assert();
105 r += pp->acr;
106 w += pp->acw;
107 e += pp->ace;
108 dp = pp->geom->softc;
109 dev = dp->d_dev;
110 error = 0;
111 if ((pp->acr + pp->acw + pp->ace) == 0 && (r + w + e) > 0) {
112 if (dp->d_open != NULL || dp->d_copen != NULL) {
113 g_disk_lock_giant(dp);
114 if (dp->d_open != NULL)
115 error = dp->d_open(dp);
116 else
117 error = dp->d_copen(dev, FREAD|FWRITE, 0, NULL);
118 if (error != 0)
119 printf("Opened disk %s -> %d\n",
120 pp->name, error);
121 g_disk_unlock_giant(dp);
122 }
123 pp->mediasize = dp->d_mediasize;
124 pp->sectorsize = dp->d_sectorsize;
125 dp->d_flags |= DISKFLAG_OPEN;
126 if (dp->d_maxsize == 0 && dp->d_dev->si_iosize_max != 0)
127 dp->d_maxsize = dp->d_dev->si_iosize_max;
128 if (dp->d_maxsize == 0) {
129 printf("WARNING: Disk drive %s%d has no d_maxsize\n",
130 dp->d_name, dp->d_unit);
131 dp->d_maxsize = DFLTPHYS;
132 }
133 } else if ((pp->acr + pp->acw + pp->ace) > 0 && (r + w + e) == 0) {
134 if (dp->d_close != NULL || dp->d_cclose != NULL) {
135 g_disk_lock_giant(dp);
136 if (dp->d_close != NULL)
137 error = dp->d_close(dp);
138 else
139 error = dp->d_cclose(dev, FREAD|FWRITE, 0, NULL);
140 if (error != 0)
141 printf("Closed disk %s -> %d\n",
142 pp->name, error);
143 g_disk_unlock_giant(dp);
144 }
145 dp->d_flags &= ~DISKFLAG_OPEN;
146 }
147 return (error);
--- 31 unchanged lines hidden (view full) ---
179 g_std_done(bp);
180 mtx_unlock(&g_disk_done_mtx);
181}
182
183static void
184g_disk_start(struct bio *bp)
185{
186 struct bio *bp2, *bp3;
187 dev_t dev;
188 struct disk *dp;
189 struct g_ioctl *gio;
190 int error;
191 off_t off;
192
193 dp = bp->bio_to->geom->softc;
194 dev = dp->d_dev;
195 error = EJUSTRETURN;
196 switch(bp->bio_cmd) {
197 case BIO_DELETE:
198 if (!(dp->d_flags & DISKFLAG_CANDELETE)) {
199 error = 0;
200 break;
201 }
202 /* fall-through */
--- 24 unchanged lines hidden (view full) ---
227 bp3 = g_clone_bio(bp);
228 if (bp3 == NULL)
229 bp->bio_error = ENOMEM;
230 }
231 bp2->bio_done = g_disk_done;
232 bp2->bio_blkno = bp2->bio_offset >> DEV_BSHIFT;
233 bp2->bio_pblkno = bp2->bio_offset / dp->d_sectorsize;
234 bp2->bio_bcount = bp2->bio_length;
235 bp2->bio_dev = dev;
236 bp2->bio_disk = dp;
237 g_disk_lock_giant(dp);
238 dp->d_strategy(bp2);
239 g_disk_unlock_giant(dp);
240 bp2 = bp3;
241 bp3 = NULL;
242 } while (bp2 != NULL);
243 break;
244 case BIO_GETATTR:
245 if (g_handleattr_int(bp, "GEOM::fwsectors", dp->d_fwsectors))
246 break;
247 else if (g_handleattr_int(bp, "GEOM::fwheads", dp->d_fwheads))
248 break;
249 else if (g_handleattr_off_t(bp, "GEOM::frontstuff", 0))
250 break;
251 else if (!strcmp(bp->bio_attribute, "GEOM::kerneldump"))
252 g_disk_kerneldump(bp, dp);
253 else if ((dp->d_ioctl != NULL || dp->d_cioctl != NULL) &&
254 !strcmp(bp->bio_attribute, "GEOM::ioctl") &&
255 bp->bio_length == sizeof *gio) {
256 gio = (struct g_ioctl *)bp->bio_data;
257 if (dp->d_ioctl != NULL) {
258 gio->func = (d_ioctl_t *)(dp->d_ioctl);
259 gio->dev = dp;
260 } else {
261 gio->func = dp->d_cioctl;
262 gio->dev = dp->d_dev;
263 }
264 error = EDIRIOCTL;
265 } else
266 error = ENOIOCTL;
267 break;
268 case BIO_SETATTR:
269 if (!strcmp(bp->bio_attribute, "GEOM::ioctl") &&
270 bp->bio_length == sizeof *gio) {
271 gio = (struct g_ioctl *)bp->bio_data;
272 gio->func = devsw(dp->d_dev)->d_ioctl;
273 gio->dev = dp->d_dev;
274 error = EDIRIOCTL;
275 } else
276 error = ENOIOCTL;
277 break;
278 default:
279 error = EOPNOTSUPP;
280 break;
281 }
282 if (error != EJUSTRETURN)
283 g_io_deliver(bp, error);
284 return;
--- 42 unchanged lines hidden (view full) ---
327 pp->stripesize = dp->d_stripesize;
328 g_error_provider(pp, 0);
329 if (bootverbose)
330 printf("GEOM: new disk %s\n", gp->name);
331}
332
333
334
335dev_t
336disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, void * unused __unused)
337{
338 dev_t dev;
339
340 dev = g_malloc(sizeof *dev, M_WAITOK | M_ZERO);
341 dp->d_unit = unit;
342 dp->d_dev = dev;
343 dp->d_flags = flags;
344 dp->d_devsw = cdevsw;
345 dev->si_devsw = cdevsw;
346 if (cdevsw != NULL) {
347 dp->d_copen = cdevsw->d_open;
348 dp->d_cclose = cdevsw->d_close;
349 dp->d_cioctl = cdevsw->d_ioctl;
350 dp->d_strategy = cdevsw->d_strategy;
351 dp->d_dump = cdevsw->d_dump;
352 dp->d_name = cdevsw->d_name;
353 }
354 KASSERT(dp->d_strategy != NULL, ("disk_create need d_strategy"));
355 KASSERT(dp->d_name != NULL, ("disk_create need d_name"));
356 KASSERT(*dp->d_name != 0, ("disk_create need d_name"));
357 KASSERT(strlen(dp->d_name) < SPECNAMELEN - 4, ("disk name too long"));
358 dev->si_disk = dp;
359 dev->si_udev = 0x10002; /* XXX: Needed ? */
360 dev->si_name = dev->__si_namebuf;
361 sprintf(dev->si_name, "%s%d", dp->d_name, unit);
362 g_call_me(g_disk_create, dp);
363 return (dev);
364}
365
366void
367disk_destroy(struct disk *dp)
368{
369 struct g_geom *gp;
370
371 gp = dp->d_geom;
372 g_free(dp->d_dev);
373 gp->flags |= G_GEOM_WITHER;
374 gp->softc = NULL;
375 g_orphan_provider(LIST_FIRST(&gp->provider), ENXIO);
376}
377
378static void
379g_kern_disks(void *p)
380{
--- 35 unchanged lines hidden ---