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 int vdev_disk_start_flush(zio_t *zio) { vdev_t *vd = zio->io_vd; struct vdev_disk *dvd = vd->vdev_tsd; struct bio *bio; bio = alloc_bio(); bio->bio_cmd = BIO_FLUSH; bio->bio_dev = dvd->device; bio->bio_caller1 = zio; bio->bio_done = vdev_disk_bio_done; bio->bio_dev->driver->devops->strategy(bio); return ZIO_PIPELINE_STOP; }
void multiplex_strategy(struct bio *bio) { struct device *dev = bio->bio_dev; devop_strategy_t strategy = *((devop_strategy_t *)dev->private_data); uint64_t len = bio->bio_bcount; bio->bio_offset += bio->bio_dev->offset; uint64_t offset = bio->bio_offset; void *buf = bio->bio_data; assert(strategy != NULL); if (len <= dev->max_io_size) { strategy(bio); return; } // It is better to initialize the refcounter beforehand, specially because we can // trivially determine what is the number going to be. Otherwise, we can have a // situation in which we bump the refcount to 1, get scheduled out, the bio is // finished, and when it drops its refcount to 0, we consider the main bio finished. refcount_init(&bio->bio_refcnt, (len / dev->max_io_size) + !!(len % dev->max_io_size)); while (len > 0) { uint64_t req_size = MIN(len, dev->max_io_size); struct bio *b = alloc_bio(); b->bio_bcount = req_size; b->bio_data = buf; b->bio_offset = offset; b->bio_cmd = bio->bio_cmd; b->bio_dev = bio->bio_dev; b->bio_caller1 = bio; b->bio_done = multiplex_bio_done; strategy(b); buf += req_size; offset += req_size; len -= req_size; } }
static int vdev_disk_start_bio(zio_t *zio) { vdev_t *vd = zio->io_vd; struct vdev_disk *dvd = vd->vdev_tsd; struct bio *bio; bio = alloc_bio(); if (zio->io_type == ZIO_TYPE_READ) bio->bio_cmd = BIO_READ; else bio->bio_cmd = BIO_WRITE; bio->bio_dev = dvd->device; bio->bio_data = zio->io_data; bio->bio_offset = zio->io_offset; bio->bio_bcount = zio->io_size; bio->bio_caller1 = zio; bio->bio_done = vdev_disk_bio_done; bio->bio_dev->driver->devops->strategy(bio); return ZIO_PIPELINE_STOP; }