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 248694 2013-03-25 05:45:24Z mav $");
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 mtx done_mtx;
64 struct disk *dp;
65 struct sysctl_ctx_list sysctl_ctx;
66 struct sysctl_oid *sysctl_tree;
67 char led[64];
68 uint32_t state;
69};
70
71static g_access_t g_disk_access;
72static g_start_t g_disk_start;
73static g_ioctl_t g_disk_ioctl;
74static g_dumpconf_t g_disk_dumpconf;
75static g_provgone_t g_disk_providergone;
76
77static struct g_class g_disk_class = {
78 .name = "DISK",
79 .version = G_VERSION,
80 .start = g_disk_start,
81 .access = g_disk_access,
82 .ioctl = g_disk_ioctl,
83 .providergone = g_disk_providergone,
84 .dumpconf = g_disk_dumpconf,
85};
86
87SYSCTL_DECL(_kern_geom);
88static SYSCTL_NODE(_kern_geom, OID_AUTO, disk, CTLFLAG_RW, 0,
89 "GEOM_DISK stuff");
90
91DECLARE_GEOM_CLASS(g_disk_class, g_disk);
92
93static void __inline
94g_disk_lock_giant(struct disk *dp)
95{
96
97 if (dp->d_flags & DISKFLAG_NEEDSGIANT)
98 mtx_lock(&Giant);
--- 12 unchanged lines hidden (view full) ---
111{
112 struct disk *dp;
113 struct g_disk_softc *sc;
114 int error;
115
116 g_trace(G_T_ACCESS, "g_disk_access(%s, %d, %d, %d)",
117 pp->name, r, w, e);
118 g_topology_assert();
119 sc = pp->private;
120 if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
121 /*
122 * Allow decreasing access count even if disk is not
123 * avaliable anymore.
124 */
125 if (r <= 0 && w <= 0 && e <= 0)
126 return (0);
127 return (ENXIO);
--- 88 unchanged lines hidden (view full) ---
216 }
217 g_io_deliver(bp, 0);
218}
219
220static void
221g_disk_done(struct bio *bp)
222{
223 struct bio *bp2;
224 struct g_disk_softc *sc;
225
226 /* See "notes" for why we need a mutex here */
227 /* XXX: will witness accept a mix of Giant/unGiant drivers here ? */
228 bp2 = bp->bio_parent;
229 sc = bp2->bio_to->private;
230 bp->bio_completed = bp->bio_length - bp->bio_resid;
231 mtx_lock(&sc->done_mtx);
232 if (bp2->bio_error == 0)
233 bp2->bio_error = bp->bio_error;
234 bp2->bio_completed += bp->bio_completed;
235 if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) != 0)
236 devstat_end_transaction_bio(sc->dp->d_devstat, bp);
237 g_destroy_bio(bp);
238 bp2->bio_inbed++;
239 if (bp2->bio_children == bp2->bio_inbed) {
240 bp2->bio_resid = bp2->bio_bcount - bp2->bio_completed;
241 g_io_deliver(bp2, bp2->bio_error);
242 }
243 mtx_unlock(&sc->done_mtx);
244}
245
246static int
247g_disk_ioctl(struct g_provider *pp, u_long cmd, void * data, int fflag, struct thread *td)
248{
249 struct disk *dp;
250 struct g_disk_softc *sc;
251 int error;
252
253 sc = pp->private;
254 dp = sc->dp;
255
256 if (dp->d_ioctl == NULL)
257 return (ENOIOCTL);
258 g_disk_lock_giant(dp);
259 error = dp->d_ioctl(dp, cmd, data, fflag, td);
260 g_disk_unlock_giant(dp);
261 return (error);
262}
263
264static void
265g_disk_start(struct bio *bp)
266{
267 struct bio *bp2, *bp3;
268 struct disk *dp;
269 struct g_disk_softc *sc;
270 int error;
271 off_t off;
272
273 sc = bp->bio_to->private;
274 if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
275 g_io_deliver(bp, ENXIO);
276 return;
277 }
278 error = EJUSTRETURN;
279 switch(bp->bio_cmd) {
280 case BIO_DELETE:
281 if (!(dp->d_flags & DISKFLAG_CANDELETE)) {
--- 184 unchanged lines hidden (view full) ---
466 struct g_disk_softc *sc;
467 char tmpstr[80];
468
469 if (flag == EV_CANCEL)
470 return;
471 g_topology_assert();
472 dp = arg;
473 sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
474 mtx_init(&sc->done_mtx, "g_disk_done", NULL, MTX_DEF);
475 sc->dp = dp;
476 gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit);
477 gp->softc = sc;
478 pp = g_new_providerf(gp, "%s", gp->name);
479 pp->mediasize = dp->d_mediasize;
480 pp->sectorsize = dp->d_sectorsize;
481 pp->stripeoffset = dp->d_stripeoffset;
482 pp->stripesize = dp->d_stripesize;
--- 27 unchanged lines hidden (view full) ---
510 * be getting any more accesses from GEOM.
511 */
512static void
513g_disk_providergone(struct g_provider *pp)
514{
515 struct disk *dp;
516 struct g_disk_softc *sc;
517
518 sc = (struct g_disk_softc *)pp->private;
519 dp = sc->dp;
520 if (dp != NULL && dp->d_gone != NULL)
521 dp->d_gone(dp);
522 if (sc->sysctl_tree != NULL) {
523 sysctl_ctx_free(&sc->sysctl_ctx);
524 sc->sysctl_tree = NULL;
525 }
526 if (sc->led[0] != 0) {
527 led_set(sc->led, "0");
528 sc->led[0] = 0;
529 }
530 pp->private = NULL;
531 pp->geom->softc = NULL;
532 mtx_destroy(&sc->done_mtx);
533 g_free(sc);
534}
535
536static void
537g_disk_destroy(void *ptr, int flag)
538{
539 struct disk *dp;
540 struct g_geom *gp;
541 struct g_disk_softc *sc;
542
543 g_topology_assert();
544 dp = ptr;
545 gp = dp->d_geom;
546 if (gp != NULL) {
547 sc = gp->softc;
548 if (sc != NULL)
549 sc->dp = NULL;
550 dp->d_geom = NULL;
551 g_wither_geom(gp, ENXIO);
552 }
553 g_free(dp);
554}
555
556/*
557 * We only allow printable characters in disk ident,
558 * 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 248694 2013-03-25 05:45:24Z mav $");
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 mtx done_mtx;
64 struct disk *dp;
65 struct sysctl_ctx_list sysctl_ctx;
66 struct sysctl_oid *sysctl_tree;
67 char led[64];
68 uint32_t state;
69};
70
71static g_access_t g_disk_access;
72static g_start_t g_disk_start;
73static g_ioctl_t g_disk_ioctl;
74static g_dumpconf_t g_disk_dumpconf;
75static g_provgone_t g_disk_providergone;
76
77static struct g_class g_disk_class = {
78 .name = "DISK",
79 .version = G_VERSION,
80 .start = g_disk_start,
81 .access = g_disk_access,
82 .ioctl = g_disk_ioctl,
83 .providergone = g_disk_providergone,
84 .dumpconf = g_disk_dumpconf,
85};
86
87SYSCTL_DECL(_kern_geom);
88static SYSCTL_NODE(_kern_geom, OID_AUTO, disk, CTLFLAG_RW, 0,
89 "GEOM_DISK stuff");
90
91DECLARE_GEOM_CLASS(g_disk_class, g_disk);
92
93static void __inline
94g_disk_lock_giant(struct disk *dp)
95{
96
97 if (dp->d_flags & DISKFLAG_NEEDSGIANT)
98 mtx_lock(&Giant);
--- 12 unchanged lines hidden (view full) ---
111{
112 struct disk *dp;
113 struct g_disk_softc *sc;
114 int error;
115
116 g_trace(G_T_ACCESS, "g_disk_access(%s, %d, %d, %d)",
117 pp->name, r, w, e);
118 g_topology_assert();
119 sc = pp->private;
120 if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
121 /*
122 * Allow decreasing access count even if disk is not
123 * avaliable anymore.
124 */
125 if (r <= 0 && w <= 0 && e <= 0)
126 return (0);
127 return (ENXIO);
--- 88 unchanged lines hidden (view full) ---
216 }
217 g_io_deliver(bp, 0);
218}
219
220static void
221g_disk_done(struct bio *bp)
222{
223 struct bio *bp2;
224 struct g_disk_softc *sc;
225
226 /* See "notes" for why we need a mutex here */
227 /* XXX: will witness accept a mix of Giant/unGiant drivers here ? */
228 bp2 = bp->bio_parent;
229 sc = bp2->bio_to->private;
230 bp->bio_completed = bp->bio_length - bp->bio_resid;
231 mtx_lock(&sc->done_mtx);
232 if (bp2->bio_error == 0)
233 bp2->bio_error = bp->bio_error;
234 bp2->bio_completed += bp->bio_completed;
235 if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) != 0)
236 devstat_end_transaction_bio(sc->dp->d_devstat, bp);
237 g_destroy_bio(bp);
238 bp2->bio_inbed++;
239 if (bp2->bio_children == bp2->bio_inbed) {
240 bp2->bio_resid = bp2->bio_bcount - bp2->bio_completed;
241 g_io_deliver(bp2, bp2->bio_error);
242 }
243 mtx_unlock(&sc->done_mtx);
244}
245
246static int
247g_disk_ioctl(struct g_provider *pp, u_long cmd, void * data, int fflag, struct thread *td)
248{
249 struct disk *dp;
250 struct g_disk_softc *sc;
251 int error;
252
253 sc = pp->private;
254 dp = sc->dp;
255
256 if (dp->d_ioctl == NULL)
257 return (ENOIOCTL);
258 g_disk_lock_giant(dp);
259 error = dp->d_ioctl(dp, cmd, data, fflag, td);
260 g_disk_unlock_giant(dp);
261 return (error);
262}
263
264static void
265g_disk_start(struct bio *bp)
266{
267 struct bio *bp2, *bp3;
268 struct disk *dp;
269 struct g_disk_softc *sc;
270 int error;
271 off_t off;
272
273 sc = bp->bio_to->private;
274 if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
275 g_io_deliver(bp, ENXIO);
276 return;
277 }
278 error = EJUSTRETURN;
279 switch(bp->bio_cmd) {
280 case BIO_DELETE:
281 if (!(dp->d_flags & DISKFLAG_CANDELETE)) {
--- 184 unchanged lines hidden (view full) ---
466 struct g_disk_softc *sc;
467 char tmpstr[80];
468
469 if (flag == EV_CANCEL)
470 return;
471 g_topology_assert();
472 dp = arg;
473 sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
474 mtx_init(&sc->done_mtx, "g_disk_done", NULL, MTX_DEF);
475 sc->dp = dp;
476 gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit);
477 gp->softc = sc;
478 pp = g_new_providerf(gp, "%s", gp->name);
479 pp->mediasize = dp->d_mediasize;
480 pp->sectorsize = dp->d_sectorsize;
481 pp->stripeoffset = dp->d_stripeoffset;
482 pp->stripesize = dp->d_stripesize;
--- 27 unchanged lines hidden (view full) ---
510 * be getting any more accesses from GEOM.
511 */
512static void
513g_disk_providergone(struct g_provider *pp)
514{
515 struct disk *dp;
516 struct g_disk_softc *sc;
517
518 sc = (struct g_disk_softc *)pp->private;
519 dp = sc->dp;
520 if (dp != NULL && dp->d_gone != NULL)
521 dp->d_gone(dp);
522 if (sc->sysctl_tree != NULL) {
523 sysctl_ctx_free(&sc->sysctl_ctx);
524 sc->sysctl_tree = NULL;
525 }
526 if (sc->led[0] != 0) {
527 led_set(sc->led, "0");
528 sc->led[0] = 0;
529 }
530 pp->private = NULL;
531 pp->geom->softc = NULL;
532 mtx_destroy(&sc->done_mtx);
533 g_free(sc);
534}
535
536static void
537g_disk_destroy(void *ptr, int flag)
538{
539 struct disk *dp;
540 struct g_geom *gp;
541 struct g_disk_softc *sc;
542
543 g_topology_assert();
544 dp = ptr;
545 gp = dp->d_geom;
546 if (gp != NULL) {
547 sc = gp->softc;
548 if (sc != NULL)
549 sc->dp = NULL;
550 dp->d_geom = NULL;
551 g_wither_geom(gp, ENXIO);
552 }
553 g_free(dp);
554}
555
556/*
557 * We only allow printable characters in disk ident,
558 * the rest is converted to 'x<HH>'.
--- 163 unchanged lines hidden ---