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;