]> granicus.if.org Git - zfs/commitdiff
Use uio for zvol_{read,write}
authorChunwei Chen <david.chen@osnexus.com>
Tue, 8 Dec 2015 20:37:24 +0000 (12:37 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 16 Dec 2015 00:21:43 +0000 (16:21 -0800)
Since uio now supports bvec, we can convert bio into uio and reuse
dmu_{read,write}_uio. This way, we can remove some duplicate code.

Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #4078

include/linux/blkdev_compat.h
include/sys/dmu.h
module/zfs/dmu.c
module/zfs/zvol.c

index 868b89c55cbbad13825bf07cb1b3c5ee09e31c11..0cb07207e44e49c8f29604bf4e3763e51624d77b 100644 (file)
@@ -118,6 +118,7 @@ get_disk_ro(struct gendisk *disk)
 #define        BIO_BI_SECTOR(bio)      (bio)->bi_iter.bi_sector
 #define        BIO_BI_SIZE(bio)        (bio)->bi_iter.bi_size
 #define        BIO_BI_IDX(bio)         (bio)->bi_iter.bi_idx
+#define        BIO_BI_SKIP(bio)        (bio)->bi_iter.bi_bvec_done
 #define        bio_for_each_segment4(bv, bvp, b, i)    \
        bio_for_each_segment((bv), (b), (i))
 typedef struct bvec_iter bvec_iterator_t;
@@ -125,6 +126,7 @@ typedef struct bvec_iter bvec_iterator_t;
 #define        BIO_BI_SECTOR(bio)      (bio)->bi_sector
 #define        BIO_BI_SIZE(bio)        (bio)->bi_size
 #define        BIO_BI_IDX(bio)         (bio)->bi_idx
+#define        BIO_BI_SKIP(bio)        (0)
 #define        bio_for_each_segment4(bv, bvp, b, i)    \
        bio_for_each_segment((bvp), (b), (i))
 typedef int bvec_iterator_t;
index d9434db463831df9b04f2e4214c07cc084e01732..6bf51975ea1ba452b64d077a1ff8842f949b1c09 100644 (file)
@@ -710,9 +710,6 @@ void dmu_prealloc(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
        dmu_tx_t *tx);
 #ifdef _KERNEL
 #include <linux/blkdev_compat.h>
-int dmu_read_bio(objset_t *os, uint64_t object, struct bio *bio);
-int dmu_write_bio(objset_t *os, uint64_t object, struct bio *bio,
-       dmu_tx_t *tx);
 int dmu_read_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size);
 int dmu_read_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size);
 int dmu_write_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size,
index 5e2a1db601b49fc85d59bf064cfcfa8a150f814f..f4027af9c1d4ea8f2800852ecf678f94b0c0bd40 100644 (file)
@@ -1041,170 +1041,6 @@ xuio_stat_wbuf_nocopy()
 }
 
 #ifdef _KERNEL
