]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/dmu.c
Illumos 5987 - zfs prefetch code needs work
[mirror_zfs.git] / module / zfs / dmu.c
index b4133f0e4205c10746e4857f1f6dd73066e56d39..1bf108bfeabb63aedfbf7b02b48ed92873e0a725 100644 (file)
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
  * Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2015 by Chunwei Chen. All rights reserved.
@@ -386,7 +386,7 @@ dmu_spill_hold_by_bonus(dmu_buf_t *bonus, void *tag, dmu_buf_t **dbp)
  */
 static int
 dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
-    int read, void *tag, int *numbufsp, dmu_buf_t ***dbpp, uint32_t flags)
+    boolean_t read, void *tag, int *numbufsp, dmu_buf_t ***dbpp, uint32_t flags)
 {
        dmu_buf_t **dbp;
        uint64_t blkid, nblks, i;
@@ -396,15 +396,19 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
 
        ASSERT(length <= DMU_MAX_ACCESS);
 
-       dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT | DB_RF_HAVESTRUCT;
-       if (flags & DMU_READ_NO_PREFETCH || length > zfetch_array_rd_sz)
-               dbuf_flags |= DB_RF_NOPREFETCH;
+       /*
+        * Note: We directly notify the prefetch code of this read, so that
+        * we can tell it about the multi-block read.  dbuf_read() only knows
+        * about the one block it is accessing.
+        */
+       dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT | DB_RF_HAVESTRUCT |
+           DB_RF_NOPREFETCH;
 
        rw_enter(&dn->dn_struct_rwlock, RW_READER);
        if (dn->dn_datablkshift) {
                int blkshift = dn->dn_datablkshift;
-               nblks = (P2ROUNDUP(offset+length, 1ULL<<blkshift) -
-                   P2ALIGN(offset, 1ULL<<blkshift)) >> blkshift;
+               nblks = (P2ROUNDUP(offset + length, 1ULL << blkshift) -
+                   P2ALIGN(offset, 1ULL << blkshift)) >> blkshift;
        } else {
                if (offset + length > dn->dn_datablksz) {
                        zfs_panic_recover("zfs: accessing past end of object "
@@ -423,19 +427,24 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
        zio = zio_root(dn->dn_objset->os_spa, NULL, NULL, ZIO_FLAG_CANFAIL);
        blkid = dbuf_whichblock(dn, 0, offset);
        for (i = 0; i < nblks; i++) {
-               dmu_buf_impl_t *db = dbuf_hold(dn, blkid+i, tag);
+               dmu_buf_impl_t *db = dbuf_hold(dn, blkid + i, tag);
                if (db == NULL) {
                        rw_exit(&dn->dn_struct_rwlock);
                        dmu_buf_rele_array(dbp, nblks, tag);
                        zio_nowait(zio);
                        return (SET_ERROR(EIO));
                }
+
                /* initiate async i/o */
-               if (read) {
+               if (read)
                        (void) dbuf_read(db, zio, dbuf_flags);
-               }
                dbp[i] = &db->db;
        }
+
+       if ((flags & DMU_READ_NO_PREFETCH) == 0 && read &&
+           length < zfetch_array_rd_sz) {
+               dmu_zfetch(&dn->dn_zfetch, blkid, nblks);
+       }
        rw_exit(&dn->dn_struct_rwlock);
 
        /* wait for async i/o */
@@ -489,7 +498,8 @@ dmu_buf_hold_array(objset_t *os, uint64_t object, uint64_t offset,
 
 int
 dmu_buf_hold_array_by_bonus(dmu_buf_t *db_fake, uint64_t offset,
-    uint64_t length, int read, void *tag, int *numbufsp, dmu_buf_t ***dbpp)
+    uint64_t length, boolean_t read, void *tag, int *numbufsp,
+    dmu_buf_t ***dbpp)
 {
        dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
        dnode_t *dn;
@@ -537,9 +547,6 @@ dmu_prefetch(objset_t *os, uint64_t object, int64_t level, uint64_t offset,
        uint64_t blkid;
        int nblks, err;
 
-       if (zfs_prefetch_disable)
-               return;
-
        if (len == 0) {  /* they're interested in the bonus buffer */
                dn = DMU_META_DNODE(os);