1 /*- 2 * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * Copyright (c) 2009-2010 The FreeBSD Foundation 4 * All rights reserved. 5 * 6 * Portions of this software were developed by Pawel Jakub Dawidek 7 * under sponsorship from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/bio.h> 37 #include <sys/conf.h> 38 #include <sys/kernel.h> 39 #include <sys/kthread.h> 40 #include <sys/fcntl.h> 41 #include <sys/linker.h> 42 #include <sys/lock.h> 43 #include <sys/malloc.h> 44 #include <sys/mutex.h> 45 #include <sys/proc.h> 46 #include <sys/limits.h> 47 #include <sys/queue.h> 48 #include <sys/sbuf.h> 49 #include <sys/sysctl.h> 50 #include <sys/signalvar.h> 51 #include <sys/time.h> 52 #include <machine/atomic.h> 53 54 #include <geom/geom.h> 55 #include <geom/gate/g_gate.h> 56 57 FEATURE(geom_gate, "GEOM Gate module"); 58 59 static MALLOC_DEFINE(M_GATE, "gg_data", "GEOM Gate Data"); 60 61 SYSCTL_DECL(_kern_geom); 62 static SYSCTL_NODE(_kern_geom, OID_AUTO, gate, CTLFLAG_RW, 0, 63 "GEOM_GATE configuration"); 64 static int g_gate_debug = 0; 65 SYSCTL_INT(_kern_geom_gate, OID_AUTO, debug, CTLFLAG_RWTUN, &g_gate_debug, 0, 66 "Debug level"); 67 static u_int g_gate_maxunits = 256; 68 SYSCTL_UINT(_kern_geom_gate, OID_AUTO, maxunits, CTLFLAG_RDTUN, 69 &g_gate_maxunits, 0, "Maximum number of ggate devices"); 70 71 struct g_class g_gate_class = { 72 .name = G_GATE_CLASS_NAME, 73 .version = G_VERSION, 74 }; 75 76 static struct cdev *status_dev; 77 static d_ioctl_t g_gate_ioctl; 78 static struct cdevsw g_gate_cdevsw = { 79 .d_version = D_VERSION, 80 .d_ioctl = g_gate_ioctl, 81 .d_name = G_GATE_CTL_NAME 82 }; 83 84 85 static struct g_gate_softc **g_gate_units; 86 static u_int g_gate_nunits; 87 static struct mtx g_gate_units_lock; 88 89 static int 90 g_gate_destroy(struct g_gate_softc *sc, boolean_t force) 91 { 92 struct bio_queue_head queue; 93 struct g_provider *pp; 94 struct g_consumer *cp; 95 struct g_geom *gp; 96 struct bio *bp; 97 98 g_topology_assert(); 99 mtx_assert(&g_gate_units_lock, MA_OWNED); 100 pp = sc->sc_provider; 101 if (!force && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) { 102 mtx_unlock(&g_gate_units_lock); 103 return (EBUSY); 104 } 105 mtx_unlock(&g_gate_units_lock); 106 mtx_lock(&sc->sc_queue_mtx); 107 if ((sc->sc_flags & G_GATE_FLAG_DESTROY) == 0) 108 sc->sc_flags |= G_GATE_FLAG_DESTROY; 109 wakeup(sc); 110 mtx_unlock(&sc->sc_queue_mtx); 111 gp = pp->geom; 112 pp->flags |= G_PF_WITHER; 113 g_orphan_provider(pp, ENXIO); 114 callout_drain(&sc->sc_callout); 115 bioq_init(&queue); 116 mtx_lock(&sc->sc_queue_mtx); 117 while ((bp = bioq_takefirst(&sc->sc_inqueue)) != NULL) { 118 sc->sc_queue_count--; 119 bioq_insert_tail(&queue, bp); 120 } 121 while ((bp = bioq_takefirst(&sc->sc_outqueue)) != NULL) { 122 sc->sc_queue_count--; 123 bioq_insert_tail(&queue, bp); 124 } 125 mtx_unlock(&sc->sc_queue_mtx); 126 g_topology_unlock(); 127 while ((bp = bioq_takefirst(&queue)) != NULL) { 128 G_GATE_LOGREQ(1, bp, "Request canceled."); 129 g_io_deliver(bp, ENXIO); 130 } 131 mtx_lock(&g_gate_units_lock); 132 /* One reference is ours. */ 133 sc->sc_ref--; 134 while (sc->sc_ref > 0) 135 msleep(&sc->sc_ref, &g_gate_units_lock, 0, "gg:destroy", 0); 136 g_gate_units[sc->sc_unit] = NULL; 137 KASSERT(g_gate_nunits > 0, ("negative g_gate_nunits?")); 138 g_gate_nunits--; 139 mtx_unlock(&g_gate_units_lock); 140 mtx_destroy(&sc->sc_queue_mtx); 141 g_topology_lock(); 142 if ((cp = sc->sc_readcons) != NULL) { 143 sc->sc_readcons = NULL; 144 (void)g_access(cp, -1, 0, 0); 145 g_detach(cp); 146 g_destroy_consumer(cp); 147 } 148 G_GATE_DEBUG(1, "Device %s destroyed.", gp->name); 149 gp->softc = NULL; 150 g_wither_geom(gp, ENXIO); 151 sc->sc_provider = NULL; 152 free(sc, M_GATE); 153 return (0); 154 } 155 156 static int 157 g_gate_access(struct g_provider *pp, int dr, int dw, int de) 158 { 159 struct g_gate_softc *sc; 160 161 if (dr <= 0 && dw <= 0 && de <= 0) 162 return (0); 163 sc = pp->geom->softc; 164 if (sc == NULL || (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0) 165 return (ENXIO); 166 /* XXX: Hack to allow read-only mounts. */ 167 #if 0 168 if ((sc->sc_flags & G_GATE_FLAG_READONLY) != 0 && dw > 0) 169 return (EPERM); 170 #endif 171 if ((sc->sc_flags & G_GATE_FLAG_WRITEONLY) != 0 && dr > 0) 172 return (EPERM); 173 return (0); 174 } 175 176 static void 177 g_gate_queue_io(struct bio *bp) 178 { 179 struct g_gate_softc *sc; 180 181 sc = bp->bio_to->geom->softc; 182 if (sc == NULL || (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0) { 183 g_io_deliver(bp, ENXIO); 184 return; 185 } 186 187 mtx_lock(&sc->sc_queue_mtx); 188 189 if (sc->sc_queue_size > 0 && sc->sc_queue_count > sc->sc_queue_size) { 190 mtx_unlock(&sc->sc_queue_mtx); 191 G_GATE_LOGREQ(1, bp, "Queue full, request canceled."); 192 g_io_deliver(bp, ENOMEM); 193 return; 194 } 195 196 bp->bio_driver1 = (void *)sc->sc_seq; 197 sc->sc_seq++; 198 sc->sc_queue_count++; 199 200 bioq_insert_tail(&sc->sc_inqueue, bp); 201 wakeup(sc); 202 203 mtx_unlock(&sc->sc_queue_mtx); 204 } 205 206 static void 207 g_gate_done(struct bio *cbp) 208 { 209 struct bio *pbp; 210 211 pbp = cbp->bio_parent; 212 if (cbp->bio_error == 0) { 213 pbp->bio_completed = cbp->bio_completed; 214 g_destroy_bio(cbp); 215 pbp->bio_inbed++; 216 g_io_deliver(pbp, 0); 217 } else { 218 /* If direct read failed, pass it through userland daemon. */ 219 g_destroy_bio(cbp); 220 pbp->bio_children--; 221 g_gate_queue_io(pbp); 222 } 223 } 224 225 static void 226 g_gate_start(struct bio *pbp) 227 { 228 struct g_gate_softc *sc; 229 230 sc = pbp->bio_to->geom->softc; 231 if (sc == NULL || (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0) { 232 g_io_deliver(pbp, ENXIO); 233 return; 234 } 235 G_GATE_LOGREQ(2, pbp, "Request received."); 236 switch (pbp->bio_cmd) { 237 case BIO_READ: 238 if (sc->sc_readcons != NULL) { 239 struct bio *cbp; 240 241 cbp = g_clone_bio(pbp); 242 if (cbp == NULL) { 243 g_io_deliver(pbp, ENOMEM); 244 return; 245 } 246 cbp->bio_done = g_gate_done; 247 cbp->bio_offset = pbp->bio_offset + sc->sc_readoffset; 248 cbp->bio_to = sc->sc_readcons->provider; 249 g_io_request(cbp, sc->sc_readcons); 250 return; 251 } 252 break; 253 case BIO_DELETE: 254 case BIO_WRITE: 255 case BIO_FLUSH: 256 /* XXX: Hack to allow read-only mounts. */ 257 if ((sc->sc_flags & G_GATE_FLAG_READONLY) != 0) { 258 g_io_deliver(pbp, EPERM); 259 return; 260 } 261 break; 262 case BIO_GETATTR: 263 default: 264 G_GATE_LOGREQ(2, pbp, "Ignoring request."); 265 g_io_deliver(pbp, EOPNOTSUPP); 266 return; 267 } 268 269 g_gate_queue_io(pbp); 270 } 271 272 static struct g_gate_softc * 273 g_gate_hold(int unit, const char *name) 274 { 275 struct g_gate_softc *sc = NULL; 276 277 mtx_lock(&g_gate_units_lock); 278 if (unit >= 0 && unit < g_gate_maxunits) 279 sc = g_gate_units[unit]; 280 else if (unit == G_GATE_NAME_GIVEN) { 281 KASSERT(name != NULL, ("name is NULL")); 282 for (unit = 0; unit < g_gate_maxunits; unit++) { 283 if (g_gate_units[unit] == NULL) 284 continue; 285 if (strcmp(name, 286 g_gate_units[unit]->sc_provider->name) != 0) { 287 continue; 288 } 289 sc = g_gate_units[unit]; 290 break; 291 } 292 } 293 if (sc != NULL) 294 sc->sc_ref++; 295 mtx_unlock(&g_gate_units_lock); 296 return (sc); 297 } 298 299 static void 300 g_gate_release(struct g_gate_softc *sc) 301 { 302 303 g_topology_assert_not(); 304 mtx_lock(&g_gate_units_lock); 305 sc->sc_ref--; 306 KASSERT(sc->sc_ref >= 0, ("Negative sc_ref for %s.", sc->sc_name)); 307 if (sc->sc_ref == 0 && (sc->sc_flags & G_GATE_FLAG_DESTROY) != 0) 308 wakeup(&sc->sc_ref); 309 mtx_unlock(&g_gate_units_lock); 310 } 311 312 static int 313 g_gate_getunit(int unit, int *errorp) 314 { 315 316 mtx_assert(&g_gate_units_lock, MA_OWNED); 317 if (unit >= 0) { 318 if (unit >= g_gate_maxunits) 319 *errorp = EINVAL; 320 else if (g_gate_units[unit] == NULL) 321 return (unit); 322 else 323 *errorp = EEXIST; 324 } else { 325 for (unit = 0; unit < g_gate_maxunits; unit++) { 326 if (g_gate_units[unit] == NULL) 327 return (unit); 328 } 329 *errorp = ENFILE; 330 } 331 return (-1); 332 } 333 334 static void 335 g_gate_guard(void *arg) 336 { 337 struct bio_queue_head queue; 338 struct g_gate_softc *sc; 339 struct bintime curtime; 340 struct bio *bp, *bp2; 341 342 sc = arg; 343 binuptime(&curtime); 344 g_gate_hold(sc->sc_unit, NULL); 345 bioq_init(&queue); 346 mtx_lock(&sc->sc_queue_mtx); 347 TAILQ_FOREACH_SAFE(bp, &sc->sc_inqueue.queue, bio_queue, bp2) { 348 if (curtime.sec - bp->bio_t0.sec < 5) 349 continue; 350 bioq_remove(&sc->sc_inqueue, bp); 351 sc->sc_queue_count--; 352 bioq_insert_tail(&queue, bp); 353 } 354 TAILQ_FOREACH_SAFE(bp, &sc->sc_outqueue.queue, bio_queue, bp2) { 355 if (curtime.sec - bp->bio_t0.sec < 5) 356 continue; 357 bioq_remove(&sc->sc_outqueue, bp); 358 sc->sc_queue_count--; 359 bioq_insert_tail(&queue, bp); 360 } 361 mtx_unlock(&sc->sc_queue_mtx); 362 while ((bp = bioq_takefirst(&queue)) != NULL) { 363 G_GATE_LOGREQ(1, bp, "Request timeout."); 364 g_io_deliver(bp, EIO); 365 } 366 if ((sc->sc_flags & G_GATE_FLAG_DESTROY) == 0) { 367 callout_reset(&sc->sc_callout, sc->sc_timeout * hz, 368 g_gate_guard, sc); 369 } 370 g_gate_release(sc); 371 } 372 373 static void 374 g_gate_orphan(struct g_consumer *cp) 375 { 376 struct g_gate_softc *sc; 377 struct g_geom *gp; 378 379 g_topology_assert(); 380 gp = cp->geom; 381 sc = gp->softc; 382 if (sc == NULL) 383 return; 384 KASSERT(cp == sc->sc_readcons, ("cp=%p sc_readcons=%p", cp, 385 sc->sc_readcons)); 386 sc->sc_readcons = NULL; 387 G_GATE_DEBUG(1, "Destroying read consumer on provider %s orphan.", 388 cp->provider->name); 389 (void)g_access(cp, -1, 0, 0); 390 g_detach(cp); 391 g_destroy_consumer(cp); 392 } 393 394 static void 395 g_gate_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, 396 struct g_consumer *cp, struct g_provider *pp) 397 { 398 struct g_gate_softc *sc; 399 400 sc = gp->softc; 401 if (sc == NULL || pp != NULL || cp != NULL) 402 return; 403 sc = g_gate_hold(sc->sc_unit, NULL); 404 if (sc == NULL) 405 return; 406 if ((sc->sc_flags & G_GATE_FLAG_READONLY) != 0) { 407 sbuf_printf(sb, "%s<access>%s</access>\n", indent, "read-only"); 408 } else if ((sc->sc_flags & G_GATE_FLAG_WRITEONLY) != 0) { 409 sbuf_printf(sb, "%s<access>%s</access>\n", indent, 410 "write-only"); 411 } else { 412 sbuf_printf(sb, "%s<access>%s</access>\n", indent, 413 "read-write"); 414 } 415 if (sc->sc_readcons != NULL) { 416 sbuf_printf(sb, "%s<read_offset>%jd</read_offset>\n", 417 indent, (intmax_t)sc->sc_readoffset); 418 sbuf_printf(sb, "%s<read_provider>%s</read_provider>\n", 419 indent, sc->sc_readcons->provider->name); 420 } 421 sbuf_printf(sb, "%s<timeout>%u</timeout>\n", indent, sc->sc_timeout); 422 sbuf_printf(sb, "%s<info>%s</info>\n", indent, sc->sc_info); 423 sbuf_printf(sb, "%s<queue_count>%u</queue_count>\n", indent, 424 sc->sc_queue_count); 425 sbuf_printf(sb, "%s<queue_size>%u</queue_size>\n", indent, 426 sc->sc_queue_size); 427 sbuf_printf(sb, "%s<ref>%u</ref>\n", indent, sc->sc_ref); 428 sbuf_printf(sb, "%s<unit>%d</unit>\n", indent, sc->sc_unit); 429 g_topology_unlock(); 430 g_gate_release(sc); 431 g_topology_lock(); 432 } 433 434 static int 435 g_gate_create(struct g_gate_ctl_create *ggio) 436 { 437 struct g_gate_softc *sc; 438 struct g_geom *gp; 439 struct g_provider *pp, *ropp; 440 struct g_consumer *cp; 441 char name[NAME_MAX]; 442 int error = 0, unit; 443 444 if (ggio->gctl_mediasize <= 0) { 445 G_GATE_DEBUG(1, "Invalid media size."); 446 return (EINVAL); 447 } 448 if (ggio->gctl_sectorsize <= 0) { 449 G_GATE_DEBUG(1, "Invalid sector size."); 450 return (EINVAL); 451 } 452 if (!powerof2(ggio->gctl_sectorsize)) { 453 G_GATE_DEBUG(1, "Invalid sector size."); 454 return (EINVAL); 455 } 456 if ((ggio->gctl_mediasize % ggio->gctl_sectorsize) != 0) { 457 G_GATE_DEBUG(1, "Invalid media size."); 458 return (EINVAL); 459 } 460 if ((ggio->gctl_flags & G_GATE_FLAG_READONLY) != 0 && 461 (ggio->gctl_flags & G_GATE_FLAG_WRITEONLY) != 0) { 462 G_GATE_DEBUG(1, "Invalid flags."); 463 return (EINVAL); 464 } 465 if (ggio->gctl_unit != G_GATE_UNIT_AUTO && 466 ggio->gctl_unit != G_GATE_NAME_GIVEN && 467 ggio->gctl_unit < 0) { 468 G_GATE_DEBUG(1, "Invalid unit number."); 469 return (EINVAL); 470 } 471 if (ggio->gctl_unit == G_GATE_NAME_GIVEN && 472 ggio->gctl_name[0] == '\0') { 473 G_GATE_DEBUG(1, "No device name."); 474 return (EINVAL); 475 } 476 477 sc = malloc(sizeof(*sc), M_GATE, M_WAITOK | M_ZERO); 478 sc->sc_flags = (ggio->gctl_flags & G_GATE_USERFLAGS); 479 strlcpy(sc->sc_info, ggio->gctl_info, sizeof(sc->sc_info)); 480 sc->sc_seq = 1; 481 bioq_init(&sc->sc_inqueue); 482 bioq_init(&sc->sc_outqueue); 483 mtx_init(&sc->sc_queue_mtx, "gg:queue", NULL, MTX_DEF); 484 sc->sc_queue_count = 0; 485 sc->sc_queue_size = ggio->gctl_maxcount; 486 if (sc->sc_queue_size > G_GATE_MAX_QUEUE_SIZE) 487 sc->sc_queue_size = G_GATE_MAX_QUEUE_SIZE; 488 sc->sc_timeout = ggio->gctl_timeout; 489 callout_init(&sc->sc_callout, 1); 490 491 mtx_lock(&g_gate_units_lock); 492 sc->sc_unit = g_gate_getunit(ggio->gctl_unit, &error); 493 if (sc->sc_unit < 0) 494 goto fail1; 495 if (ggio->gctl_unit == G_GATE_NAME_GIVEN) 496 snprintf(name, sizeof(name), "%s", ggio->gctl_name); 497 else { 498 snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME, 499 sc->sc_unit); 500 } 501 /* Check for name collision. */ 502 for (unit = 0; unit < g_gate_maxunits; unit++) { 503 if (g_gate_units[unit] == NULL) 504 continue; 505 if (strcmp(name, g_gate_units[unit]->sc_name) != 0) 506 continue; 507 error = EEXIST; 508 goto fail1; 509 } 510 sc->sc_name = name; 511 g_gate_units[sc->sc_unit] = sc; 512 g_gate_nunits++; 513 mtx_unlock(&g_gate_units_lock); 514 515 g_topology_lock(); 516 517 if (ggio->gctl_readprov[0] == '\0') { 518 ropp = NULL; 519 } else { 520 ropp = g_provider_by_name(ggio->gctl_readprov); 521 if (ropp == NULL) { 522 G_GATE_DEBUG(1, "Provider %s doesn't exist.", 523 ggio->gctl_readprov); 524 error = EINVAL; 525 goto fail2; 526 } 527 if ((ggio->gctl_readoffset % ggio->gctl_sectorsize) != 0) { 528 G_GATE_DEBUG(1, "Invalid read offset."); 529 error = EINVAL; 530 goto fail2; 531 } 532 if (ggio->gctl_mediasize + ggio->gctl_readoffset > 533 ropp->mediasize) { 534 G_GATE_DEBUG(1, "Invalid read offset or media size."); 535 error = EINVAL; 536 goto fail2; 537 } 538 } 539 540 gp = g_new_geomf(&g_gate_class, "%s", name); 541 gp->start = g_gate_start; 542 gp->access = g_gate_access; 543 gp->orphan = g_gate_orphan; 544 gp->dumpconf = g_gate_dumpconf; 545 gp->softc = sc; 546 547 if (ropp != NULL) { 548 cp = g_new_consumer(gp); 549 cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; 550 error = g_attach(cp, ropp); 551 if (error != 0) { 552 G_GATE_DEBUG(1, "Unable to attach to %s.", ropp->name); 553 goto fail3; 554 } 555 error = g_access(cp, 1, 0, 0); 556 if (error != 0) { 557 G_GATE_DEBUG(1, "Unable to access %s.", ropp->name); 558 g_detach(cp); 559 goto fail3; 560 } 561 sc->sc_readcons = cp; 562 sc->sc_readoffset = ggio->gctl_readoffset; 563 } 564 565 ggio->gctl_unit = sc->sc_unit; 566 567 pp = g_new_providerf(gp, "%s", name); 568 pp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE; 569 pp->mediasize = ggio->gctl_mediasize; 570 pp->sectorsize = ggio->gctl_sectorsize; 571 sc->sc_provider = pp; 572 g_error_provider(pp, 0); 573 574 g_topology_unlock(); 575 mtx_lock(&g_gate_units_lock); 576 sc->sc_name = sc->sc_provider->name; 577 mtx_unlock(&g_gate_units_lock); 578 G_GATE_DEBUG(1, "Device %s created.", gp->name); 579 580 if (sc->sc_timeout > 0) { 581 callout_reset(&sc->sc_callout, sc->sc_timeout * hz, 582 g_gate_guard, sc); 583 } 584 return (0); 585 fail3: 586 g_destroy_consumer(cp); 587 g_destroy_geom(gp); 588 fail2: 589 g_topology_unlock(); 590 mtx_lock(&g_gate_units_lock); 591 g_gate_units[sc->sc_unit] = NULL; 592 KASSERT(g_gate_nunits > 0, ("negative g_gate_nunits?")); 593 g_gate_nunits--; 594 fail1: 595 mtx_unlock(&g_gate_units_lock); 596 mtx_destroy(&sc->sc_queue_mtx); 597 free(sc, M_GATE); 598 return (error); 599 } 600 601 static int 602 g_gate_modify(struct g_gate_softc *sc, struct g_gate_ctl_modify *ggio) 603 { 604 struct g_provider *pp; 605 struct g_consumer *cp; 606 int error; 607 608 if ((ggio->gctl_modify & GG_MODIFY_MEDIASIZE) != 0) { 609 if (ggio->gctl_mediasize <= 0) { 610 G_GATE_DEBUG(1, "Invalid media size."); 611 return (EINVAL); 612 } 613 pp = sc->sc_provider; 614 if ((ggio->gctl_mediasize % pp->sectorsize) != 0) { 615 G_GATE_DEBUG(1, "Invalid media size."); 616 return (EINVAL); 617 } 618 /* TODO */ 619 return (EOPNOTSUPP); 620 } 621 622 if ((ggio->gctl_modify & GG_MODIFY_INFO) != 0) 623 (void)strlcpy(sc->sc_info, ggio->gctl_info, sizeof(sc->sc_info)); 624 625 cp = NULL; 626 627 if ((ggio->gctl_modify & GG_MODIFY_READPROV) != 0) { 628 g_topology_lock(); 629 if (sc->sc_readcons != NULL) { 630 cp = sc->sc_readcons; 631 sc->sc_readcons = NULL; 632 (void)g_access(cp, -1, 0, 0); 633 g_detach(cp); 634 g_destroy_consumer(cp); 635 } 636 if (ggio->gctl_readprov[0] != '\0') { 637 pp = g_provider_by_name(ggio->gctl_readprov); 638 if (pp == NULL) { 639 g_topology_unlock(); 640 G_GATE_DEBUG(1, "Provider %s doesn't exist.", 641 ggio->gctl_readprov); 642 return (EINVAL); 643 } 644 cp = g_new_consumer(sc->sc_provider->geom); 645 cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; 646 error = g_attach(cp, pp); 647 if (error != 0) { 648 G_GATE_DEBUG(1, "Unable to attach to %s.", 649 pp->name); 650 } else { 651 error = g_access(cp, 1, 0, 0); 652 if (error != 0) { 653 G_GATE_DEBUG(1, "Unable to access %s.", 654 pp->name); 655 g_detach(cp); 656 } 657 } 658 if (error != 0) { 659 g_destroy_consumer(cp); 660 g_topology_unlock(); 661 return (error); 662 } 663 } 664 } else { 665 cp = sc->sc_readcons; 666 } 667 668 if ((ggio->gctl_modify & GG_MODIFY_READOFFSET) != 0) { 669 if (cp == NULL) { 670 G_GATE_DEBUG(1, "No read provider."); 671 return (EINVAL); 672 } 673 pp = sc->sc_provider; 674 if ((ggio->gctl_readoffset % pp->sectorsize) != 0) { 675 G_GATE_DEBUG(1, "Invalid read offset."); 676 return (EINVAL); 677 } 678 if (pp->mediasize + ggio->gctl_readoffset > 679 cp->provider->mediasize) { 680 G_GATE_DEBUG(1, "Invalid read offset or media size."); 681 return (EINVAL); 682 } 683 sc->sc_readoffset = ggio->gctl_readoffset; 684 } 685 686 if ((ggio->gctl_modify & GG_MODIFY_READPROV) != 0) { 687 sc->sc_readcons = cp; 688 g_topology_unlock(); 689 } 690 691 return (0); 692 } 693 694 #define G_GATE_CHECK_VERSION(ggio) do { \ 695 if ((ggio)->gctl_version != G_GATE_VERSION) { \ 696 printf("Version mismatch %d != %d.\n", \ 697 ggio->gctl_version, G_GATE_VERSION); \ 698 return (EINVAL); \ 699 } \ 700 } while (0) 701 static int 702 g_gate_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) 703 { 704 struct g_gate_softc *sc; 705 struct bio *bp; 706 int error = 0; 707 708 G_GATE_DEBUG(4, "ioctl(%s, %lx, %p, %x, %p)", devtoname(dev), cmd, addr, 709 flags, td); 710 711 switch (cmd) { 712 case G_GATE_CMD_CREATE: 713 { 714 struct g_gate_ctl_create *ggio = (void *)addr; 715 716 G_GATE_CHECK_VERSION(ggio); 717 error = g_gate_create(ggio); 718 /* 719 * Reset TDP_GEOM flag. 720 * There are pending events for sure, because we just created 721 * new provider and other classes want to taste it, but we 722 * cannot answer on I/O requests until we're here. 723 */ 724 td->td_pflags &= ~TDP_GEOM; 725 return (error); 726 } 727 case G_GATE_CMD_MODIFY: 728 { 729 struct g_gate_ctl_modify *ggio = (void *)addr; 730 731 G_GATE_CHECK_VERSION(ggio); 732 sc = g_gate_hold(ggio->gctl_unit, NULL); 733 if (sc == NULL) 734 return (ENXIO); 735 error = g_gate_modify(sc, ggio); 736 g_gate_release(sc); 737 return (error); 738 } 739 case G_GATE_CMD_DESTROY: 740 { 741 struct g_gate_ctl_destroy *ggio = (void *)addr; 742 743 G_GATE_CHECK_VERSION(ggio); 744 sc = g_gate_hold(ggio->gctl_unit, ggio->gctl_name); 745 if (sc == NULL) 746 return (ENXIO); 747 g_topology_lock(); 748 mtx_lock(&g_gate_units_lock); 749 error = g_gate_destroy(sc, ggio->gctl_force); 750 g_topology_unlock(); 751 if (error != 0) 752 g_gate_release(sc); 753 return (error); 754 } 755 case G_GATE_CMD_CANCEL: 756 { 757 struct g_gate_ctl_cancel *ggio = (void *)addr; 758 struct bio *tbp, *lbp; 759 760 G_GATE_CHECK_VERSION(ggio); 761 sc = g_gate_hold(ggio->gctl_unit, ggio->gctl_name); 762 if (sc == NULL) 763 return (ENXIO); 764 lbp = NULL; 765 mtx_lock(&sc->sc_queue_mtx); 766 TAILQ_FOREACH_SAFE(bp, &sc->sc_outqueue.queue, bio_queue, tbp) { 767 if (ggio->gctl_seq == 0 || 768 ggio->gctl_seq == (uintptr_t)bp->bio_driver1) { 769 G_GATE_LOGREQ(1, bp, "Request canceled."); 770 bioq_remove(&sc->sc_outqueue, bp); 771 /* 772 * Be sure to put requests back onto incoming 773 * queue in the proper order. 774 */ 775 if (lbp == NULL) 776 bioq_insert_head(&sc->sc_inqueue, bp); 777 else { 778 TAILQ_INSERT_AFTER(&sc->sc_inqueue.queue, 779 lbp, bp, bio_queue); 780 } 781 lbp = bp; 782 /* 783 * If only one request was canceled, leave now. 784 */ 785 if (ggio->gctl_seq != 0) 786 break; 787 } 788 } 789 if (ggio->gctl_unit == G_GATE_NAME_GIVEN) 790 ggio->gctl_unit = sc->sc_unit; 791 mtx_unlock(&sc->sc_queue_mtx); 792 g_gate_release(sc); 793 return (error); 794 } 795 case G_GATE_CMD_START: 796 { 797 struct g_gate_ctl_io *ggio = (void *)addr; 798 799 G_GATE_CHECK_VERSION(ggio); 800 sc = g_gate_hold(ggio->gctl_unit, NULL); 801 if (sc == NULL) 802 return (ENXIO); 803 error = 0; 804 for (;;) { 805 mtx_lock(&sc->sc_queue_mtx); 806 bp = bioq_first(&sc->sc_inqueue); 807 if (bp != NULL) 808 break; 809 if ((sc->sc_flags & G_GATE_FLAG_DESTROY) != 0) { 810 ggio->gctl_error = ECANCELED; 811 mtx_unlock(&sc->sc_queue_mtx); 812 goto start_end; 813 } 814 if (msleep(sc, &sc->sc_queue_mtx, 815 PPAUSE | PDROP | PCATCH, "ggwait", 0) != 0) { 816 ggio->gctl_error = ECANCELED; 817 goto start_end; 818 } 819 } 820 ggio->gctl_cmd = bp->bio_cmd; 821 if (bp->bio_cmd == BIO_WRITE && 822 bp->bio_length > ggio->gctl_length) { 823 mtx_unlock(&sc->sc_queue_mtx); 824 ggio->gctl_length = bp->bio_length; 825 ggio->gctl_error = ENOMEM; 826 goto start_end; 827 } 828 bioq_remove(&sc->sc_inqueue, bp); 829 bioq_insert_tail(&sc->sc_outqueue, bp); 830 mtx_unlock(&sc->sc_queue_mtx); 831 832 ggio->gctl_seq = (uintptr_t)bp->bio_driver1; 833 ggio->gctl_offset = bp->bio_offset; 834 ggio->gctl_length = bp->bio_length; 835 836 switch (bp->bio_cmd) { 837 case BIO_READ: 838 case BIO_DELETE: 839 case BIO_FLUSH: 840 break; 841 case BIO_WRITE: 842 error = copyout(bp->bio_data, ggio->gctl_data, 843 bp->bio_length); 844 if (error != 0) { 845 mtx_lock(&sc->sc_queue_mtx); 846 bioq_remove(&sc->sc_outqueue, bp); 847 bioq_insert_head(&sc->sc_inqueue, bp); 848 mtx_unlock(&sc->sc_queue_mtx); 849 goto start_end; 850 } 851 break; 852 } 853 start_end: 854 g_gate_release(sc); 855 return (error); 856 } 857 case G_GATE_CMD_DONE: 858 { 859 struct g_gate_ctl_io *ggio = (void *)addr; 860 861 G_GATE_CHECK_VERSION(ggio); 862 sc = g_gate_hold(ggio->gctl_unit, NULL); 863 if (sc == NULL) 864 return (ENOENT); 865 error = 0; 866 mtx_lock(&sc->sc_queue_mtx); 867 TAILQ_FOREACH(bp, &sc->sc_outqueue.queue, bio_queue) { 868 if (ggio->gctl_seq == (uintptr_t)bp->bio_driver1) 869 break; 870 } 871 if (bp != NULL) { 872 bioq_remove(&sc->sc_outqueue, bp); 873 sc->sc_queue_count--; 874 } 875 mtx_unlock(&sc->sc_queue_mtx); 876 if (bp == NULL) { 877 /* 878 * Request was probably canceled. 879 */ 880 goto done_end; 881 } 882 if (ggio->gctl_error == EAGAIN) { 883 bp->bio_error = 0; 884 G_GATE_LOGREQ(1, bp, "Request desisted."); 885 mtx_lock(&sc->sc_queue_mtx); 886 sc->sc_queue_count++; 887 bioq_insert_head(&sc->sc_inqueue, bp); 888 wakeup(sc); 889 mtx_unlock(&sc->sc_queue_mtx); 890 } else { 891 bp->bio_error = ggio->gctl_error; 892 if (bp->bio_error == 0) { 893 bp->bio_completed = bp->bio_length; 894 switch (bp->bio_cmd) { 895 case BIO_READ: 896 error = copyin(ggio->gctl_data, 897 bp->bio_data, bp->bio_length); 898 if (error != 0) 899 bp->bio_error = error; 900 break; 901 case BIO_DELETE: 902 case BIO_WRITE: 903 case BIO_FLUSH: 904 break; 905 } 906 } 907 G_GATE_LOGREQ(2, bp, "Request done."); 908 g_io_deliver(bp, bp->bio_error); 909 } 910 done_end: 911 g_gate_release(sc); 912 return (error); 913 } 914 } 915 return (ENOIOCTL); 916 } 917 918 static void 919 g_gate_device(void) 920 { 921 922 status_dev = make_dev(&g_gate_cdevsw, 0x0, UID_ROOT, GID_WHEEL, 0600, 923 G_GATE_CTL_NAME); 924 } 925 926 static int 927 g_gate_modevent(module_t mod, int type, void *data) 928 { 929 int error = 0; 930 931 switch (type) { 932 case MOD_LOAD: 933 mtx_init(&g_gate_units_lock, "gg_units_lock", NULL, MTX_DEF); 934 g_gate_units = malloc(g_gate_maxunits * sizeof(g_gate_units[0]), 935 M_GATE, M_WAITOK | M_ZERO); 936 g_gate_nunits = 0; 937 g_gate_device(); 938 break; 939 case MOD_UNLOAD: 940 mtx_lock(&g_gate_units_lock); 941 if (g_gate_nunits > 0) { 942 mtx_unlock(&g_gate_units_lock); 943 error = EBUSY; 944 break; 945 } 946 mtx_unlock(&g_gate_units_lock); 947 mtx_destroy(&g_gate_units_lock); 948 if (status_dev != NULL) 949 destroy_dev(status_dev); 950 free(g_gate_units, M_GATE); 951 break; 952 default: 953 return (EOPNOTSUPP); 954 break; 955 } 956 957 return (error); 958 } 959 static moduledata_t g_gate_module = { 960 G_GATE_MOD_NAME, 961 g_gate_modevent, 962 NULL 963 }; 964 DECLARE_MODULE(geom_gate, g_gate_module, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 965 DECLARE_GEOM_CLASS(g_gate_class, g_gate); 966