diff options
author | Matthew Ahrens <[email protected]> | 2014-04-15 19:40:22 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2014-07-30 09:20:35 -0700 |
commit | 9bd274ddd846cd4024ebe3253c7b2d4f3b6f9dc0 (patch) | |
tree | 81da771b7588f8585fca225f38a32f605a3486a1 /module/zfs/dnode_sync.c | |
parent | da536844d55b2f3aaefdaebd36fb97bb867494aa (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.c | 39 |
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) { |