summaryrefslogtreecommitdiffstats
path: root/module/zfs/dnode_sync.c
diff options
context:
space:
mode:
authorMatthew Ahrens <[email protected]>2014-04-15 19:40:22 -0800
committerBrian Behlendorf <[email protected]>2014-07-30 09:20:35 -0700
commit9bd274ddd846cd4024ebe3253c7b2d4f3b6f9dc0 (patch)
tree81da771b7588f8585fca225f38a32f605a3486a1 /module/zfs/dnode_sync.c
parentda536844d55b2f3aaefdaebd36fb97bb867494aa (diff)
Illumos #4374
4374 dn_free_ranges should use range_tree_t Reviewed by: George Wilson <[email protected]> Reviewed by: Max Grossman <[email protected]> Reviewed by: Christopher Siden <[email protected] Reviewed by: Garrett D'Amore <[email protected]> Reviewed by: Dan McDonald <[email protected]> Approved by: Dan McDonald <[email protected]> References: https://www.illumos.org/issues/4374 https://github.com/illumos/illumos-gate/commit/bf16b11 Ported by: Tim Chase <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #2531
Diffstat (limited to 'module/zfs/dnode_sync.c')
-rw-r--r--module/zfs/dnode_sync.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/module/zfs/dnode_sync.c b/module/zfs/dnode_sync.c
index 885dc2dbc..238920060 100644
--- a/module/zfs/dnode_sync.c
+++ b/module/zfs/dnode_sync.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
*/
#include <sys/zfs_context.h>
@@ -32,6 +32,7 @@
#include <sys/dmu_objset.h>
#include <sys/dsl_dataset.h>
#include <sys/spa.h>
+#include <sys/range_tree.h>
#include <sys/zfeature.h>
static void
@@ -322,7 +323,7 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
* and "free" all the blocks contained there.
*/
static void
-dnode_sync_free_range(dnode_t *dn, uint64_t blkid, uint64_t nblks,
+dnode_sync_free_range_impl(dnode_t *dn, uint64_t blkid, uint64_t nblks,
dmu_tx_t *tx)
{
blkptr_t *bp = dn->dn_phys->dn_blkptr;
@@ -381,6 +382,22 @@ dnode_sync_free_range(dnode_t *dn, uint64_t blkid, uint64_t nblks,
}
}
+typedef struct dnode_sync_free_range_arg {
+ dnode_t *dsfra_dnode;
+ dmu_tx_t *dsfra_tx;
+} dnode_sync_free_range_arg_t;
+
+static void
+dnode_sync_free_range(void *arg, uint64_t blkid, uint64_t nblks)
+{
+ dnode_sync_free_range_arg_t *dsfra = arg;
+ dnode_t *dn = dsfra->dsfra_dnode;
+
+ mutex_exit(&dn->dn_mtx);
+ dnode_sync_free_range_impl(dn, blkid, nblks, dsfra->dsfra_tx);
+ mutex_enter(&dn->dn_mtx);
+}
+
/*
* Try to kick all the dnode's dbufs out of the cache...
*/
@@ -542,7 +559,6 @@ dnode_sync_free(dnode_t *dn, dmu_tx_t *tx)
void
dnode_sync(dnode_t *dn, dmu_tx_t *tx)
{
- free_range_t *rp;
dnode_phys_t *dnp = dn->dn_phys;
int txgoff = tx->tx_txg & TXG_MASK;
list_t *list = &dn->dn_dirty_records[txgoff];
@@ -601,9 +617,9 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
SPA_MINBLOCKSIZE) == 0);
ASSERT(BP_IS_HOLE(&dnp->dn_blkptr[0]) ||
dn->dn_maxblkid == 0 || list_head(list) != NULL ||
- avl_last(&dn->dn_ranges[txgoff]) ||
dn->dn_next_blksz[txgoff] >> SPA_MINBLOCKSHIFT ==
- dnp->dn_datablkszsec);
+ dnp->dn_datablkszsec ||
+ range_tree_space(dn->dn_free_ranges[txgoff]) != 0);
dnp->dn_datablkszsec =
dn->dn_next_blksz[txgoff] >> SPA_MINBLOCKSHIFT;
dn->dn_next_blksz[txgoff] = 0;
@@ -661,13 +677,16 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
}
/* process all the "freed" ranges in the file */
- while ((rp = avl_last(&dn->dn_ranges[txgoff]))) {
- dnode_sync_free_range(dn, rp->fr_blkid, rp->fr_nblks, tx);
- /* grab the mutex so we don't race with dnode_block_freed() */
+ if (dn->dn_free_ranges[txgoff] != NULL) {
+ dnode_sync_free_range_arg_t dsfra;
+ dsfra.dsfra_dnode = dn;
+ dsfra.dsfra_tx = tx;
mutex_enter(&dn->dn_mtx);
- avl_remove(&dn->dn_ranges[txgoff], rp);
+ range_tree_vacate(dn->dn_free_ranges[txgoff],
+ dnode_sync_free_range, &dsfra);
+ range_tree_destroy(dn->dn_free_ranges[txgoff]);
+ dn->dn_free_ranges[txgoff] = NULL;
mutex_exit(&dn->dn_mtx);
- kmem_free(rp, sizeof (free_range_t));
}
if (freeing_dnode) {