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


 624         zbookmark_phys_t zb;
 625         arc_flags_t aflags = ARC_FLAG_NOWAIT;
 626 
 627         DB_DNODE_ENTER(db);
 628         dn = DB_DNODE(db);
 629         ASSERT(!refcount_is_zero(&db->db_holds));
 630         /* We need the struct_rwlock to prevent db_blkptr from changing. */
 631         ASSERT(RW_LOCK_HELD(&dn->dn_struct_rwlock));
 632         ASSERT(MUTEX_HELD(&db->db_mtx));
 633         ASSERT(db->db_state == DB_UNCACHED);
 634         ASSERT(db->db_buf == NULL);
 635 
 636         if (db->db_blkid == DMU_BONUS_BLKID) {
 637                 int bonuslen = MIN(dn->dn_bonuslen, dn->dn_phys->dn_bonuslen);
 638 
 639                 ASSERT3U(bonuslen, <=, db->db.db_size);
 640                 db->db.db_data = zio_buf_alloc(DN_MAX_BONUSLEN);
 641                 arc_space_consume(DN_MAX_BONUSLEN, ARC_SPACE_OTHER);
 642                 if (bonuslen < DN_MAX_BONUSLEN)
 643                         bzero(db->db.db_data, DN_MAX_BONUSLEN);
 644                 if (bonuslen)
 645                         bcopy(DN_BONUS(dn->dn_phys), db->db.db_data, bonuslen);

















 646                 DB_DNODE_EXIT(db);
 647                 db->db_state = DB_CACHED;
 648                 mutex_exit(&db->db_mtx);
 649                 return;
 650         }
 651 
 652         /*
 653          * Recheck BP_IS_HOLE() after dnode_block_freed() in case dnode_sync()
 654          * processes the delete record and clears the bp while we are waiting
 655          * for the dn_mtx (resulting in a "no" from block_freed).
 656          */
 657         if (db->db_blkptr == NULL || BP_IS_HOLE(db->db_blkptr) ||
 658             (db->db_level == 0 && (dnode_block_freed(dn, db->db_blkid) ||
 659             BP_IS_HOLE(db->db_blkptr)))) {
 660                 arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db);
 661 
 662                 DB_DNODE_EXIT(db);
 663                 dbuf_set_data(db, arc_buf_alloc(db->db_objset->os_spa,
 664                     db->db.db_size, db, type));
 665                 bzero(db->db.db_data, db->db.db_size);




 624         zbookmark_phys_t zb;
 625         arc_flags_t aflags = ARC_FLAG_NOWAIT;
 626 
 627         DB_DNODE_ENTER(db);
 628         dn = DB_DNODE(db);
 629         ASSERT(!refcount_is_zero(&db->db_holds));
 630         /* We need the struct_rwlock to prevent db_blkptr from changing. */
 631         ASSERT(RW_LOCK_HELD(&dn->dn_struct_rwlock));
 632         ASSERT(MUTEX_HELD(&db->db_mtx));
 633         ASSERT(db->db_state == DB_UNCACHED);
 634         ASSERT(db->db_buf == NULL);
 635 
 636         if (db->db_blkid == DMU_BONUS_BLKID) {
 637                 int bonuslen = MIN(dn->dn_bonuslen, dn->dn_phys->dn_bonuslen);
 638 
 639                 ASSERT3U(bonuslen, <=, db->db.db_size);
 640                 db->db.db_data = zio_buf_alloc(DN_MAX_BONUSLEN);
 641                 arc_space_consume(DN_MAX_BONUSLEN, ARC_SPACE_OTHER);
 642                 if (bonuslen < DN_MAX_BONUSLEN)
 643                         bzero(db->db.db_data, DN_MAX_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                 }
 663                 DB_DNODE_EXIT(db);
 664                 db->db_state = DB_CACHED;
 665                 mutex_exit(&db->db_mtx);
 666                 return;
 667         }
 668 
 669         /*
 670          * Recheck BP_IS_HOLE() after dnode_block_freed() in case dnode_sync()
 671          * processes the delete record and clears the bp while we are waiting
 672          * for the dn_mtx (resulting in a "no" from block_freed).
 673          */
 674         if (db->db_blkptr == NULL || BP_IS_HOLE(db->db_blkptr) ||
 675             (db->db_level == 0 && (dnode_block_freed(dn, db->db_blkid) ||
 676             BP_IS_HOLE(db->db_blkptr)))) {
 677                 arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db);
 678 
 679                 DB_DNODE_EXIT(db);
 680                 dbuf_set_data(db, arc_buf_alloc(db->db_objset->os_spa,
 681                     db->db.db_size, db, type));
 682                 bzero(db->db.db_data, db->db.db_size);