Print this page
4374 dn_free_ranges should use range_tree_t
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Max Grossman <max.grossman@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Approved by: Dan McDonald <danmcd@omniti.com>

*** 19,29 **** * CDDL HEADER END */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright (c) 2013 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> #include <sys/dbuf.h> #include <sys/dnode.h> --- 19,29 ---- * CDDL HEADER END */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright (c) 2012, 2014 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> #include <sys/dbuf.h> #include <sys/dnode.h>
*** 30,39 **** --- 30,40 ---- #include <sys/dmu.h> #include <sys/dmu_tx.h> #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 dnode_increase_indirection(dnode_t *dn, dmu_tx_t *tx) {
*** 316,326 **** /* * Traverse the indicated range of the provided file * and "free" all the blocks contained there. */ static void ! dnode_sync_free_range(dnode_t *dn, uint64_t blkid, uint64_t nblks, dmu_tx_t *tx) { blkptr_t *bp = dn->dn_phys->dn_blkptr; int dnlevel = dn->dn_phys->dn_nlevels; boolean_t trunc = B_FALSE; --- 317,327 ---- /* * Traverse the indicated range of the provided file * and "free" all the blocks contained there. */ static void ! 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; int dnlevel = dn->dn_phys->dn_nlevels; boolean_t trunc = B_FALSE;
*** 374,383 **** --- 375,400 ---- dn->dn_phys->dn_maxblkid == 0 || dnode_next_offset(dn, 0, &off, 1, 1, 0) != 0); } } + 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... */ void dnode_evict_dbufs(dnode_t *dn)
*** 531,541 **** * Write out the dnode's dirty buffers. */ 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]; static const dnode_phys_t zerodn = { 0 }; boolean_t kill_spill = B_FALSE; --- 548,557 ----
*** 589,601 **** if (dn->dn_next_blksz[txgoff] != 0) { ASSERT(P2PHASE(dn->dn_next_blksz[txgoff], 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 = dn->dn_next_blksz[txgoff] >> SPA_MINBLOCKSHIFT; dn->dn_next_blksz[txgoff] = 0; } --- 605,617 ---- if (dn->dn_next_blksz[txgoff] != 0) { ASSERT(P2PHASE(dn->dn_next_blksz[txgoff], SPA_MINBLOCKSIZE) == 0); ASSERT(BP_IS_HOLE(&dnp->dn_blkptr[0]) || dn->dn_maxblkid == 0 || list_head(list) != NULL || dn->dn_next_blksz[txgoff] >> SPA_MINBLOCKSHIFT == ! 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; }
*** 650,666 **** dnp->dn_flags &= ~DNODE_FLAG_SPILL_BLKPTR; mutex_exit(&dn->dn_mtx); } /* 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() */ mutex_enter(&dn->dn_mtx); ! avl_remove(&dn->dn_ranges[txgoff], rp); mutex_exit(&dn->dn_mtx); - kmem_free(rp, sizeof (free_range_t)); } if (freeing_dnode) { dnode_sync_free(dn, tx); return; --- 666,685 ---- dnp->dn_flags &= ~DNODE_FLAG_SPILL_BLKPTR; mutex_exit(&dn->dn_mtx); } /* process all the "freed" ranges in the file */ ! 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); ! 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); } if (freeing_dnode) { dnode_sync_free(dn, tx); return;