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
--- 20 unchanged lines hidden (view full) ---
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
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: head/sys/geom/geom_disk.c 248516 2013-03-19 14:49:15Z kib $");
38
39#include "opt_geom.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/sysctl.h>
45#include <sys/bio.h>
--- 9 unchanged lines hidden (view full) ---
55#include <sys/mutex.h>
56#include <geom/geom.h>
57#include <geom/geom_disk.h>
58#include <geom/geom_int.h>
59
60#include <dev/led/led.h>
61
62struct g_disk_softc {
63 struct disk *dp;
64 struct sysctl_ctx_list sysctl_ctx;
65 struct sysctl_oid *sysctl_tree;
66 char led[64];
67 uint32_t state;
68};
69
70static struct mtx g_disk_done_mtx;
71
72static g_access_t g_disk_access;
73static g_init_t g_disk_init;
74static g_fini_t g_disk_fini;
75static g_start_t g_disk_start;
76static g_ioctl_t g_disk_ioctl;
77static g_dumpconf_t g_disk_dumpconf;
78static g_provgone_t g_disk_providergone;
79
80static struct g_class g_disk_class = {
81 .name = "DISK",
82 .version = G_VERSION,
83 .init = g_disk_init,
84 .fini = g_disk_fini,
85 .start = g_disk_start,
86 .access = g_disk_access,
87 .ioctl = g_disk_ioctl,
88 .providergone = g_disk_providergone,
89 .dumpconf = g_disk_dumpconf,
90};
91
92SYSCTL_DECL(_kern_geom);
93static SYSCTL_NODE(_kern_geom, OID_AUTO, disk, CTLFLAG_RW, 0,
94 "GEOM_DISK stuff");
95
96static void
97g_disk_init(struct g_class *mp __unused)
98{
99
100 mtx_init(&g_disk_done_mtx, "g_disk_done", NULL, MTX_DEF);
101}
102
103static void
104g_disk_fini(struct g_class *mp __unused)
105{
106
107 mtx_destroy(&g_disk_done_mtx);
108}
109
110DECLARE_GEOM_CLASS(g_disk_class, g_disk);
111
112static void __inline
113g_disk_lock_giant(struct disk *dp)
114{
115
116 if (dp->d_flags & DISKFLAG_NEEDSGIANT)
117 mtx_lock(&Giant);
--- 12 unchanged lines hidden (view full) ---
130{
131 struct disk *dp;
132 struct g_disk_softc *sc;
133 int error;
134
135 g_trace(G_T_ACCESS, "g_disk_access(%s, %d, %d, %d)",
136 pp->name, r, w, e);
137 g_topology_assert();
138 sc = pp->geom->softc;
139 if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
140 /*
141 * Allow decreasing access count even if disk is not
142 * avaliable anymore.
143 */
144 if (r <= 0 && w <= 0 && e <= 0)
145 return (0);
146 return (ENXIO);
--- 88 unchanged lines hidden (view full) ---
235 }
236 g_io_deliver(bp, 0);
237}
238
239static void
240g_disk_done(struct bio *bp)
241{
242 struct bio *bp2;
243 struct disk *dp;
244 struct g_disk_softc *sc;
245
246 /* See "notes" for why we need a mutex here */
247 /* XXX: will witness accept a mix of Giant/unGiant drivers here ? */
248 mtx_lock(&g_disk_done_mtx);
249 bp->bio_completed = bp->bio_length - bp->bio_resid;
250
251 bp2 = bp->bio_parent;
252 if (bp2->bio_error == 0)
253 bp2->bio_error = bp->bio_error;
254 bp2->bio_completed += bp->bio_completed;
255 if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) != 0 &&
256 (sc = bp2->bio_to->geom->softc) != NULL &&
257 (dp = sc->dp) != NULL) {
258 devstat_end_transaction_bio(dp->d_devstat, bp);
259 }
260 g_destroy_bio(bp);
261 bp2->bio_inbed++;
262 if (bp2->bio_children == bp2->bio_inbed) {
263 bp2->bio_resid = bp2->bio_bcount - bp2->bio_completed;
264 g_io_deliver(bp2, bp2->bio_error);
265 }
266 mtx_unlock(&g_disk_done_mtx);
267}
268
269static int
270g_disk_ioctl(struct g_provider *pp, u_long cmd, void * data, int fflag, struct thread *td)
271{
272 struct g_geom *gp;
273 struct disk *dp;
274 struct g_disk_softc *sc;
275 int error;
276
277 gp = pp->geom;
278 sc = gp->softc;
279 dp = sc->dp;
280
281 if (dp->d_ioctl == NULL)
282 return (ENOIOCTL);
283 g_disk_lock_giant(dp);
284 error = dp->d_ioctl(dp, cmd, data, fflag, td);
285 g_disk_unlock_giant(dp);
286 return (error);
287}
288
289static void
290g_disk_start(struct bio *bp)
291{
292 struct bio *bp2, *bp3;
293 struct disk *dp;
294 struct g_disk_softc *sc;
295 int error;
296 off_t off;
297
298 sc = bp->bio_to->geom->softc;
299 if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
300 g_io_deliver(bp, ENXIO);
301 return;
302 }
303 error = EJUSTRETURN;
304 switch(bp->bio_cmd) {
305 case BIO_DELETE:
306 if (!(dp->d_flags & DISKFLAG_CANDELETE)) {
--- 184 unchanged lines hidden (view full) ---
491 struct g_disk_softc *sc;
492 char tmpstr[80];
493
494 if (flag == EV_CANCEL)
495 return;
496 g_topology_assert();
497 dp = arg;
498 sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
499 sc->dp = dp;
500 gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit);
501 gp->softc = sc;
502 pp = g_new_providerf(gp, "%s", gp->name);
503 pp->mediasize = dp->d_mediasize;
504 pp->sectorsize = dp->d_sectorsize;
505 pp->stripeoffset = dp->d_stripeoffset;
506 pp->stripesize = dp->d_stripesize;
--- 27 unchanged lines hidden (view full) ---
534 * be getting any more accesses from GEOM.
535 */
536static void
537g_disk_providergone(struct g_provider *pp)
538{
539 struct disk *dp;
540 struct g_disk_softc *sc;
541
542 sc = (struct g_disk_softc *)pp->geom->softc;
543
544 /*
545 * If the softc is already NULL, then we've probably been through
546 * g_disk_destroy already; there is nothing for us to do anyway.
547 */
548 if (sc == NULL)
549 return;
550
551 dp = sc->dp;
552
553 if (dp->d_gone != NULL)
554 dp->d_gone(dp);
555}
556
557static void
558g_disk_destroy(void *ptr, int flag)
559{
560 struct disk *dp;
561 struct g_geom *gp;
562 struct g_disk_softc *sc;
563
564 g_topology_assert();
565 dp = ptr;
566 gp = dp->d_geom;
567 if (gp != NULL) {
568 sc = gp->softc;
569 if (sc->sysctl_tree != NULL) {
570 sysctl_ctx_free(&sc->sysctl_ctx);
571 sc->sysctl_tree = NULL;
572 }
573 if (sc->led[0] != 0) {
574 led_set(sc->led, "0");
575 sc->led[0] = 0;
576 }
577 g_free(sc);
578 gp->softc = NULL;
579 g_wither_geom(gp, ENXIO);
580 }
581 g_free(dp);
582}
583
584/*
585 * We only allow printable characters in disk ident,
586 * the rest is converted to 'x<HH>'.
--- 163 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
--- 20 unchanged lines hidden (view full) ---
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
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: head/sys/geom/geom_disk.c 248516 2013-03-19 14:49:15Z kib $");
38
39#include "opt_geom.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/sysctl.h>
45#include <sys/bio.h>
--- 9 unchanged lines hidden (view full) ---
55#include <sys/mutex.h>
56#include <geom/geom.h>
57#include <geom/geom_disk.h>
58#include <geom/geom_int.h>
59
60#include <dev/led/led.h>
61
62struct g_disk_softc {
63 struct disk *dp;
64 struct sysctl_ctx_list sysctl_ctx;
65 struct sysctl_oid *sysctl_tree;
66 char led[64];
67 uint32_t state;
68};
69
70static struct mtx g_disk_done_mtx;
71
72static g_access_t g_disk_access;
73static g_init_t g_disk_init;
74static g_fini_t g_disk_fini;
75static g_start_t g_disk_start;
76static g_ioctl_t g_disk_ioctl;
77static g_dumpconf_t g_disk_dumpconf;
78static g_provgone_t g_disk_providergone;
79
80static struct g_class g_disk_class = {
81 .name = "DISK",
82 .version = G_VERSION,
83 .init = g_disk_init,
84 .fini = g_disk_fini,
85 .start = g_disk_start,
86 .access = g_disk_access,
87 .ioctl = g_disk_ioctl,
88 .providergone = g_disk_providergone,
89 .dumpconf = g_disk_dumpconf,
90};
91
92SYSCTL_DECL(_kern_geom);
93static SYSCTL_NODE(_kern_geom, OID_AUTO, disk, CTLFLAG_RW, 0,
94 "GEOM_DISK stuff");
95
96static void
97g_disk_init(struct g_class *mp __unused)
98{
99
100 mtx_init(&g_disk_done_mtx, "g_disk_done", NULL, MTX_DEF);
101}
102
103static void
104g_disk_fini(struct g_class *mp __unused)
105{
106
107 mtx_destroy(&g_disk_done_mtx);
108}
109
110DECLARE_GEOM_CLASS(g_disk_class, g_disk);
111
112static void __inline
113g_disk_lock_giant(struct disk *dp)
114{
115
116 if (dp->d_flags & DISKFLAG_NEEDSGIANT)
117 mtx_lock(&Giant);
--- 12 unchanged lines hidden (view full) ---
130{
131 struct disk *dp;
132 struct g_disk_softc *sc;
133 int error;
134
135 g_trace(G_T_ACCESS, "g_disk_access(%s, %d, %d, %d)",
136 pp->name, r, w, e);
137 g_topology_assert();
138 sc = pp->geom->softc;
139 if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
140 /*
141 * Allow decreasing access count even if disk is not
142 * avaliable anymore.
143 */
144 if (r <= 0 && w <= 0 && e <= 0)
145 return (0);
146 return (ENXIO);
--- 88 unchanged lines hidden (view full) ---
235 }
236 g_io_deliver(bp, 0);
237}
238
239static void
240g_disk_done(struct bio *bp)
241{
242 struct bio *bp2;
243 struct disk *dp;
244 struct g_disk_softc *sc;
245
246 /* See "notes" for why we need a mutex here */
247 /* XXX: will witness accept a mix of Giant/unGiant drivers here ? */
248 mtx_lock(&g_disk_done_mtx);
249 bp->bio_completed = bp->bio_length - bp->bio_resid;
250
251 bp2 = bp->bio_parent;
252 if (bp2->bio_error == 0)
253 bp2->bio_error = bp->bio_error;
254 bp2->bio_completed += bp->bio_completed;
255 if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) != 0 &&
256 (sc = bp2->bio_to->geom->softc) != NULL &&
257 (dp = sc->dp) != NULL) {
258 devstat_end_transaction_bio(dp->d_devstat, bp);
259 }
260 g_destroy_bio(bp);
261 bp2->bio_inbed++;
262 if (bp2->bio_children == bp2->bio_inbed) {
263 bp2->bio_resid = bp2->bio_bcount - bp2->bio_completed;
264 g_io_deliver(bp2, bp2->bio_error);
265 }
266 mtx_unlock(&g_disk_done_mtx);
267}
268
269static int
270g_disk_ioctl(struct g_provider *pp, u_long cmd, void * data, int fflag, struct thread *td)
271{
272 struct g_geom *gp;
273 struct disk *dp;
274 struct g_disk_softc *sc;
275 int error;
276
277 gp = pp->geom;
278 sc = gp->softc;
279 dp = sc->dp;
280
281 if (dp->d_ioctl == NULL)
282 return (ENOIOCTL);
283 g_disk_lock_giant(dp);
284 error = dp->d_ioctl(dp, cmd, data, fflag, td);
285 g_disk_unlock_giant(dp);
286 return (error);
287}
288
289static void
290g_disk_start(struct bio *bp)
291{
292 struct bio *bp2, *bp3;
293 struct disk *dp;
294 struct g_disk_softc *sc;
295 int error;
296 off_t off;
297
298 sc = bp->bio_to->geom->softc;
299 if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
300 g_io_deliver(bp, ENXIO);
301 return;
302 }
303 error = EJUSTRETURN;
304 switch(bp->bio_cmd) {
305 case BIO_DELETE:
306 if (!(dp->d_flags & DISKFLAG_CANDELETE)) {
--- 184 unchanged lines hidden (view full) ---
491 struct g_disk_softc *sc;
492 char tmpstr[80];
493
494 if (flag == EV_CANCEL)
495 return;
496 g_topology_assert();
497 dp = arg;
498 sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
499 sc->dp = dp;
500 gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit);
501 gp->softc = sc;
502 pp = g_new_providerf(gp, "%s", gp->name);
503 pp->mediasize = dp->d_mediasize;
504 pp->sectorsize = dp->d_sectorsize;
505 pp->stripeoffset = dp->d_stripeoffset;
506 pp->stripesize = dp->d_stripesize;
--- 27 unchanged lines hidden (view full) ---
534 * be getting any more accesses from GEOM.
535 */
536static void
537g_disk_providergone(struct g_provider *pp)
538{
539 struct disk *dp;
540 struct g_disk_softc *sc;
541
542 sc = (struct g_disk_softc *)pp->geom->softc;
543
544 /*
545 * If the softc is already NULL, then we've probably been through
546 * g_disk_destroy already; there is nothing for us to do anyway.
547 */
548 if (sc == NULL)
549 return;
550
551 dp = sc->dp;
552
553 if (dp->d_gone != NULL)
554 dp->d_gone(dp);
555}
556
557static void
558g_disk_destroy(void *ptr, int flag)
559{
560 struct disk *dp;
561 struct g_geom *gp;
562 struct g_disk_softc *sc;
563
564 g_topology_assert();
565 dp = ptr;
566 gp = dp->d_geom;
567 if (gp != NULL) {
568 sc = gp->softc;
569 if (sc->sysctl_tree != NULL) {
570 sysctl_ctx_free(&sc->sysctl_ctx);
571 sc->sysctl_tree = NULL;
572 }
573 if (sc->led[0] != 0) {
574 led_set(sc->led, "0");
575 sc->led[0] = 0;
576 }
577 g_free(sc);
578 gp->softc = NULL;
579 g_wither_geom(gp, ENXIO);
580 }
581 g_free(dp);
582}
583
584/*
585 * We only allow printable characters in disk ident,
586 * the rest is converted to 'x<HH>'.
--- 163 unchanged lines hidden ---