Print this page
6267 dn_bonus evicted too early
Reviewed by: Richard Yao <ryao@gentoo.org>
Reviewed by: Xin LI <delphij@freebsd.org>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Richard Lowe <richlowe@richlowe.net>

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 ↓ 416 lines elided ↑ open up ↑
 417  417                          db_marker.db_blkid = db->db_blkid;
 418  418                          db_marker.db_state = DB_SEARCH;
 419  419                          avl_insert_here(&dn->dn_dbufs, &db_marker, db,
 420  420                              AVL_BEFORE);
 421  421  
 422  422                          dbuf_clear(db);
 423  423  
 424  424                          db_next = AVL_NEXT(&dn->dn_dbufs, &db_marker);
 425  425                          avl_remove(&dn->dn_dbufs, &db_marker);
 426  426                  } else {
      427 +                        db->db_pending_evict = TRUE;
 427  428                          mutex_exit(&db->db_mtx);
 428  429                          db_next = AVL_NEXT(&dn->dn_dbufs, db);
 429  430                  }
 430  431          }
 431  432          mutex_exit(&dn->dn_dbufs_mtx);
 432  433  
 433  434          dnode_evict_bonus(dn);
 434  435  }
 435  436  
 436  437  void
 437  438  dnode_evict_bonus(dnode_t *dn)
 438  439  {
 439  440          rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
 440      -        if (dn->dn_bonus && refcount_is_zero(&dn->dn_bonus->db_holds)) {
 441      -                mutex_enter(&dn->dn_bonus->db_mtx);
 442      -                dbuf_evict(dn->dn_bonus);
 443      -                dn->dn_bonus = NULL;
      441 +        if (dn->dn_bonus != NULL) {
      442 +                if (refcount_is_zero(&dn->dn_bonus->db_holds)) {
      443 +                        mutex_enter(&dn->dn_bonus->db_mtx);
      444 +                        dbuf_evict(dn->dn_bonus);
      445 +                        dn->dn_bonus = NULL;
      446 +                } else {
      447 +                        dn->dn_bonus->db_pending_evict = TRUE;
      448 +                }
 444  449          }
 445  450          rw_exit(&dn->dn_struct_rwlock);
 446  451  }
 447  452  
 448  453  static void
 449  454  dnode_undirty_dbufs(list_t *list)
 450  455  {
 451  456          dbuf_dirty_record_t *dr;
 452  457  
 453  458          while (dr = list_head(list)) {
↓ open down ↓ 31 lines elided ↑ open up ↑
 485  490  
 486  491          /*
 487  492           * Our contents should have been freed in dnode_sync() by the
 488  493           * free range record inserted by the caller of dnode_free().
 489  494           */
 490  495          ASSERT0(DN_USED_BYTES(dn->dn_phys));
 491  496          ASSERT(BP_IS_HOLE(dn->dn_phys->dn_blkptr));
 492  497  
 493  498          dnode_undirty_dbufs(&dn->dn_dirty_records[txgoff]);
 494  499          dnode_evict_dbufs(dn);
 495      -        ASSERT(avl_is_empty(&dn->dn_dbufs));
 496  500  
 497  501          /*
 498  502           * XXX - It would be nice to assert this, but we may still
 499  503           * have residual holds from async evictions from the arc...
 500  504           *
 501  505           * zfs_obj_to_path() also depends on this being
 502  506           * commented out.
 503  507           *
 504  508           * ASSERT3U(refcount_count(&dn->dn_holds), ==, 1);
 505  509           */
↓ open down ↓ 217 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX