Print this page
5814 bpobj_iterate_impl(): Close a refcount leak iterating on a sublist.
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Paul Dagnelie <paul.dagnelie@delphix.com>
Reviewed by: Simon Klinkert <simon.klinkert@gmail.com>
Approved by: Gordon Ross <gwr@nexenta.com>
5812 assertion failed in zrl_tryenter(): zr_owner==NULL
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: Will Andrews <will@freebsd.org>
Approved by: Gordon Ross <gwr@nexenta.com>
5810 zdb should print details of bpobj
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Will Andrews <will@freebsd.org>
Reviewed by: Simon Klinkert <simon.klinkert@gmail.com>
Approved by: Gordon Ross <gwr@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/bpobj.c
          +++ new/usr/src/uts/common/fs/zfs/bpobj.c
↓ open down ↓ 168 lines elided ↑ open up ↑
 169  169  
 170  170          bpo->bpo_os = os;
 171  171          bpo->bpo_object = object;
 172  172          bpo->bpo_epb = doi.doi_data_block_size >> SPA_BLKPTRSHIFT;
 173  173          bpo->bpo_havecomp = (doi.doi_bonus_size > BPOBJ_SIZE_V0);
 174  174          bpo->bpo_havesubobj = (doi.doi_bonus_size > BPOBJ_SIZE_V1);
 175  175          bpo->bpo_phys = bpo->bpo_dbuf->db_data;
 176  176          return (0);
 177  177  }
 178  178  
 179      -boolean_t
 180      -bpobj_is_open(const bpobj_t *bpo)
 181      -{
 182      -        return (bpo->bpo_object != 0);
 183      -}
 184      -
 185  179  void
 186  180  bpobj_close(bpobj_t *bpo)
 187  181  {
 188  182          /* Lame workaround for closing a bpobj that was never opened. */
 189  183          if (bpo->bpo_object == 0)
 190  184                  return;
 191  185  
 192  186          dmu_buf_rele(bpo->bpo_dbuf, bpo);
 193  187          if (bpo->bpo_cached_dbuf != NULL)
 194  188                  dmu_buf_rele(bpo->bpo_cached_dbuf, bpo);
 195  189          bpo->bpo_dbuf = NULL;
 196  190          bpo->bpo_phys = NULL;
 197  191          bpo->bpo_cached_dbuf = NULL;
 198  192          bpo->bpo_object = 0;
 199  193  
 200  194          mutex_destroy(&bpo->bpo_lock);
 201  195  }
 202  196  
 203      -boolean_t
 204      -bpobj_is_empty(bpobj_t *bpo)
      197 +static boolean_t
      198 +bpobj_hasentries(bpobj_t *bpo)
 205  199  {
 206      -        return (bpo->bpo_phys->bpo_num_blkptrs == 0 &&
 207      -            (!bpo->bpo_havesubobj || bpo->bpo_phys->bpo_num_subobjs == 0));
      200 +        return (bpo->bpo_phys->bpo_num_blkptrs != 0 ||
      201 +            (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_num_subobjs != 0));
 208  202  }
 209  203  
 210  204  static int
 211  205  bpobj_iterate_impl(bpobj_t *bpo, bpobj_itor_t func, void *arg, dmu_tx_t *tx,
 212  206      boolean_t free)
 213  207  {
 214  208          dmu_object_info_t doi;
 215  209          int epb;
 216  210          int64_t i;
 217  211          int err = 0;
 218  212          dmu_buf_t *dbuf = NULL;
 219  213  
 220      -        ASSERT(bpobj_is_open(bpo));
 221  214          mutex_enter(&bpo->bpo_lock);
 222  215  
      216 +        if (!bpobj_hasentries(bpo))
      217 +                goto out;
      218 +
 223  219          if (free)
 224  220                  dmu_buf_will_dirty(bpo->bpo_dbuf, tx);
 225  221  
 226  222          for (i = bpo->bpo_phys->bpo_num_blkptrs - 1; i >= 0; i--) {
 227  223                  blkptr_t *bparray;
 228  224                  blkptr_t *bp;
 229  225                  uint64_t offset, blkoff;
 230  226  
 231  227                  offset = i * sizeof (blkptr_t);
 232  228                  blkoff = P2PHASE(i, bpo->bpo_epb);
↓ open down ↓ 109 lines elided ↑ open up ↑
 342  338                  dbuf = NULL;
 343  339          }
 344  340          if (free) {
 345  341                  VERIFY3U(0, ==, dmu_free_range(bpo->bpo_os,
 346  342                      bpo->bpo_phys->bpo_subobjs,
 347  343                      (i + 1) * sizeof (uint64_t), -1ULL, tx));
 348  344          }
 349  345  
 350  346  out:
 351  347          /* If there are no entries, there should be no bytes. */
 352      -        if (bpobj_is_empty(bpo)) {
      348 +        if (!bpobj_hasentries(bpo)) {
 353  349                  ASSERT0(bpo->bpo_phys->bpo_bytes);
 354  350                  ASSERT0(bpo->bpo_phys->bpo_comp);
 355  351                  ASSERT0(bpo->bpo_phys->bpo_uncomp);
 356  352          }
 357  353  
 358  354          mutex_exit(&bpo->bpo_lock);
 359  355          return (err);
 360  356  }
 361  357  
 362  358  /*
↓ open down ↓ 14 lines elided ↑ open up ↑
 377  373  {
 378  374          return (bpobj_iterate_impl(bpo, func, arg, tx, B_FALSE));
 379  375  }
 380  376  
 381  377  void
 382  378  bpobj_enqueue_subobj(bpobj_t *bpo, uint64_t subobj, dmu_tx_t *tx)
 383  379  {
 384  380          bpobj_t subbpo;
 385  381          uint64_t used, comp, uncomp, subsubobjs;
 386  382  
 387      -        ASSERT(bpobj_is_open(bpo));
 388      -        ASSERT(subobj != 0);
 389  383          ASSERT(bpo->bpo_havesubobj);
 390  384          ASSERT(bpo->bpo_havecomp);
 391  385          ASSERT(bpo->bpo_object != dmu_objset_pool(bpo->bpo_os)->dp_empty_bpobj);
 392  386  
 393  387          if (subobj == dmu_objset_pool(bpo->bpo_os)->dp_empty_bpobj) {
 394  388                  bpobj_decr_empty(bpo->bpo_os, tx);
 395  389                  return;
 396  390          }
 397  391  
 398  392          VERIFY3U(0, ==, bpobj_open(&subbpo, bpo->bpo_os, subobj));
 399  393          VERIFY3U(0, ==, bpobj_space(&subbpo, &used, &comp, &uncomp));
 400  394  
 401      -        if (bpobj_is_empty(&subbpo)) {
      395 +        if (!bpobj_hasentries(&subbpo)) {
 402  396                  /* No point in having an empty subobj. */
 403  397                  bpobj_close(&subbpo);
 404  398                  bpobj_free(bpo->bpo_os, subobj, tx);
 405  399                  return;
 406  400          }
 407  401  
 408  402          mutex_enter(&bpo->bpo_lock);
 409  403          dmu_buf_will_dirty(bpo->bpo_dbuf, tx);
 410  404          if (bpo->bpo_phys->bpo_subobjs == 0) {
 411  405                  bpo->bpo_phys->bpo_subobjs = dmu_object_alloc(bpo->bpo_os,
↓ open down ↓ 53 lines elided ↑ open up ↑
 465  459  }
 466  460  
 467  461  void
 468  462  bpobj_enqueue(bpobj_t *bpo, const blkptr_t *bp, dmu_tx_t *tx)
 469  463  {
 470  464          blkptr_t stored_bp = *bp;
 471  465          uint64_t offset;
 472  466          int blkoff;
 473  467          blkptr_t *bparray;
 474  468  
 475      -        ASSERT(bpobj_is_open(bpo));
 476  469          ASSERT(!BP_IS_HOLE(bp));
 477  470          ASSERT(bpo->bpo_object != dmu_objset_pool(bpo->bpo_os)->dp_empty_bpobj);
 478  471  
 479  472          if (BP_IS_EMBEDDED(bp)) {
 480  473                  /*
 481  474                   * The bpobj will compress better without the payload.
 482  475                   *
 483  476                   * Note that we store EMBEDDED bp's because they have an
 484  477                   * uncompressed size, which must be accounted for.  An
 485  478                   * alternative would be to add their size to bpo_uncomp
↓ open down ↓ 65 lines elided ↑ open up ↑
 551  544                          sra->used += bp_get_dsize(sra->spa, bp);
 552  545                  sra->comp += BP_GET_PSIZE(bp);
 553  546                  sra->uncomp += BP_GET_UCSIZE(bp);
 554  547          }
 555  548          return (0);
 556  549  }
 557  550  
 558  551  int
 559  552  bpobj_space(bpobj_t *bpo, uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
 560  553  {
 561      -        ASSERT(bpobj_is_open(bpo));
 562  554          mutex_enter(&bpo->bpo_lock);
 563  555  
 564  556          *usedp = bpo->bpo_phys->bpo_bytes;
 565  557          if (bpo->bpo_havecomp) {
 566  558                  *compp = bpo->bpo_phys->bpo_comp;
 567  559                  *uncompp = bpo->bpo_phys->bpo_uncomp;
 568  560                  mutex_exit(&bpo->bpo_lock);
 569  561                  return (0);
 570  562          } else {
 571  563                  mutex_exit(&bpo->bpo_lock);
↓ open down ↓ 6 lines elided ↑ open up ↑
 578  570   * Return the amount of space in the bpobj which is:
 579  571   * mintxg < blk_birth <= maxtxg
 580  572   */
 581  573  int
 582  574  bpobj_space_range(bpobj_t *bpo, uint64_t mintxg, uint64_t maxtxg,
 583  575      uint64_t *usedp, uint64_t *compp, uint64_t *uncompp)
 584  576  {
 585  577          struct space_range_arg sra = { 0 };
 586  578          int err;
 587  579  
 588      -        ASSERT(bpobj_is_open(bpo));
 589      -
 590  580          /*
 591  581           * As an optimization, if they want the whole txg range, just
 592  582           * get bpo_bytes rather than iterating over the bps.
 593  583           */
 594  584          if (mintxg < TXG_INITIAL && maxtxg == UINT64_MAX && bpo->bpo_havecomp)
 595  585                  return (bpobj_space(bpo, usedp, compp, uncompp));
 596  586  
 597  587          sra.spa = dmu_objset_spa(bpo->bpo_os);
 598  588          sra.mintxg = mintxg;
 599  589          sra.maxtxg = maxtxg;
 600  590  
 601  591          err = bpobj_iterate_nofree(bpo, space_range_cb, &sra, NULL);
 602  592          *usedp = sra.used;
 603  593          *compp = sra.comp;
 604  594          *uncompp = sra.uncomp;
 605  595          return (err);
 606  596  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX