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> 40dd84a43cSPoul-Henning Kamp #ifndef _KERNEL 41dd84a43cSPoul-Henning Kamp #include <stdio.h> 42dd84a43cSPoul-Henning Kamp #include <string.h> 43dd84a43cSPoul-Henning Kamp #include <stdlib.h> 44dd84a43cSPoul-Henning Kamp #include <signal.h> 45dd84a43cSPoul-Henning Kamp #include <err.h> 46dd84a43cSPoul-Henning Kamp #include <sched.h> 47dd84a43cSPoul-Henning Kamp #else 48dd84a43cSPoul-Henning Kamp #include <sys/systm.h> 49dd84a43cSPoul-Henning Kamp #include <sys/kernel.h> 50dd84a43cSPoul-Henning Kamp #include <sys/malloc.h> 51dd84a43cSPoul-Henning Kamp #include <sys/bio.h> 52dd84a43cSPoul-Henning Kamp #endif 53dd84a43cSPoul-Henning Kamp 54dd84a43cSPoul-Henning Kamp #include <sys/errno.h> 55dd84a43cSPoul-Henning Kamp #include <geom/geom.h> 56dd84a43cSPoul-Henning Kamp 57dd84a43cSPoul-Henning Kamp static struct g_bioq g_bio_run_down; 58dd84a43cSPoul-Henning Kamp static struct g_bioq g_bio_run_up; 59dd84a43cSPoul-Henning Kamp static struct g_bioq g_bio_idle; 60dd84a43cSPoul-Henning Kamp 61dd84a43cSPoul-Henning Kamp #include <machine/atomic.h> 62dd84a43cSPoul-Henning Kamp 63dd84a43cSPoul-Henning Kamp static void 64dd84a43cSPoul-Henning Kamp g_bioq_lock(struct g_bioq *bq) 65dd84a43cSPoul-Henning Kamp { 66dd84a43cSPoul-Henning Kamp 67dd84a43cSPoul-Henning Kamp mtx_lock(&bq->bio_queue_lock); 68dd84a43cSPoul-Henning Kamp } 69dd84a43cSPoul-Henning Kamp 70dd84a43cSPoul-Henning Kamp static void 71dd84a43cSPoul-Henning Kamp g_bioq_unlock(struct g_bioq *bq) 72dd84a43cSPoul-Henning Kamp { 73dd84a43cSPoul-Henning Kamp 74dd84a43cSPoul-Henning Kamp mtx_unlock(&bq->bio_queue_lock); 75dd84a43cSPoul-Henning Kamp } 76dd84a43cSPoul-Henning Kamp 77dd84a43cSPoul-Henning Kamp #if 0 78dd84a43cSPoul-Henning Kamp static void 79dd84a43cSPoul-Henning Kamp g_bioq_destroy(struct g_bioq *bq) 80dd84a43cSPoul-Henning Kamp { 81dd84a43cSPoul-Henning Kamp 82dd84a43cSPoul-Henning Kamp mtx_destroy(&bq->bio_queue_lock); 83dd84a43cSPoul-Henning Kamp } 84dd84a43cSPoul-Henning Kamp #endif 85dd84a43cSPoul-Henning Kamp 86dd84a43cSPoul-Henning Kamp static void 87dd84a43cSPoul-Henning Kamp g_bioq_init(struct g_bioq *bq) 88dd84a43cSPoul-Henning Kamp { 89dd84a43cSPoul-Henning Kamp 90dd84a43cSPoul-Henning Kamp TAILQ_INIT(&bq->bio_queue); 91dd84a43cSPoul-Henning Kamp mtx_init(&bq->bio_queue_lock, "bio queue", MTX_DEF); 92dd84a43cSPoul-Henning Kamp } 93dd84a43cSPoul-Henning Kamp 94dd84a43cSPoul-Henning Kamp static struct bio * 95dd84a43cSPoul-Henning Kamp g_bioq_first(struct g_bioq *bq) 96dd84a43cSPoul-Henning Kamp { 97dd84a43cSPoul-Henning Kamp struct bio *bp; 98dd84a43cSPoul-Henning Kamp 99dd84a43cSPoul-Henning Kamp g_bioq_lock(bq); 100dd84a43cSPoul-Henning Kamp bp = TAILQ_FIRST(&bq->bio_queue); 101dd84a43cSPoul-Henning Kamp if (bp != NULL) { 102dd84a43cSPoul-Henning Kamp TAILQ_REMOVE(&bq->bio_queue, bp, bio_queue); 103dd84a43cSPoul-Henning Kamp bq->bio_queue_length--; 104dd84a43cSPoul-Henning Kamp } 105dd84a43cSPoul-Henning Kamp g_bioq_unlock(bq); 106dd84a43cSPoul-Henning Kamp return (bp); 107dd84a43cSPoul-Henning Kamp } 108dd84a43cSPoul-Henning Kamp 109dd84a43cSPoul-Henning Kamp static void 110dd84a43cSPoul-Henning Kamp g_bioq_enqueue_tail(struct bio *bp, struct g_bioq *rq) 111dd84a43cSPoul-Henning Kamp { 112dd84a43cSPoul-Henning Kamp 113dd84a43cSPoul-Henning Kamp g_bioq_lock(rq); 114dd84a43cSPoul-Henning Kamp TAILQ_INSERT_TAIL(&rq->bio_queue, bp, bio_queue); 115dd84a43cSPoul-Henning Kamp rq->bio_queue_length++; 116dd84a43cSPoul-Henning Kamp g_bioq_unlock(rq); 117dd84a43cSPoul-Henning Kamp } 118dd84a43cSPoul-Henning Kamp 119dd84a43cSPoul-Henning Kamp struct bio * 120dd84a43cSPoul-Henning Kamp g_new_bio(void) 121dd84a43cSPoul-Henning Kamp { 122dd84a43cSPoul-Henning Kamp struct bio *bp; 123dd84a43cSPoul-Henning Kamp 124dd84a43cSPoul-Henning Kamp bp = g_bioq_first(&g_bio_idle); 125dd84a43cSPoul-Henning Kamp if (bp == NULL) 126dd84a43cSPoul-Henning Kamp bp = g_malloc(sizeof *bp, M_WAITOK | M_ZERO); 127dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, "g_new_bio() = %p", bp); 128dd84a43cSPoul-Henning Kamp return (bp); 129dd84a43cSPoul-Henning Kamp } 130dd84a43cSPoul-Henning Kamp 131dd84a43cSPoul-Henning Kamp void 132dd84a43cSPoul-Henning Kamp g_destroy_bio(struct bio *bp) 133dd84a43cSPoul-Henning Kamp { 134dd84a43cSPoul-Henning Kamp 135dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, "g_destroy_bio(%p)", bp); 136dd84a43cSPoul-Henning Kamp bzero(bp, sizeof *bp); 137dd84a43cSPoul-Henning Kamp g_bioq_enqueue_tail(bp, &g_bio_idle); 138dd84a43cSPoul-Henning Kamp } 139dd84a43cSPoul-Henning Kamp 140dd84a43cSPoul-Henning Kamp struct bio * 141dd84a43cSPoul-Henning Kamp g_clone_bio(struct bio *bp) 142dd84a43cSPoul-Henning Kamp { 143dd84a43cSPoul-Henning Kamp struct bio *bp2; 144dd84a43cSPoul-Henning Kamp 145dd84a43cSPoul-Henning Kamp bp2 = g_new_bio(); 146dd84a43cSPoul-Henning Kamp bp2->bio_linkage = bp; 147dd84a43cSPoul-Henning Kamp bp2->bio_cmd = bp->bio_cmd; 148dd84a43cSPoul-Henning Kamp bp2->bio_length = bp->bio_length; 149dd84a43cSPoul-Henning Kamp bp2->bio_offset = bp->bio_offset; 150dd84a43cSPoul-Henning Kamp bp2->bio_data = bp->bio_data; 151dd84a43cSPoul-Henning Kamp bp2->bio_attribute = bp->bio_attribute; 152dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, "g_clone_bio(%p) = %p", bp, bp2); 153dd84a43cSPoul-Henning Kamp return(bp2); 154dd84a43cSPoul-Henning Kamp } 155dd84a43cSPoul-Henning Kamp 156dd84a43cSPoul-Henning Kamp void 157dd84a43cSPoul-Henning Kamp g_io_init() 158dd84a43cSPoul-Henning Kamp { 159dd84a43cSPoul-Henning Kamp 160dd84a43cSPoul-Henning Kamp g_bioq_init(&g_bio_run_down); 161dd84a43cSPoul-Henning Kamp g_bioq_init(&g_bio_run_up); 162dd84a43cSPoul-Henning Kamp g_bioq_init(&g_bio_idle); 163dd84a43cSPoul-Henning Kamp } 164dd84a43cSPoul-Henning Kamp 165dd84a43cSPoul-Henning Kamp int 166dd84a43cSPoul-Henning Kamp g_io_setattr(char *attr, struct g_consumer *cp, int len, void *ptr, struct thread *tp __unused) 167dd84a43cSPoul-Henning Kamp { 168dd84a43cSPoul-Henning Kamp struct bio *bp; 169dd84a43cSPoul-Henning Kamp int error; 170dd84a43cSPoul-Henning Kamp 171dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, "bio_setattr(%s)", attr); 172dd84a43cSPoul-Henning Kamp do { 173dd84a43cSPoul-Henning Kamp bp = g_new_bio(); 174dd84a43cSPoul-Henning Kamp bp->bio_cmd = BIO_SETATTR; 175dd84a43cSPoul-Henning Kamp bp->bio_done = NULL; 176dd84a43cSPoul-Henning Kamp bp->bio_attribute = attr; 177dd84a43cSPoul-Henning Kamp bp->bio_length = len; 178dd84a43cSPoul-Henning Kamp bp->bio_data = ptr; 179dd84a43cSPoul-Henning Kamp g_io_request(bp, cp); 180dd84a43cSPoul-Henning Kamp while ((bp->bio_flags & BIO_DONE) == 0) { 181dd84a43cSPoul-Henning Kamp mtx_lock(&Giant); 182dd84a43cSPoul-Henning Kamp tsleep(bp, 0, "setattr", hz / 10); 183dd84a43cSPoul-Henning Kamp mtx_unlock(&Giant); 184dd84a43cSPoul-Henning Kamp } 185dd84a43cSPoul-Henning Kamp error = bp->bio_error; 186dd84a43cSPoul-Henning Kamp g_destroy_bio(bp); 187dd84a43cSPoul-Henning Kamp if (error == EBUSY) 188dd84a43cSPoul-Henning Kamp tsleep(&error, 0, "setattr_busy", hz); 189dd84a43cSPoul-Henning Kamp } while(error == EBUSY); 190dd84a43cSPoul-Henning Kamp return (error); 191dd84a43cSPoul-Henning Kamp } 192dd84a43cSPoul-Henning Kamp 193dd84a43cSPoul-Henning Kamp 194dd84a43cSPoul-Henning Kamp int 195dd84a43cSPoul-Henning Kamp g_io_getattr(char *attr, struct g_consumer *cp, int *len, void *ptr, struct thread *tp __unused) 196dd84a43cSPoul-Henning Kamp { 197dd84a43cSPoul-Henning Kamp struct bio *bp; 198dd84a43cSPoul-Henning Kamp int error; 199dd84a43cSPoul-Henning Kamp 200dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, "bio_getattr(%s)", attr); 201dd84a43cSPoul-Henning Kamp do { 202dd84a43cSPoul-Henning Kamp bp = g_new_bio(); 203dd84a43cSPoul-Henning Kamp bp->bio_cmd = BIO_GETATTR; 204dd84a43cSPoul-Henning Kamp bp->bio_done = NULL; 205dd84a43cSPoul-Henning Kamp bp->bio_attribute = attr; 206dd84a43cSPoul-Henning Kamp bp->bio_length = *len; 207dd84a43cSPoul-Henning Kamp bp->bio_data = ptr; 208dd84a43cSPoul-Henning Kamp g_io_request(bp, cp); 209dd84a43cSPoul-Henning Kamp while ((bp->bio_flags & BIO_DONE) == 0) { 210dd84a43cSPoul-Henning Kamp mtx_lock(&Giant); 211dd84a43cSPoul-Henning Kamp tsleep(bp, 0, "getattr", hz / 10); 212dd84a43cSPoul-Henning Kamp mtx_unlock(&Giant); 213dd84a43cSPoul-Henning Kamp } 214dd84a43cSPoul-Henning Kamp *len = bp->bio_completed; 215dd84a43cSPoul-Henning Kamp error = bp->bio_error; 216dd84a43cSPoul-Henning Kamp g_destroy_bio(bp); 217dd84a43cSPoul-Henning Kamp if (error == EBUSY) 218dd84a43cSPoul-Henning Kamp tsleep(&error, 0, "getattr_busy", hz); 219dd84a43cSPoul-Henning Kamp 220dd84a43cSPoul-Henning Kamp } while(error == EBUSY); 221dd84a43cSPoul-Henning Kamp return (error); 222dd84a43cSPoul-Henning Kamp } 223dd84a43cSPoul-Henning Kamp 224dd84a43cSPoul-Henning Kamp void 225dd84a43cSPoul-Henning Kamp g_io_request(struct bio *bp, struct g_consumer *cp) 226dd84a43cSPoul-Henning Kamp { 227dd84a43cSPoul-Henning Kamp int error; 228dd84a43cSPoul-Henning Kamp 229dd84a43cSPoul-Henning Kamp KASSERT(cp != NULL, ("bio_request on thin air")); 230dd84a43cSPoul-Henning Kamp error = 0; 231dd84a43cSPoul-Henning Kamp bp->bio_from = cp; 232dd84a43cSPoul-Henning Kamp bp->bio_to = cp->provider; 233dd84a43cSPoul-Henning Kamp 234dd84a43cSPoul-Henning Kamp /* begin_stats(&bp->stats); */ 235dd84a43cSPoul-Henning Kamp 236dd84a43cSPoul-Henning Kamp atomic_add_int(&cp->biocount, 1); 237dd84a43cSPoul-Henning Kamp if (bp->bio_to == NULL) 238dd84a43cSPoul-Henning Kamp error = ENXIO; 239dd84a43cSPoul-Henning Kamp if (!error) { 240dd84a43cSPoul-Henning Kamp switch(bp->bio_cmd) { 241dd84a43cSPoul-Henning Kamp case BIO_READ: 242dd84a43cSPoul-Henning Kamp case BIO_GETATTR: 243dd84a43cSPoul-Henning Kamp if (cp->acr == 0) 244dd84a43cSPoul-Henning Kamp error = EPERM; 245dd84a43cSPoul-Henning Kamp break; 246dd84a43cSPoul-Henning Kamp case BIO_WRITE: 247dd84a43cSPoul-Henning Kamp if (cp->acw == 0) 248dd84a43cSPoul-Henning Kamp error = EPERM; 249dd84a43cSPoul-Henning Kamp break; 250dd84a43cSPoul-Henning Kamp case BIO_SETATTR: 251dd84a43cSPoul-Henning Kamp case BIO_DELETE: 252dd84a43cSPoul-Henning Kamp case BIO_FORMAT: 253dd84a43cSPoul-Henning Kamp if ((cp->acw == 0) || (cp->ace == 0)) 254dd84a43cSPoul-Henning Kamp error = EPERM; 255dd84a43cSPoul-Henning Kamp break; 256dd84a43cSPoul-Henning Kamp default: 257dd84a43cSPoul-Henning Kamp error = EPERM; 258dd84a43cSPoul-Henning Kamp break; 259dd84a43cSPoul-Henning Kamp } 260dd84a43cSPoul-Henning Kamp } 261dd84a43cSPoul-Henning Kamp /* if provider is marked for error, don't disturb */ 262dd84a43cSPoul-Henning Kamp if (!error) 263dd84a43cSPoul-Henning Kamp error = bp->bio_to->error; 264dd84a43cSPoul-Henning Kamp if (error) { 265dd84a43cSPoul-Henning Kamp bp->bio_error = error; 266dd84a43cSPoul-Henning Kamp /* finish_stats(&bp->stats); */ 267dd84a43cSPoul-Henning Kamp 268dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, 269dd84a43cSPoul-Henning Kamp "bio_request(%p) from %p(%s) to %p(%s) cmd %d error %d\n", 270dd84a43cSPoul-Henning Kamp bp, bp->bio_from, bp->bio_from->geom->name, 271dd84a43cSPoul-Henning Kamp bp->bio_to, bp->bio_to->name, bp->bio_cmd, bp->bio_error); 272dd84a43cSPoul-Henning Kamp g_bioq_enqueue_tail(bp, &g_bio_run_up); 273dd84a43cSPoul-Henning Kamp mtx_lock(&Giant); 274dd84a43cSPoul-Henning Kamp wakeup(&g_wait_up); 275dd84a43cSPoul-Henning Kamp mtx_unlock(&Giant); 276dd84a43cSPoul-Henning Kamp } else { 277dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, "bio_request(%p) from %p(%s) to %p(%s) cmd %d", 278dd84a43cSPoul-Henning Kamp bp, bp->bio_from, bp->bio_from->geom->name, 279dd84a43cSPoul-Henning Kamp bp->bio_to, bp->bio_to->name, bp->bio_cmd); 280dd84a43cSPoul-Henning Kamp g_bioq_enqueue_tail(bp, &g_bio_run_down); 281dd84a43cSPoul-Henning Kamp mtx_lock(&Giant); 282dd84a43cSPoul-Henning Kamp wakeup(&g_wait_down); 283dd84a43cSPoul-Henning Kamp mtx_unlock(&Giant); 284dd84a43cSPoul-Henning Kamp } 285dd84a43cSPoul-Henning Kamp } 286dd84a43cSPoul-Henning Kamp 287dd84a43cSPoul-Henning Kamp void 288dd84a43cSPoul-Henning Kamp g_io_deliver(struct bio *bp) 289dd84a43cSPoul-Henning Kamp { 290dd84a43cSPoul-Henning Kamp 291dd84a43cSPoul-Henning Kamp g_trace(G_T_BIO, 292dd84a43cSPoul-Henning Kamp "g_io_deliver(%p) from %p(%s) to %p(%s) cmd %d error %d", 293dd84a43cSPoul-Henning Kamp bp, bp->bio_from, bp->bio_from->geom->name, 294dd84a43cSPoul-Henning Kamp bp->bio_to, bp->bio_to->name, bp->bio_cmd, bp->bio_error); 295dd84a43cSPoul-Henning Kamp /* finish_stats(&bp->stats); */ 296dd84a43cSPoul-Henning Kamp 297dd84a43cSPoul-Henning Kamp g_bioq_enqueue_tail(bp, &g_bio_run_up); 298dd84a43cSPoul-Henning Kamp 299dd84a43cSPoul-Henning Kamp mtx_lock(&Giant); 300dd84a43cSPoul-Henning Kamp wakeup(&g_wait_up); 301dd84a43cSPoul-Henning Kamp mtx_unlock(&Giant); 302dd84a43cSPoul-Henning Kamp } 303dd84a43cSPoul-Henning Kamp 304dd84a43cSPoul-Henning Kamp void 305dd84a43cSPoul-Henning Kamp g_io_schedule_down(struct thread *tp __unused) 306dd84a43cSPoul-Henning Kamp { 307dd84a43cSPoul-Henning Kamp struct bio *bp; 308dd84a43cSPoul-Henning Kamp 309dd84a43cSPoul-Henning Kamp for(;;) { 310dd84a43cSPoul-Henning Kamp bp = g_bioq_first(&g_bio_run_down); 311dd84a43cSPoul-Henning Kamp if (bp == NULL) 312dd84a43cSPoul-Henning Kamp break; 313dd84a43cSPoul-Henning Kamp bp->bio_to->geom->start(bp); 314dd84a43cSPoul-Henning Kamp } 315dd84a43cSPoul-Henning Kamp } 316dd84a43cSPoul-Henning Kamp 317dd84a43cSPoul-Henning Kamp void 318dd84a43cSPoul-Henning Kamp g_io_schedule_up(struct thread *tp __unused) 319dd84a43cSPoul-Henning Kamp { 320dd84a43cSPoul-Henning Kamp struct bio *bp; 321dd84a43cSPoul-Henning Kamp struct g_consumer *cp; 322dd84a43cSPoul-Henning Kamp 323dd84a43cSPoul-Henning Kamp for(;;) { 324dd84a43cSPoul-Henning Kamp bp = g_bioq_first(&g_bio_run_up); 325dd84a43cSPoul-Henning Kamp if (bp == NULL) 326dd84a43cSPoul-Henning Kamp break; 327dd84a43cSPoul-Henning Kamp 328dd84a43cSPoul-Henning Kamp cp = bp->bio_from; 329dd84a43cSPoul-Henning Kamp 330dd84a43cSPoul-Henning Kamp bp->bio_flags |= BIO_DONE; 331dd84a43cSPoul-Henning Kamp atomic_add_int(&cp->biocount, -1); 332dd84a43cSPoul-Henning Kamp if (bp->bio_done != NULL) { 333dd84a43cSPoul-Henning Kamp bp->bio_done(bp); 334dd84a43cSPoul-Henning Kamp } else { 335dd84a43cSPoul-Henning Kamp mtx_lock(&Giant); 336dd84a43cSPoul-Henning Kamp wakeup(bp); 337dd84a43cSPoul-Henning Kamp mtx_unlock(&Giant); 338dd84a43cSPoul-Henning Kamp } 339dd84a43cSPoul-Henning Kamp } 340dd84a43cSPoul-Henning Kamp } 341dd84a43cSPoul-Henning Kamp 342dd84a43cSPoul-Henning Kamp void * 343dd84a43cSPoul-Henning Kamp g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error) 344dd84a43cSPoul-Henning Kamp { 345dd84a43cSPoul-Henning Kamp struct bio *bp; 346dd84a43cSPoul-Henning Kamp void *ptr; 347dd84a43cSPoul-Henning Kamp int errorc; 348dd84a43cSPoul-Henning Kamp 349dd84a43cSPoul-Henning Kamp do { 350dd84a43cSPoul-Henning Kamp bp = g_new_bio(); 351dd84a43cSPoul-Henning Kamp bp->bio_cmd = BIO_READ; 352dd84a43cSPoul-Henning Kamp bp->bio_done = NULL; 353dd84a43cSPoul-Henning Kamp bp->bio_offset = offset; 354dd84a43cSPoul-Henning Kamp bp->bio_length = length; 355dd84a43cSPoul-Henning Kamp ptr = g_malloc(length, M_WAITOK); 356dd84a43cSPoul-Henning Kamp bp->bio_data = ptr; 357dd84a43cSPoul-Henning Kamp g_io_request(bp, cp); 358dd84a43cSPoul-Henning Kamp while ((bp->bio_flags & BIO_DONE) == 0) { 359dd84a43cSPoul-Henning Kamp mtx_lock(&Giant); 360dd84a43cSPoul-Henning Kamp tsleep(bp, 0, "g_read_data", hz / 10); 361dd84a43cSPoul-Henning Kamp mtx_unlock(&Giant); 362dd84a43cSPoul-Henning Kamp } 363dd84a43cSPoul-Henning Kamp errorc = bp->bio_error; 364dd84a43cSPoul-Henning Kamp if (error != NULL) 365dd84a43cSPoul-Henning Kamp *error = errorc; 366dd84a43cSPoul-Henning Kamp g_destroy_bio(bp); 367dd84a43cSPoul-Henning Kamp if (errorc) { 368dd84a43cSPoul-Henning Kamp g_free(ptr); 369dd84a43cSPoul-Henning Kamp ptr = NULL; 370dd84a43cSPoul-Henning Kamp } 371dd84a43cSPoul-Henning Kamp if (errorc == EBUSY) 372dd84a43cSPoul-Henning Kamp tsleep(&errorc, 0, "g_read_data_busy", hz); 373dd84a43cSPoul-Henning Kamp } while (errorc == EBUSY); 374dd84a43cSPoul-Henning Kamp return (ptr); 375dd84a43cSPoul-Henning Kamp } 376