-
-/*
- * Copy up to size bytes between arg_buf and req based on the data direction
- * described by the req.  If an entire req's data cannot be transfered in one
- * pass, you should pass in @req_offset to indicate where to continue. The
- * return value is the number of bytes successfully copied to arg_buf.
- */
-static int
-dmu_bio_copy(void *arg_buf, int size, struct bio *bio, size_t bio_offset)
-{
-       struct bio_vec bv, *bvp = &bv;
-       bvec_iterator_t iter;
-       char *bv_buf;
-       int tocpy, bv_len, bv_offset;
-       int offset = 0;
-
-       bio_for_each_segment4(bv, bvp, bio, iter) {
-
-               /*
-                * Fully consumed the passed arg_buf. We use goto here because
-                * rq_for_each_segment is a double loop
-                */
-               ASSERT3S(offset, <=, size);
-               if (size == offset)
-                       goto out;
-
-               /* Skip already copied bvp */
-               if (bio_offset >= bvp->bv_len) {
-                       bio_offset -= bvp->bv_len;
-                       continue;
-               }
-
-               bv_len = bvp->bv_len - bio_offset;
-               bv_offset = bvp->bv_offset + bio_offset;
-               bio_offset = 0;
-
-               tocpy = MIN(bv_len, size - offset);
-               ASSERT3S(tocpy, >=, 0);
-
-               bv_buf = page_address(bvp->bv_page) + bv_offset;
-               ASSERT3P(bv_buf, !=, NULL);
-
-               if (bio_data_dir(bio) == WRITE)
-                       memcpy(arg_buf + offset, bv_buf, tocpy);
-               else
-                       memcpy(bv_buf, arg_buf + offset, tocpy);
-
-               offset += tocpy;
-       }
-out:
-       return (offset);
-}
-
-int
-dmu_read_bio(objset_t *os, uint64_t object, struct bio *bio)
-{
-       uint64_t offset = BIO_BI_SECTOR(bio) << 9;
-       uint64_t size = BIO_BI_SIZE(bio);
-       dmu_buf_t **dbp;
-       int numbufs, i, err;
-       size_t bio_offset;
-
-       /*
-        * NB: we could do this block-at-a-time, but it's nice
-        * to be reading in parallel.
-        */
-       err = dmu_buf_hold_array(os, object, offset, size, TRUE, FTAG,
-           &numbufs, &dbp);
-       if (err)
-               return (err);
-
-       bio_offset = 0;
-       for (i = 0; i < numbufs; i++) {
-               uint64_t tocpy;
-               int64_t bufoff;
-               int didcpy;
-               dmu_buf_t *db = dbp[i];
-
-               bufoff = offset - db->db_offset;
-               ASSERT3S(bufoff, >=, 0);
-
-               tocpy = MIN(db->db_size - bufoff, size);
-               if (tocpy == 0)
-                       break;
-
-               didcpy = dmu_bio_copy(db->db_data + bufoff, tocpy, bio,
-                   bio_offset);
-
-               if (didcpy < tocpy)
-                       err = EIO;
-
-               if (err)
-                       break;
-
-               size -= tocpy;
-               offset += didcpy;
-               bio_offset += didcpy;
-               err = 0;
-       }
-       dmu_buf_rele_array(dbp, numbufs, FTAG);
-
-       return (err);
-}
-
-int
-dmu_write_bio(objset_t *os, uint64_t object, struct bio *bio, dmu_tx_t *tx)
-{
-       uint64_t offset = BIO_BI_SECTOR(bio) << 9;
-       uint64_t size = BIO_BI_SIZE(bio);
-       dmu_buf_t **dbp;
-       int numbufs, i, err;
-       size_t bio_offset;
-
-       if (size == 0)
-               return (0);
-
-       err = dmu_buf_hold_array(os, object, offset, size, FALSE, FTAG,
-           &numbufs, &dbp);
-       if (err)
-               return (err);
-
-       bio_offset = 0;
-       for (i = 0; i < numbufs; i++) {
-               uint64_t tocpy;
-               int64_t bufoff;
-               int didcpy;
-               dmu_buf_t *db = dbp[i];
-
-               bufoff = offset - db->db_offset;
-               ASSERT3S(bufoff, >=, 0);
-
-               tocpy = MIN(db->db_size - bufoff, size);
-               if (tocpy == 0)
-                       break;
-
-               ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size);
-
-               if (tocpy == db->db_size)
-                       dmu_buf_will_fill(db, tx);
-               else
-                       dmu_buf_will_dirty(db, tx);
-
-               didcpy = dmu_bio_copy(db->db_data + bufoff, tocpy, bio,
-                   bio_offset);
-
-               if (tocpy == db->db_size)
-                       dmu_buf_fill_done(db, tx);
-
-               if (didcpy < tocpy)
-                       err = EIO;
-
-               if (err)
-                       break;
-
-               size -= tocpy;
-               offset += didcpy;
-               bio_offset += didcpy;
-               err = 0;
-       }
-
-       dmu_buf_rele_array(dbp, numbufs, FTAG);
-       return (err);
-}
-
 static int
 dmu_read_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size)
 {
index 574d3c306bc9964f24fa13ed1bf31f925c3f4371..8208d29f382c41fb5d2c1eb677ff2d3af314540e 100644 (file)
@@ -597,6 +597,7 @@ zvol_write(struct bio *bio)
        int error = 0;
        dmu_tx_t *tx;
        rl_t *rl;
+       uio_t uio;
 
        if (bio->bi_rw & VDEV_REQ_FLUSH)
                zil_commit(zv->zv_zilog, ZVOL_OBJ);
@@ -607,6 +608,14 @@ zvol_write(struct bio *bio)
        if (size == 0)
                goto out;
 
+       uio.uio_bvec = &bio->bi_io_vec[BIO_BI_IDX(bio)];
+       uio.uio_skip = BIO_BI_SKIP(bio);
+       uio.uio_resid = size;
+       uio.uio_iovcnt = bio->bi_vcnt - BIO_BI_IDX(bio);
+       uio.uio_loffset = offset;
+       uio.uio_limit = MAXOFFSET_T;
+       uio.uio_segflg = UIO_BVEC;
+
        rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_WRITER);
 
        tx = dmu_tx_create(zv->zv_objset);
@@ -620,7 +629,7 @@ zvol_write(struct bio *bio)
                goto out;
        }
 
-       error = dmu_write_bio(zv->zv_objset, ZVOL_OBJ, bio, tx);
+       error = dmu_write_uio(zv->zv_objset, ZVOL_OBJ, &uio, size, tx);
        if (error == 0)
                zvol_log_write(zv, tx, offset, size,
                    !!(bio->bi_rw & VDEV_REQ_FUA));
@@ -686,17 +695,25 @@ zvol_read(struct bio *bio)
 {
        zvol_state_t *zv = bio->bi_bdev->bd_disk->private_data;
        uint64_t offset = BIO_BI_SECTOR(bio) << 9;
-       uint64_t len = BIO_BI_SIZE(bio);
+       uint64_t size = BIO_BI_SIZE(bio);
        int error;
        rl_t *rl;
+       uio_t uio;
 
-       if (len == 0)
+       if (size == 0)
                return (0);
 
+       uio.uio_bvec = &bio->bi_io_vec[BIO_BI_IDX(bio)];
+       uio.uio_skip = BIO_BI_SKIP(bio);
+       uio.uio_resid = size;
+       uio.uio_iovcnt = bio->bi_vcnt - BIO_BI_IDX(bio);
+       uio.uio_loffset = offset;
+       uio.uio_limit = MAXOFFSET_T;
+       uio.uio_segflg = UIO_BVEC;
 
-       rl = zfs_range_lock(&zv->zv_znode, offset, len, RL_READER);
+       rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_READER);
 
-       error = dmu_read_bio(zv->zv_objset, ZVOL_OBJ, bio);
+       error = dmu_read_uio(zv->zv_objset, ZVOL_OBJ, &uio, size);
 
        zfs_range_unlock(rl);