Пример #1
0
/*
 * 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);
}
Пример #2
0
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);
}