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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dnode_sync.c
          +++ new/usr/src/uts/common/fs/zfs/dnode_sync.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright (c) 2013 by Delphix. All rights reserved.
       24 + * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
  25   25   */
  26   26  
  27   27  #include <sys/zfs_context.h>
  28   28  #include <sys/dbuf.h>
  29   29  #include <sys/dnode.h>
  30   30  #include <sys/dmu.h>
  31   31  #include <sys/dmu_tx.h>
  32   32  #include <sys/dmu_objset.h>
  33   33  #include <sys/dsl_dataset.h>
  34   34  #include <sys/spa.h>
       35 +#include <sys/range_tree.h>
  35   36  #include <sys/zfeature.h>
  36   37  
  37   38  static void
  38   39  dnode_increase_indirection(dnode_t *dn, dmu_tx_t *tx)
  39   40  {
  40   41          dmu_buf_impl_t *db;
  41   42          int txgoff = tx->tx_txg & TXG_MASK;
  42   43          int nblkptr = dn->dn_phys->dn_nblkptr;
  43   44          int old_toplvl = dn->dn_phys->dn_nlevels - 1;
  44   45          int new_level = dn->dn_next_nlevels[txgoff];
↓ open down ↓ 266 lines elided ↑ open up ↑
 311  312  
 312  313          DB_DNODE_EXIT(db);
 313  314          arc_buf_freeze(db->db_buf);
 314  315  }
 315  316  
 316  317  /*
 317  318   * Traverse the indicated range of the provided file
 318  319   * and "free" all the blocks contained there.
 319  320   */
 320  321  static void
 321      -dnode_sync_free_range(dnode_t *dn, uint64_t blkid, uint64_t nblks,
      322 +dnode_sync_free_range_impl(dnode_t *dn, uint64_t blkid, uint64_t nblks,
 322  323      dmu_tx_t *tx)
 323  324  {
 324  325          blkptr_t *bp = dn->dn_phys->dn_blkptr;
 325  326          int dnlevel = dn->dn_phys->dn_nlevels;
 326  327          boolean_t trunc = B_FALSE;
 327  328  
 328  329          if (blkid > dn->dn_phys->dn_maxblkid)
 329  330                  return;
 330  331  
 331  332          ASSERT(dn->dn_phys->dn_maxblkid < UINT64_MAX);
↓ open down ↓ 37 lines elided ↑ open up ↑
 369  370                  dn->dn_phys->dn_maxblkid = blkid == 0 ? 0 : blkid - 1;
 370  371  
 371  372                  uint64_t off = (dn->dn_phys->dn_maxblkid + 1) *
 372  373                      (dn->dn_phys->dn_datablkszsec << SPA_MINBLOCKSHIFT);
 373  374                  ASSERT(off < dn->dn_phys->dn_maxblkid ||
 374  375                      dn->dn_phys->dn_maxblkid == 0 ||
 375  376                      dnode_next_offset(dn, 0, &off, 1, 1, 0) != 0);
 376  377          }
 377  378  }
 378  379  
      380 +typedef struct dnode_sync_free_range_arg {
      381 +        dnode_t *dsfra_dnode;
      382 +        dmu_tx_t *dsfra_tx;
      383 +} dnode_sync_free_range_arg_t;
      384 +
      385 +static void
      386 +dnode_sync_free_range(void *arg, uint64_t blkid, uint64_t nblks)
      387 +{
      388 +        dnode_sync_free_range_arg_t *dsfra = arg;
      389 +        dnode_t *dn = dsfra->dsfra_dnode;
      390 +
      391 +        mutex_exit(&dn->dn_mtx);
      392 +        dnode_sync_free_range_impl(dn, blkid, nblks, dsfra->dsfra_tx);
      393 +        mutex_enter(&dn->dn_mtx);
      394 +}
      395 +
 379  396  /*
 380  397   * Try to kick all the dnode's dbufs out of the cache...
 381  398   */
 382  399  void
 383  400  dnode_evict_dbufs(dnode_t *dn)
 384  401  {
 385  402          int progress;
 386  403          int pass = 0;
 387  404  
 388  405          do {
↓ open down ↓ 137 lines elided ↑ open up ↑
 526  543           * be evicted, so we musn't access it.
 527  544           */
 528  545  }
 529  546  
 530  547  /*
 531  548   * Write out the dnode's dirty buffers.
 532  549   */
 533  550  void
 534  551  dnode_sync(dnode_t *dn, dmu_tx_t *tx)
 535  552  {
 536      -        free_range_t *rp;
 537  553          dnode_phys_t *dnp = dn->dn_phys;
 538  554          int txgoff = tx->tx_txg & TXG_MASK;
 539  555          list_t *list = &dn->dn_dirty_records[txgoff];
 540  556          static const dnode_phys_t zerodn = { 0 };
 541  557          boolean_t kill_spill = B_FALSE;
 542  558  
 543  559          ASSERT(dmu_tx_is_syncing(tx));
 544  560          ASSERT(dnp->dn_type != DMU_OT_NONE || dn->dn_allocated_txg);
 545  561          ASSERT(dnp->dn_type != DMU_OT_NONE ||
 546  562              bcmp(dnp, &zerodn, DNODE_SIZE) == 0);
↓ open down ↓ 37 lines elided ↑ open up ↑
 584  600          if (dn->dn_next_type[txgoff] != 0) {
 585  601                  dnp->dn_type = dn->dn_type;
 586  602                  dn->dn_next_type[txgoff] = 0;
 587  603          }
 588  604  
 589  605          if (dn->dn_next_blksz[txgoff] != 0) {
 590  606                  ASSERT(P2PHASE(dn->dn_next_blksz[txgoff],
 591  607                      SPA_MINBLOCKSIZE) == 0);
 592  608                  ASSERT(BP_IS_HOLE(&dnp->dn_blkptr[0]) ||
 593  609                      dn->dn_maxblkid == 0 || list_head(list) != NULL ||
 594      -                    avl_last(&dn->dn_ranges[txgoff]) ||
 595  610                      dn->dn_next_blksz[txgoff] >> SPA_MINBLOCKSHIFT ==
 596      -                    dnp->dn_datablkszsec);
      611 +                    dnp->dn_datablkszsec ||
      612 +                    range_tree_space(dn->dn_free_ranges[txgoff]) != 0);
 597  613                  dnp->dn_datablkszsec =
 598  614                      dn->dn_next_blksz[txgoff] >> SPA_MINBLOCKSHIFT;
 599  615                  dn->dn_next_blksz[txgoff] = 0;
 600  616          }
 601  617  
 602  618          if (dn->dn_next_bonuslen[txgoff] != 0) {
 603  619                  if (dn->dn_next_bonuslen[txgoff] == DN_ZERO_BONUSLEN)
 604  620                          dnp->dn_bonuslen = 0;
 605  621                  else
 606  622                          dnp->dn_bonuslen = dn->dn_next_bonuslen[txgoff];
↓ open down ↓ 38 lines elided ↑ open up ↑
 645  661          mutex_exit(&dn->dn_mtx);
 646  662  
 647  663          if (kill_spill) {
 648  664                  free_blocks(dn, &dn->dn_phys->dn_spill, 1, tx);
 649  665                  mutex_enter(&dn->dn_mtx);
 650  666                  dnp->dn_flags &= ~DNODE_FLAG_SPILL_BLKPTR;
 651  667                  mutex_exit(&dn->dn_mtx);
 652  668          }
 653  669  
 654  670          /* process all the "freed" ranges in the file */
 655      -        while (rp = avl_last(&dn->dn_ranges[txgoff])) {
 656      -                dnode_sync_free_range(dn, rp->fr_blkid, rp->fr_nblks, tx);
 657      -                /* grab the mutex so we don't race with dnode_block_freed() */
      671 +        if (dn->dn_free_ranges[txgoff] != NULL) {
      672 +                dnode_sync_free_range_arg_t dsfra;
      673 +                dsfra.dsfra_dnode = dn;
      674 +                dsfra.dsfra_tx = tx;
 658  675                  mutex_enter(&dn->dn_mtx);
 659      -                avl_remove(&dn->dn_ranges[txgoff], rp);
      676 +                range_tree_vacate(dn->dn_free_ranges[txgoff],
      677 +                    dnode_sync_free_range, &dsfra);
      678 +                range_tree_destroy(dn->dn_free_ranges[txgoff]);
      679 +                dn->dn_free_ranges[txgoff] = NULL;
 660  680                  mutex_exit(&dn->dn_mtx);
 661      -                kmem_free(rp, sizeof (free_range_t));
 662  681          }
 663  682  
 664  683          if (freeing_dnode) {
 665  684                  dnode_sync_free(dn, tx);
 666  685                  return;
 667  686          }
 668  687  
 669  688          if (dn->dn_next_nblkptr[txgoff]) {
 670  689                  /* this should only happen on a realloc */
 671  690                  ASSERT(dn->dn_allocated_txg == tx->tx_txg);
↓ open down ↓ 39 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX