1dd84a43cSPoul-Henning Kamp /*- 2dd84a43cSPoul-Henning Kamp * Copyright (c) 2002 Poul-Henning Kamp 3dd84a43cSPoul-Henning Kamp * Copyright (c) 2002 Networks Associates Technology, Inc. 4dd84a43cSPoul-Henning Kamp * All rights reserved. 5dd84a43cSPoul-Henning Kamp * 6dd84a43cSPoul-Henning Kamp * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7dd84a43cSPoul-Henning Kamp * and NAI Labs, the Security Research Division of Network Associates, Inc. 8dd84a43cSPoul-Henning Kamp * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9dd84a43cSPoul-Henning Kamp * DARPA CHATS research program. 10dd84a43cSPoul-Henning Kamp * 11dd84a43cSPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without 12dd84a43cSPoul-Henning Kamp * modification, are permitted provided that the following conditions 13dd84a43cSPoul-Henning Kamp * are met: 14dd84a43cSPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright 15dd84a43cSPoul-Henning Kamp * notice, this list of conditions and the following disclaimer. 16dd84a43cSPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright 17dd84a43cSPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the 18dd84a43cSPoul-Henning Kamp * documentation and/or other materials provided with the distribution. 19dd84a43cSPoul-Henning Kamp * 3. The names of the authors may not be used to endorse or promote 20dd84a43cSPoul-Henning Kamp * products derived from this software without specific prior written 21dd84a43cSPoul-Henning Kamp * permission. 22dd84a43cSPoul-Henning Kamp * 23dd84a43cSPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24dd84a43cSPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25dd84a43cSPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26dd84a43cSPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27dd84a43cSPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28dd84a43cSPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29dd84a43cSPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30dd84a43cSPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31dd84a43cSPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32dd84a43cSPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33dd84a43cSPoul-Henning Kamp * SUCH DAMAGE. 34dd84a43cSPoul-Henning Kamp * 35dd84a43cSPoul-Henning Kamp * $FreeBSD$ 36dd84a43cSPoul-Henning Kamp */ 37dd84a43cSPoul-Henning Kamp 38dd84a43cSPoul-Henning Kamp 39dd84a43cSPoul-Henning Kamp #include <sys/param.h> 400355b86eSPoul-Henning Kamp #include <sys/stdint.h> 41dd84a43cSPoul-Henning Kamp #ifndef _KERNEL 42dd84a43cSPoul-Henning Kamp #include <stdio.h> 43dd84a43cSPoul-Henning Kamp #include <string.h> 44dd84a43cSPoul-Henning Kamp #include <stdlib.h> 45dd84a43cSPoul-Henning Kamp #include <signal.h> 46dd84a43cSPoul-Henning Kamp #include <err.h> 47dd84a43cSPoul-Henning Kamp #include <sched.h> 48dd84a43cSPoul-Henning Kamp #else 49dd84a43cSPoul-Henning Kamp #include <sys/systm.h> 50dd84a43cSPoul-Henning Kamp #include <sys/kernel.h> 51dd84a43cSPoul-Henning Kamp #include <sys/malloc.h> 52dd84a43cSPoul-Henning Kamp #include <sys/bio.h> 53dd84a43cSPoul-Henning Kamp #endif 54dd84a43cSPoul-Henning Kamp 55dd84a43cSPoul-Henning Kamp #include <sys/errno.h> 56dd84a43cSPoul-Henning Kamp #include <geom/geom.h> 57b1876192SPoul-Henning Kamp #include <geom/geom_int.h> 58dd84a43cSPoul-Henning Kamp 59dd84a43cSPoul-Henning Kamp static struct g_bioq g_bio_run_down; 60dd84a43cSPoul-Henning Kamp static struct g_bioq g_bio_run_up; 61dd84a43cSPoul-Henning Kamp static struct g_bioq g_bio_idle; 62dd84a43cSPoul-Henning Kamp 633432e4fdSPoul-Henning Kamp static u_int pace; 643432e4fdSPoul-Henning Kamp 65dd84a43cSPoul-Henning Kamp #include <machine/atomic.h> 66dd84a43cSPoul-Henning Kamp 67dd84a43cSPoul-Henning Kamp static void 68dd84a43cSPoul-Henning Kamp g_bioq_lock(struct g_bioq *bq) 69dd84a43cSPoul-Henning Kamp { 70dd84a43cSPoul-Henning Kamp 71dd84a43cSPoul-Henning Kamp mtx_lock(&bq->bio_queue_lock); 72dd84a43cSPoul-Henning Kamp } 73dd84a43cSPoul-Henning Kamp 74dd84a43cSPoul-Henning Kamp static void 75dd84a43cSPoul-Henning Kamp g_bioq_unlock(struct g_bioq *bq) 76dd84a43cSPoul-Henning Kamp { 77dd84a43cSPoul-Henning Kamp 78dd84a43cSPoul-Henning Kamp mtx_unlock(&bq->bio_queue_lock); 79dd84a43cSPoul-Henning Kamp } 80dd84a43cSPoul-Henning Kamp 81dd84a43cSPoul-Henning Kamp #if 0 82dd84a43cSPoul-Henning Kamp static void 83dd84a43cSPoul-Henning Kamp g_bioq_destroy(struct g_bioq *bq) 84dd84a43cSPoul-Henning Kamp { 85dd84a43cSPoul-Henning Kamp 86dd84a43cSPoul-Henning Kamp mtx_destroy(&bq->bio_queue_lock); 87dd84a43cSPoul-Henning Kamp } 88dd84a43cSPoul-Henning Kamp #endif 89dd84a43cSPoul-Henning Kamp 90dd84a43cSPoul-Henning Kamp static void 91dd84a43cSPoul-Henning Kamp g_bioq_init(struct g_bioq *bq) 92dd84a43cSPoul-Henning Kamp { 93dd84a43cSPoul-Henning Kamp 94dd84a43cSPoul-Henning Kamp TAILQ_INIT(&bq->bio_queue); 956008862bSJohn Baldwin mtx_init(&bq->bio_queue_lock, "bio queue", NULL, MTX_DEF); 96dd84a43cSPoul-Henning Kamp } 97dd84a43cSPoul-Henning Kamp 98dd84a43cSPoul-Henning Kamp static struct bio * 99dd84a43cSPoul-Henning Kamp g_bioq_first(struct g_bioq *bq) 100dd84a43cSPoul-Henning Kamp { 101dd84a43cSPoul-Henning Kamp struct bio *bp; 102dd84a43cSPoul-Henning Kamp 103dd84a43cSPoul-Henning Kamp g_bioq_lock(bq); 104dd84a43cSPoul-Henning Kamp bp = TAILQ_FIRST(&bq->bio_queue); 105dd84a43cSPoul-Henning Kamp if (bp != NULL) { 106dd84a43cSPoul-Henning Kamp TAILQ_REMOVE(&bq->bio_queue, bp, bio_queue); 107dd84a43cSPoul-Henning Kamp bq->bio_queue_length--; 108dd84a43cSPoul-Henning Kamp } 109dd84a43cSPoul-Henning Kamp g_bioq_unlock(bq); 110dd84a43cSPoul-Henning Kamp return (bp); 111dd84a43cSPoul-Henning Kamp } 112dd84a43cSPoul-Henning Kamp 113dd84a43cSPoul-Henning Kamp static void 114dd84a43cSPoul-Henning Kamp g_bioq_enqueue_tail(struct bio *bp, struct g_bioq *rq) 115dd84a43cSPoul-Henning Kamp { 116dd84a43cSPoul-Henning Kamp 117dd84a43cSPoul-Henning Kamp g_bioq_lock(rq); 118dd84a43cSPoul-Henning Kamp TAILQ_INSERT_TAIL(&rq->bio_queue, bp, bio_queue); 119dd84a43cSPoul-Henning Kamp rq->bio_queue_length++; 120dd84a43cSPoul-Henning Kamp g_bioq_unlock(rq); 121dd84a43cSPoul-Henning Kamp } 122dd84a43cSPoul-Henning Kamp 123dd84a43cSPoul-Henning Kamp struct bio * 124dd84a43cSPoul-Henning Kamp g_new_bio(void) 125dd84a43cSPoul-Henning Kamp { 126dd84a43cSPoul-Henning Kamp struct bio *bp; 127dd84a43cSPoul-Henning Kamp 128dd84a43cSPoul-Henning Kamp bp = g_bioq_first(&g_bio_idle); 129dd84a43cSPoul-Henning Kamp if (bp == NULL) 130a1bd3ee2SPoul-Henning Kamp bp = g_malloc(sizeof *bp, M_NOWAIT | M_ZERO); 1310355b86eSPoul-Henning Kamp /* g_trace(G_T_BIO, "g_new_bio() = %p", bp); */ 132dd84a43cSPoul-Henning Kamp return (bp); 133dd84a43cSPoul-Henning Kamp } 134dd84a43cSPoul-Henning Kamp 135dd84a43cSPoul-Henning Kamp void 136dd84a43cSPoul-Henning Kamp g_destroy_bio(struct bio *bp) 137dd84a43cSPoul-Henning Kamp { 138dd84a43cSPoul-Henning Kamp 1390355b86eSPoul-Henning Kamp /* g_trace(G_T_BIO, "g_destroy_bio(%p)", bp); */ 140dd84a43cSPoul-Henning Kamp bzero(bp, sizeof *bp); 141dd84a43cSPoul-Henning Kamp g_bioq_enqueue_tail(bp, &g_bio_idle); 142dd84a43cSPoul-Henning Kamp } 143dd84a43cSPoul-Henning Kamp 144dd84a43cSPoul-Henning Kamp struct bio * 145dd84a43cSPoul-Henning Kamp g_clone_bio(struct bio *bp) 146dd84a43cSPoul-Henning Kamp { 147dd84a43cSPoul-Henning Kamp struct bio *bp2; 148dd84a43cSPoul-Henning Kamp 149dd84a43cSPoul-Henning Kamp bp2 = g_new_bio(); 150a1bd3ee2SPoul-Henning Kamp if (bp2 != NULL) { 151936cc461SPoul-Henning Kamp bp2->bio_parent = bp; 152dd84a43cSPoul-Henning Kamp bp2->bio_cmd = bp->bio_cmd; 153dd84a43cSPoul-Henning Kamp bp2->bio_length = bp->bio_length; 154dd84a43cSPoul-Henning Kamp bp2->bio_offset = bp->bio_offset; 155dd84a43cSPoul-Henning Kamp bp2->bio_data = bp->bio_data; 156dd84a43cSPoul-Henning Kamp bp2->bio_attribute = bp->bio_attribute; 1573f521b60SPoul-Henning Kamp bp->bio_children++; /* XXX: atomic ? */ 158a1bd3ee2SPoul-Henning Kamp } 1590355b86eSPoul-Henning Kamp /* g_trace(G_T_BIO, "g_clone_bio(%p) = %p", bp, bp2); */ 160dd84a43cSPoul-Henning Kamp return(bp2); 161dd84a43cSPoul-Henning Kamp } 162dd84a43cSPoul-Henning Kamp 163dd84a43cSPoul-Henning Kamp void 164dd84a43cSPoul-Henning Kamp g_io_init() 165dd84a43cSPoul-Henning Kamp { 166dd84a43cSPoul-Henning Kamp 167dd84a43cSPoul-Henning Kamp g_bioq_init(&g_bio_run_down); 168dd84a43cSPoul-Henning Kamp g_bioq_init(&g_bio_run_up); 169dd84a43cSPoul-Henning Kamp g_bioq_init(&g_bio_idle); 170dd84a43cSPoul-Henning Kamp } 171dd84a43cSPoul-Henning Kamp 172dd84a43cSPoul-Henning Kamp int 1730d3f37a8SPoul-Henning Kamp g_io_setattr(const char *attr, struct g_consumer *cp, int len, void *ptr) 174dd84a43cSPoul-Henning Kamp { 175dd84a43cSPoul-Henning Kamp struct bio *bp; 176dd84a43cSPoul-Henning Kamp int error; 177dd84a43cSPoul-Henning Kamp 178dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, "bio_setattr(%s)", attr); 179dd84a43cSPoul-Henning Kamp bp = g_new_bio(); 180dd84a43cSPoul-Henning Kamp bp->bio_cmd = BIO_SETATTR; 181dd84a43cSPoul-Henning Kamp bp->bio_done = NULL; 182dd84a43cSPoul-Henning Kamp bp->bio_attribute = attr; 183dd84a43cSPoul-Henning Kamp bp->bio_length = len; 184dd84a43cSPoul-Henning Kamp bp->bio_data = ptr; 185dd84a43cSPoul-Henning Kamp g_io_request(bp, cp); 18653706245SPoul-Henning Kamp error = biowait(bp, "gsetattr"); 187dd84a43cSPoul-Henning Kamp g_destroy_bio(bp); 188dd84a43cSPoul-Henning Kamp return (error); 189dd84a43cSPoul-Henning Kamp } 190dd84a43cSPoul-Henning Kamp 191dd84a43cSPoul-Henning Kamp 192dd84a43cSPoul-Henning Kamp int 1930d3f37a8SPoul-Henning Kamp g_io_getattr(const char *attr, struct g_consumer *cp, int *len, void *ptr) 194dd84a43cSPoul-Henning Kamp { 195dd84a43cSPoul-Henning Kamp struct bio *bp; 196dd84a43cSPoul-Henning Kamp int error; 197dd84a43cSPoul-Henning Kamp 198dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, "bio_getattr(%s)", attr); 199dd84a43cSPoul-Henning Kamp bp = g_new_bio(); 200dd84a43cSPoul-Henning Kamp bp->bio_cmd = BIO_GETATTR; 201dd84a43cSPoul-Henning Kamp bp->bio_done = NULL; 202dd84a43cSPoul-Henning Kamp bp->bio_attribute = attr; 203dd84a43cSPoul-Henning Kamp bp->bio_length = *len; 204dd84a43cSPoul-Henning Kamp bp->bio_data = ptr; 205dd84a43cSPoul-Henning Kamp g_io_request(bp, cp); 20653706245SPoul-Henning Kamp error = biowait(bp, "ggetattr"); 207dd84a43cSPoul-Henning Kamp *len = bp->bio_completed; 208dd84a43cSPoul-Henning Kamp g_destroy_bio(bp); 209dd84a43cSPoul-Henning Kamp return (error); 210dd84a43cSPoul-Henning Kamp } 211dd84a43cSPoul-Henning Kamp 212e39d70d4SPoul-Henning Kamp static int 213e39d70d4SPoul-Henning Kamp g_io_check(struct bio *bp) 214e39d70d4SPoul-Henning Kamp { 215e39d70d4SPoul-Henning Kamp struct g_consumer *cp; 216e39d70d4SPoul-Henning Kamp struct g_provider *pp; 217e39d70d4SPoul-Henning Kamp 218e39d70d4SPoul-Henning Kamp cp = bp->bio_from; 219e39d70d4SPoul-Henning Kamp pp = bp->bio_to; 220e39d70d4SPoul-Henning Kamp 221e39d70d4SPoul-Henning Kamp /* Fail if access counters dont allow the operation */ 222e39d70d4SPoul-Henning Kamp switch(bp->bio_cmd) { 223e39d70d4SPoul-Henning Kamp case BIO_READ: 224e39d70d4SPoul-Henning Kamp case BIO_GETATTR: 225e39d70d4SPoul-Henning Kamp if (cp->acr == 0) 226e39d70d4SPoul-Henning Kamp return (EPERM); 227e39d70d4SPoul-Henning Kamp break; 228e39d70d4SPoul-Henning Kamp case BIO_WRITE: 229e39d70d4SPoul-Henning Kamp case BIO_DELETE: 230e39d70d4SPoul-Henning Kamp case BIO_SETATTR: 231e39d70d4SPoul-Henning Kamp if (cp->acw == 0) 232e39d70d4SPoul-Henning Kamp return (EPERM); 233e39d70d4SPoul-Henning Kamp break; 234e39d70d4SPoul-Henning Kamp default: 235e39d70d4SPoul-Henning Kamp return (EPERM); 236e39d70d4SPoul-Henning Kamp } 237e39d70d4SPoul-Henning Kamp /* if provider is marked for error, don't disturb. */ 238e39d70d4SPoul-Henning Kamp if (pp->error) 239e39d70d4SPoul-Henning Kamp return (pp->error); 240e39d70d4SPoul-Henning Kamp 241e39d70d4SPoul-Henning Kamp switch(bp->bio_cmd) { 242e39d70d4SPoul-Henning Kamp case BIO_READ: 243e39d70d4SPoul-Henning Kamp case BIO_WRITE: 244e39d70d4SPoul-Henning Kamp case BIO_DELETE: 245e39d70d4SPoul-Henning Kamp /* Reject I/O not on sector boundary */ 246e39d70d4SPoul-Henning Kamp if (bp->bio_offset % pp->sectorsize) 247e39d70d4SPoul-Henning Kamp return (EINVAL); 248e39d70d4SPoul-Henning Kamp /* Reject I/O not integral sector long */ 249e39d70d4SPoul-Henning Kamp if (bp->bio_length % pp->sectorsize) 250e39d70d4SPoul-Henning Kamp return (EINVAL); 251e39d70d4SPoul-Henning Kamp /* Reject requests past the end of media. */ 252e39d70d4SPoul-Henning Kamp if (bp->bio_offset > pp->mediasize) 253e39d70d4SPoul-Henning Kamp return (EIO); 254e39d70d4SPoul-Henning Kamp break; 255e39d70d4SPoul-Henning Kamp default: 256e39d70d4SPoul-Henning Kamp break; 257e39d70d4SPoul-Henning Kamp } 258e39d70d4SPoul-Henning Kamp return (0); 259e39d70d4SPoul-Henning Kamp } 260e39d70d4SPoul-Henning Kamp 261dd84a43cSPoul-Henning Kamp void 262dd84a43cSPoul-Henning Kamp g_io_request(struct bio *bp, struct g_consumer *cp) 263dd84a43cSPoul-Henning Kamp { 264dd84a43cSPoul-Henning Kamp 265d0e17c1bSPoul-Henning Kamp KASSERT(cp != NULL, ("NULL cp in g_io_request")); 266d0e17c1bSPoul-Henning Kamp KASSERT(bp != NULL, ("NULL bp in g_io_request")); 267d0e17c1bSPoul-Henning Kamp KASSERT(bp->bio_data != NULL, ("NULL bp->data in g_io_request")); 268e39d70d4SPoul-Henning Kamp KASSERT(bp->bio_to == NULL, ("consumer not attached in g_io_request")); 269dd84a43cSPoul-Henning Kamp bp->bio_from = cp; 270dd84a43cSPoul-Henning Kamp bp->bio_to = cp->provider; 2712fccec19SPoul-Henning Kamp bp->bio_error = 0; 2722fccec19SPoul-Henning Kamp bp->bio_completed = 0; 273dd84a43cSPoul-Henning Kamp 274dd84a43cSPoul-Henning Kamp /* begin_stats(&bp->stats); */ 275dd84a43cSPoul-Henning Kamp 276dd84a43cSPoul-Henning Kamp atomic_add_int(&cp->biocount, 1); 277e39d70d4SPoul-Henning Kamp 2782fccec19SPoul-Henning Kamp /* Pass it on down. */ 279dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, "bio_request(%p) from %p(%s) to %p(%s) cmd %d", 280dd84a43cSPoul-Henning Kamp bp, bp->bio_from, bp->bio_from->geom->name, 281dd84a43cSPoul-Henning Kamp bp->bio_to, bp->bio_to->name, bp->bio_cmd); 282dd84a43cSPoul-Henning Kamp g_bioq_enqueue_tail(bp, &g_bio_run_down); 283dd84a43cSPoul-Henning Kamp wakeup(&g_wait_down); 284dd84a43cSPoul-Henning Kamp } 285dd84a43cSPoul-Henning Kamp 286dd84a43cSPoul-Henning Kamp void 28772840432SPoul-Henning Kamp g_io_deliver(struct bio *bp, int error) 288dd84a43cSPoul-Henning Kamp { 289dd84a43cSPoul-Henning Kamp 290d0e17c1bSPoul-Henning Kamp KASSERT(bp != NULL, ("NULL bp in g_io_deliver")); 291d0e17c1bSPoul-Henning Kamp KASSERT(bp->bio_from != NULL, ("NULL bio_from in g_io_deliver")); 2925ab413bfSPoul-Henning Kamp KASSERT(bp->bio_from->geom != NULL, 2935ab413bfSPoul-Henning Kamp ("NULL bio_from->geom in g_io_deliver")); 294d0e17c1bSPoul-Henning Kamp KASSERT(bp->bio_to != NULL, ("NULL bio_to in g_io_deliver")); 2955ab413bfSPoul-Henning Kamp 296dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, 2970355b86eSPoul-Henning Kamp "g_io_deliver(%p) from %p(%s) to %p(%s) cmd %d error %d off %jd len %jd", 298dd84a43cSPoul-Henning Kamp bp, bp->bio_from, bp->bio_from->geom->name, 2990355b86eSPoul-Henning Kamp bp->bio_to, bp->bio_to->name, bp->bio_cmd, error, 3000355b86eSPoul-Henning Kamp (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length); 301dd84a43cSPoul-Henning Kamp /* finish_stats(&bp->stats); */ 302dd84a43cSPoul-Henning Kamp 3033432e4fdSPoul-Henning Kamp if (error == ENOMEM) { 3043432e4fdSPoul-Henning Kamp printf("ENOMEM %p on %p(%s)\n", 3053432e4fdSPoul-Henning Kamp bp, bp->bio_to, bp->bio_to->name); 3063432e4fdSPoul-Henning Kamp g_io_request(bp, bp->bio_from); 3073432e4fdSPoul-Henning Kamp pace++; 3083432e4fdSPoul-Henning Kamp return; 3093432e4fdSPoul-Henning Kamp } 3103432e4fdSPoul-Henning Kamp 31172840432SPoul-Henning Kamp bp->bio_error = error; 31272840432SPoul-Henning Kamp 313dd84a43cSPoul-Henning Kamp g_bioq_enqueue_tail(bp, &g_bio_run_up); 314dd84a43cSPoul-Henning Kamp 315dd84a43cSPoul-Henning Kamp wakeup(&g_wait_up); 316dd84a43cSPoul-Henning Kamp } 317dd84a43cSPoul-Henning Kamp 318dd84a43cSPoul-Henning Kamp void 319dd84a43cSPoul-Henning Kamp g_io_schedule_down(struct thread *tp __unused) 320dd84a43cSPoul-Henning Kamp { 321dd84a43cSPoul-Henning Kamp struct bio *bp; 322e39d70d4SPoul-Henning Kamp off_t excess; 323e39d70d4SPoul-Henning Kamp int error; 324dd84a43cSPoul-Henning Kamp 325dd84a43cSPoul-Henning Kamp for(;;) { 326dd84a43cSPoul-Henning Kamp bp = g_bioq_first(&g_bio_run_down); 327dd84a43cSPoul-Henning Kamp if (bp == NULL) 328dd84a43cSPoul-Henning Kamp break; 329e39d70d4SPoul-Henning Kamp error = g_io_check(bp); 330e39d70d4SPoul-Henning Kamp if (error) { 331e39d70d4SPoul-Henning Kamp g_io_deliver(bp, error); 332e39d70d4SPoul-Henning Kamp continue; 333e39d70d4SPoul-Henning Kamp } 334e39d70d4SPoul-Henning Kamp /* Truncate requests to the end of providers media. */ 335e39d70d4SPoul-Henning Kamp excess = bp->bio_offset + bp->bio_length; 336e39d70d4SPoul-Henning Kamp if (excess > bp->bio_to->mediasize) { 337e39d70d4SPoul-Henning Kamp excess -= bp->bio_to->mediasize; 338e39d70d4SPoul-Henning Kamp bp->bio_length -= excess; 339e39d70d4SPoul-Henning Kamp } 340e39d70d4SPoul-Henning Kamp /* Deliver zero length transfers right here. */ 341e39d70d4SPoul-Henning Kamp if (bp->bio_length == 0) { 342e39d70d4SPoul-Henning Kamp g_io_deliver(bp, 0); 343e39d70d4SPoul-Henning Kamp continue; 344e39d70d4SPoul-Henning Kamp } 345dd84a43cSPoul-Henning Kamp bp->bio_to->geom->start(bp); 3463432e4fdSPoul-Henning Kamp if (pace) { 3473432e4fdSPoul-Henning Kamp pace--; 3483432e4fdSPoul-Henning Kamp break; 3493432e4fdSPoul-Henning Kamp } 350dd84a43cSPoul-Henning Kamp } 351dd84a43cSPoul-Henning Kamp } 352dd84a43cSPoul-Henning Kamp 353dd84a43cSPoul-Henning Kamp void 354dd84a43cSPoul-Henning Kamp g_io_schedule_up(struct thread *tp __unused) 355dd84a43cSPoul-Henning Kamp { 356dd84a43cSPoul-Henning Kamp struct bio *bp; 357dd84a43cSPoul-Henning Kamp struct g_consumer *cp; 358dd84a43cSPoul-Henning Kamp 359dd84a43cSPoul-Henning Kamp for(;;) { 360dd84a43cSPoul-Henning Kamp bp = g_bioq_first(&g_bio_run_up); 361dd84a43cSPoul-Henning Kamp if (bp == NULL) 362dd84a43cSPoul-Henning Kamp break; 363dd84a43cSPoul-Henning Kamp 364dd84a43cSPoul-Henning Kamp cp = bp->bio_from; 365dd84a43cSPoul-Henning Kamp 366dd84a43cSPoul-Henning Kamp atomic_add_int(&cp->biocount, -1); 36753706245SPoul-Henning Kamp biodone(bp); 368dd84a43cSPoul-Henning Kamp } 369dd84a43cSPoul-Henning Kamp } 370dd84a43cSPoul-Henning Kamp 371dd84a43cSPoul-Henning Kamp void * 372dd84a43cSPoul-Henning Kamp g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error) 373dd84a43cSPoul-Henning Kamp { 374dd84a43cSPoul-Henning Kamp struct bio *bp; 375dd84a43cSPoul-Henning Kamp void *ptr; 376dd84a43cSPoul-Henning Kamp int errorc; 377dd84a43cSPoul-Henning Kamp 378dd84a43cSPoul-Henning Kamp bp = g_new_bio(); 379dd84a43cSPoul-Henning Kamp bp->bio_cmd = BIO_READ; 380dd84a43cSPoul-Henning Kamp bp->bio_done = NULL; 381dd84a43cSPoul-Henning Kamp bp->bio_offset = offset; 382dd84a43cSPoul-Henning Kamp bp->bio_length = length; 38344956c98SAlfred Perlstein ptr = g_malloc(length, 0); 384dd84a43cSPoul-Henning Kamp bp->bio_data = ptr; 385dd84a43cSPoul-Henning Kamp g_io_request(bp, cp); 38653706245SPoul-Henning Kamp errorc = biowait(bp, "gread"); 387dd84a43cSPoul-Henning Kamp if (error != NULL) 388dd84a43cSPoul-Henning Kamp *error = errorc; 389dd84a43cSPoul-Henning Kamp g_destroy_bio(bp); 390dd84a43cSPoul-Henning Kamp if (errorc) { 391dd84a43cSPoul-Henning Kamp g_free(ptr); 392dd84a43cSPoul-Henning Kamp ptr = NULL; 393dd84a43cSPoul-Henning Kamp } 394dd84a43cSPoul-Henning Kamp return (ptr); 395dd84a43cSPoul-Henning Kamp } 39690b1cd56SPoul-Henning Kamp 39790b1cd56SPoul-Henning Kamp int 39890b1cd56SPoul-Henning Kamp g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length) 39990b1cd56SPoul-Henning Kamp { 40090b1cd56SPoul-Henning Kamp struct bio *bp; 40190b1cd56SPoul-Henning Kamp int error; 40290b1cd56SPoul-Henning Kamp 40390b1cd56SPoul-Henning Kamp bp = g_new_bio(); 40490b1cd56SPoul-Henning Kamp bp->bio_cmd = BIO_WRITE; 40590b1cd56SPoul-Henning Kamp bp->bio_done = NULL; 40690b1cd56SPoul-Henning Kamp bp->bio_offset = offset; 40790b1cd56SPoul-Henning Kamp bp->bio_length = length; 40890b1cd56SPoul-Henning Kamp bp->bio_data = ptr; 40990b1cd56SPoul-Henning Kamp g_io_request(bp, cp); 41090b1cd56SPoul-Henning Kamp error = biowait(bp, "gwrite"); 41190b1cd56SPoul-Henning Kamp g_destroy_bio(bp); 41290b1cd56SPoul-Henning Kamp return (error); 41390b1cd56SPoul-Henning Kamp } 414