Print this page
3469 dbuf_read_impl shows too much enthusiasm
Reviewed by: Dan McDonald <danmcd@omniti.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dbuf.c
          +++ new/usr/src/uts/common/fs/zfs/dbuf.c
↓ open down ↓ 633 lines elided ↑ open up ↑
 634  634          ASSERT(db->db_buf == NULL);
 635  635  
 636  636          if (db->db_blkid == DMU_BONUS_BLKID) {
 637  637                  int bonuslen = MIN(dn->dn_bonuslen, dn->dn_phys->dn_bonuslen);
 638  638  
 639  639                  ASSERT3U(bonuslen, <=, db->db.db_size);
 640  640                  db->db.db_data = zio_buf_alloc(DN_MAX_BONUSLEN);
 641  641                  arc_space_consume(DN_MAX_BONUSLEN, ARC_SPACE_OTHER);
 642  642                  if (bonuslen < DN_MAX_BONUSLEN)
 643  643                          bzero(db->db.db_data, DN_MAX_BONUSLEN);
 644      -                if (bonuslen)
 645      -                        bcopy(DN_BONUS(dn->dn_phys), db->db.db_data, bonuslen);
      644 +                if (bonuslen) {
      645 +                        /*
      646 +                         * Absent byzantine on-disk corruption, we fully expect
      647 +                         * our bonuslen to be no more than DN_MAX_BONUSLEN --
      648 +                         * but we nonetheless explicitly clamp it on the
      649 +                         * bcopy() to prevent any on-disk corruption from
      650 +                         * becoming rampant in-kernel corruption.
      651 +                         */
      652 +                        if (bonuslen > DN_MAX_BONUSLEN) {
      653 +                                DTRACE_PROBE3(dbuf__read__impl__toolong, int,
      654 +                                    bonuslen, dnode_t *, dn, dmu_buf_impl_t *,
      655 +                                    db);
      656 +                                bcopy(DN_BONUS(dn->dn_phys), db->db.db_data,
      657 +                                    DN_MAX_BONUSLEN);
      658 +                        } else {
      659 +                                bcopy(DN_BONUS(dn->dn_phys), db->db.db_data,
      660 +                                    bonuslen);
      661 +                        }
      662 +                }
 646  663                  DB_DNODE_EXIT(db);
 647  664                  db->db_state = DB_CACHED;
 648  665                  mutex_exit(&db->db_mtx);
 649  666                  return;
 650  667          }
 651  668  
 652  669          /*
 653  670           * Recheck BP_IS_HOLE() after dnode_block_freed() in case dnode_sync()
 654  671           * processes the delete record and clears the bp while we are waiting
 655  672           * for the dn_mtx (resulting in a "no" from block_freed).
↓ open down ↓ 2556 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX