static int vdev_disk_physio(struct device *dev, caddr_t data, size_t size, uint64_t offset, int write) { struct bio *bio; int ret; bio = alloc_bio(); if (write) bio->bio_cmd = BIO_WRITE; else bio->bio_cmd = BIO_READ; bio->bio_dev = dev; bio->bio_data = data; bio->bio_offset = offset; bio->bio_bcount = size; bio->bio_dev->driver->devops->strategy(bio); ret = bio_wait(bio); destroy_bio(bio); return ret; }
static void vdev_disk_bio_done(struct bio *bio) { zio_t *zio = bio->bio_caller1; if (bio->bio_flags & BIO_ERROR) zio->io_error = EIO; else zio->io_error = 0; destroy_bio(bio); zio_interrupt(zio); }
static void multiplex_bio_done(struct bio *b) { struct bio *bio = b->bio_caller1; bool error = b->bio_flags & BIO_ERROR; destroy_bio(b); // If there is an error, we store it in the original bio flags. // This path gets slower because then we need to end up taking the // bio_mutex twice. But that should be fine. if (error) { pthread_mutex_lock(&bio->bio_mutex); bio->bio_flags |= BIO_ERROR; pthread_mutex_lock(&bio->bio_mutex); } // Last one releases it. We set the biodone to always be "ok", because // if an error exists, we have already set that in the previous operation if (refcount_release(&bio->bio_refcnt)) biodone(bio, true); }