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