| 2427 | } |
| 2428 | |
| 2429 | static void |
| 2430 | dmu_buf_will_dirty_impl(dmu_buf_t *db_fake, int flags, dmu_tx_t *tx) |
| 2431 | { |
| 2432 | dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake; |
| 2433 | |
| 2434 | ASSERT(tx->tx_txg != 0); |
| 2435 | ASSERT(!zfs_refcount_is_zero(&db->db_holds)); |
| 2436 | |
| 2437 | /* |
| 2438 | * Quick check for dirtiness. For already dirty blocks, this |
| 2439 | * reduces runtime of this function by >90%, and overall performance |
| 2440 | * by 50% for some workloads (e.g. file deletion with indirect blocks |
| 2441 | * cached). |
| 2442 | */ |
| 2443 | mutex_enter(&db->db_mtx); |
| 2444 | |
| 2445 | if (db->db_state == DB_CACHED) { |
| 2446 | dbuf_dirty_record_t *dr = dbuf_find_dirty_eq(db, tx->tx_txg); |
| 2447 | /* |
| 2448 | * It's possible that it is already dirty but not cached, |
| 2449 | * because there are some calls to dbuf_dirty() that don't |
| 2450 | * go through dmu_buf_will_dirty(). |
| 2451 | */ |
| 2452 | if (dr != NULL) { |
| 2453 | /* This dbuf is already dirty and cached. */ |
| 2454 | dbuf_redirty(dr); |
| 2455 | mutex_exit(&db->db_mtx); |
| 2456 | return; |
| 2457 | } |
| 2458 | } |
| 2459 | mutex_exit(&db->db_mtx); |
| 2460 | |
| 2461 | DB_DNODE_ENTER(db); |
| 2462 | if (RW_WRITE_HELD(&DB_DNODE(db)->dn_struct_rwlock)) |
| 2463 | flags |= DB_RF_HAVESTRUCT; |
| 2464 | DB_DNODE_EXIT(db); |
| 2465 | (void) dbuf_read(db, NULL, flags); |
| 2466 | (void) dbuf_dirty(db, tx); |
| 2467 | } |
| 2468 | |
| 2469 | void |
| 2470 | dmu_buf_will_dirty(dmu_buf_t *db_fake, dmu_tx_t *tx) |
no test coverage detected