summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2013-07-30 21:35:02 +0000
committerdelphij <delphij@FreeBSD.org>2013-07-30 21:35:02 +0000
commitaac8087bead638965fd8df72ec05b082185fa599 (patch)
tree42a4c3e4cadd64a4c76674d8c73b30d409f60f18 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
parent6cd9d0f4540cebd88fc799aa2cb692e8d3d49dcd (diff)
downloadFreeBSD-src-aac8087bead638965fd8df72ec05b082185fa599.zip
FreeBSD-src-aac8087bead638965fd8df72ec05b082185fa599.tar.gz
MFV r253783:
Skip eviction step of processing free records when doing ZFS receive to avoid the expensive search operation of non-existent dbufs in dn_dbufs. Illumos ZFS issues: 3834 incremental replication of 'holey' file systems is slow MFC after: 2 weeks
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
index 28aa330..759fd7a 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
@@ -27,6 +27,7 @@
#include <sys/zfs_context.h>
#include <sys/dmu.h>
+#include <sys/dmu_send.h>
#include <sys/dmu_impl.h>
#include <sys/dbuf.h>
#include <sys/dmu_objset.h>
@@ -796,9 +797,12 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
/*
* Evict (if its unreferenced) or clear (if its referenced) any level-0
* data blocks in the free range, so that any future readers will find
- * empty blocks. Also, if we happen accross any level-1 dbufs in the
+ * empty blocks. Also, if we happen across any level-1 dbufs in the
* range that have not already been marked dirty, mark them dirty so
* they stay in memory.
+ *
+ * This is a no-op if the dataset is in the middle of an incremental
+ * receive; see comment below for details.
*/
void
dbuf_free_range(dnode_t *dn, uint64_t start, uint64_t end, dmu_tx_t *tx)
@@ -814,6 +818,20 @@ dbuf_free_range(dnode_t *dn, uint64_t start, uint64_t end, dmu_tx_t *tx)
last_l1 = end >> epbs;
}
dprintf_dnode(dn, "start=%llu end=%llu\n", start, end);
+
+ if (dmu_objset_is_receiving(dn->dn_objset)) {
+ /*
+ * When processing a free record from a zfs receive,
+ * there should have been no previous modifications to the
+ * data in this range. Therefore there should be no dbufs
+ * in the range. Searching dn_dbufs for these non-existent
+ * dbufs can be very expensive, so simply ignore this.
+ */
+ VERIFY3P(dbuf_find(dn, 0, start), ==, NULL);
+ VERIFY3P(dbuf_find(dn, 0, end), ==, NULL);
+ return;
+ }
+
mutex_enter(&dn->dn_dbufs_mtx);
for (db = list_head(&dn->dn_dbufs); db; db = db_next) {
db_next = list_next(&dn->dn_dbufs, db);
OpenPOWER on IntegriCloud