]> granicus.if.org Git - zfs/commitdiff
Illumos 5175 - implement dmu_read_uio_dbuf() to improve cached read performance
authorMatthew Ahrens <mahrens@delphix.com>
Tue, 16 Jun 2015 21:06:27 +0000 (23:06 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 29 Jun 2015 21:33:23 +0000 (14:33 -0700)
5175 implement dmu_read_uio_dbuf() to improve cached read performance
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Alex Reece <alex.reece@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Richard Elling <richard.elling@gmail.com>
Approved by: Robert Mustacchi <rm@joyent.com>

References:
  https://www.illumos.org/issues/5175
  https://github.com/illumos/illumos-gate/commit/f8554bb

Porting notes:

This patch doesn't include the changes for the COMSTAR (Common
Multiprotocol SCSI Target) - since it's not available for ZoL.

http://thegreyblog.blogspot.co.at/2010/02/setting-up-solaris-comstar-and.html

Ported by: kernelOfTruth <kerneloftruth@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3392

include/sys/dmu.h
module/zfs/dmu.c
module/zfs/zfs_vnops.c

index a010a68c443e3f5e945487630df2e3aabc44d5bf..4ad496ae0dc34fff225887c7f5d3ea1354c76ea0 100644 (file)
@@ -714,6 +714,7 @@ int dmu_read_req(objset_t *os, uint64_t object, struct request *req);
 int dmu_write_req(objset_t *os, uint64_t object, struct request *req,
        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,
        dmu_tx_t *tx);
 int dmu_write_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size,
index 81f4343808a49538559117224c1aba68b053e442..7e8328e770a56b7ebc82e13b825587a07bb4fd35 100644 (file)
@@ -1199,8 +1199,8 @@ dmu_write_req(objset_t *os, uint64_t object, struct request *req, dmu_tx_t *tx)
        return (err);
 }
 
-int
-dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
+static int
+dmu_read_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size)
 {
        dmu_buf_t **dbp;
        int numbufs, i, err;
@@ -1210,8 +1210,8 @@ dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
         * 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, uio->uio_loffset, size, TRUE, FTAG,
-           &numbufs, &dbp);
+       err = dmu_buf_hold_array_by_dnode(dn, uio->uio_loffset, size,
+           TRUE, FTAG, &numbufs, &dbp, 0);
        if (err)
                return (err);
 
@@ -1253,6 +1253,58 @@ dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
        return (err);
 }
 
+/*
+ * Read 'size' bytes into the uio buffer.
+ * From object zdb->db_object.
+ * Starting at offset uio->uio_loffset.
+ *
+ * If the caller already has a dbuf in the target object
+ * (e.g. its bonus buffer), this routine is faster than dmu_read_uio(),
+ * because we don't have to find the dnode_t for the object.
+ */
+int
+dmu_read_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size)
+{
+       dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb;
+       dnode_t *dn;
+       int err;
+
+       if (size == 0)
+               return (0);
+
+       DB_DNODE_ENTER(db);
+       dn = DB_DNODE(db);
+       err = dmu_read_uio_dnode(dn, uio, size);
+       DB_DNODE_EXIT(db);
+
+       return (err);
+}
+
+/*
+ * Read 'size' bytes into the uio buffer.
+ * From the specified object
+ * Starting at offset uio->uio_loffset.
+ */
+int
+dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
+{
+       dnode_t *dn;
+       int err;
+
+       if (size == 0)
+               return (0);
+
+       err = dnode_hold(os, object, FTAG, &dn);
+       if (err)
+               return (err);
+
+       err = dmu_read_uio_dnode(dn, uio, size);
+
+       dnode_rele(dn, FTAG);
+
+       return (err);
+}
+
 static int
 dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx)
 {
@@ -1305,6 +1357,15 @@ dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx)
        return (err);
 }
 
+/*
+ * Write 'size' bytes from the uio buffer.
+ * To object zdb->db_object.
+ * Starting at offset uio->uio_loffset.
+ *
+ * If the caller already has a dbuf in the target object
+ * (e.g. its bonus buffer), this routine is faster than dmu_write_uio(),
+ * because we don't have to find the dnode_t for the object.
+ */
 int
 dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size,
     dmu_tx_t *tx)
@@ -1324,6 +1385,11 @@ dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size,
        return (err);
 }
 
+/*
+ * Write 'size' bytes from the uio buffer.
+ * To the specified object.
+ * Starting at offset uio->uio_loffset.
+ */
 int
 dmu_write_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size,
     dmu_tx_t *tx)
index 19a4132e4c078e2753a49b1bb93f9e12b604dace..7780fe902eb61d15449eefaeb2a45072daf7f88f 100644 (file)
@@ -376,7 +376,6 @@ mappedread(struct inode *ip, int nbytes, uio_t *uio)
        struct address_space *mp = ip->i_mapping;
        struct page *pp;
        znode_t *zp = ITOZ(ip);
-       objset_t *os = ITOZSB(ip)->z_os;
        int64_t start, off;
        uint64_t bytes;
        int len = nbytes;
@@ -403,7 +402,8 @@ mappedread(struct inode *ip, int nbytes, uio_t *uio)
                        unlock_page(pp);
                        page_cache_release(pp);
                } else {
-                       error = dmu_read_uio(os, zp->z_id, uio, bytes);
+                       error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
+                           uio, bytes);
                }
 
                len -= bytes;
@@ -440,7 +440,6 @@ zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
 {
        znode_t         *zp = ITOZ(ip);
        zfs_sb_t        *zsb = ITOZSB(ip);
-       objset_t        *os;
        ssize_t         n, nbytes;
        int             error = 0;
        rl_t            *rl;
@@ -450,7 +449,6 @@ zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
 
        ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
-       os = zsb->z_os;
 
        if (zp->z_pflags & ZFS_AV_QUARANTINED) {
                ZFS_EXIT(zsb);
@@ -531,10 +529,12 @@ zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
                nbytes = MIN(n, zfs_read_chunk_size -
                    P2PHASE(uio->uio_loffset, zfs_read_chunk_size));
 
-               if (zp->z_is_mapped && !(ioflag & O_DIRECT))
+               if (zp->z_is_mapped && !(ioflag & O_DIRECT)) {
                        error = mappedread(ip, nbytes, uio);
-               else
-                       error = dmu_read_uio(os, zp->z_id, uio, nbytes);
+               } else {
+                       error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
+                           uio, nbytes);
+               }
 
                if (error) {
                        /* convert checksum errors into IO errors */