/* * WRITE case: * * sbl is the list of bio; the first bio in the list and iblk specify * destination file offset; the content of bios in sbl is scattered source * buffer. * * The goal is to write source buffer to the file with given offset. We're * doing it by stuffing as many bvecs from source to kreqs as possible and * submitting kreqs to in-kernel aio. * * READ case: * * The same as WRITE, but here the file plays the role of source and the * content of bios in sbl plays the role of destination. */ static void kaio_sbl_submit(struct file *file, struct ploop_request *preq, unsigned long rw, struct bio_list *sbl, iblock_t iblk, size_t size) { struct bio *bio = sbl->head; int idx = 0; loff_t off = bio->bi_sector; off = ((loff_t)iblk << preq->plo->cluster_log) | (off & ((1<<preq->plo->cluster_log) - 1)); if (rw & REQ_WRITE) ploop_prepare_tracker(preq, off); off <<= 9; /* since now 'off' always points to a position in the file to X-mit */ WARN_ONCE(!(file->f_flags & O_DIRECT), "File opened w/o O_DIRECT"); ploop_prepare_io_request(preq); size <<= 9; while (size > 0) { struct kaio_req *kreq; int nr_segs; size_t copy; int err; kreq = kaio_kreq_alloc(preq, &nr_segs); if (!kreq) { PLOOP_REQ_SET_ERROR(preq, -ENOMEM); break; } copy = kaio_kreq_pack(kreq, &nr_segs, &bio, &idx, size); atomic_inc(&preq->io_count); err = kaio_kernel_submit(file, kreq, nr_segs, copy, off, rw); if (err) { PLOOP_REQ_SET_ERROR(preq, err); ploop_complete_io_request(preq); kfree(kreq); break; } off += copy; size -= copy; } kaio_complete_io_request(preq); }
static void kaio_submit(struct ploop_io *io, struct ploop_request * preq, unsigned long rw, struct bio_list *sbl, iblock_t iblk, unsigned int size) { struct bio * b; if (rw & BIO_FLUSH) { spin_lock_irq(&io->plo->lock); kaio_queue_fsync_req(preq); io->plo->st.bio_syncwait++; spin_unlock_irq(&io->plo->lock); return; } ploop_prepare_io_request(preq); if (iblk == PLOOP_ZERO_INDEX) iblk = 0; if (rw & (1<<BIO_RW)) { loff_t off = sbl->head->bi_sector; off = ((loff_t)iblk << preq->plo->cluster_log) | (off & ((1<<preq->plo->cluster_log) - 1)); ploop_prepare_tracker(preq, off); } for (b = sbl->head; b != NULL; b = b->bi_next) { int err; atomic_inc(&preq->io_count); err = kaio_kernel_submit(io->files.file, b, preq, iblk, rw); if (err) { ploop_set_error(preq, err); ploop_complete_io_request(preq); break; } } kaio_complete_io_request(preq); }