* dbuf_sync_leaf() is called recursively from dbuf_sync_list() so it is * critical the we not allow the compiler to inline this function in to * dbuf_sync_list() thereby drastically bloating the stack usage. */
| 4197 | * dbuf_sync_list() thereby drastically bloating the stack usage. |
| 4198 | */ |
| 4199 | noinline static void |
| 4200 | dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx) |
| 4201 | { |
| 4202 | arc_buf_t **datap = &dr->dt.dl.dr_data; |
| 4203 | dmu_buf_impl_t *db = dr->dr_dbuf; |
| 4204 | dnode_t *dn = dr->dr_dnode; |
| 4205 | objset_t *os; |
| 4206 | uint64_t txg = tx->tx_txg; |
| 4207 | |
| 4208 | ASSERT(dmu_tx_is_syncing(tx)); |
| 4209 | |
| 4210 | dprintf_dbuf_bp(db, db->db_blkptr, "blkptr=%p", db->db_blkptr); |
| 4211 | |
| 4212 | mutex_enter(&db->db_mtx); |
| 4213 | /* |
| 4214 | * To be synced, we must be dirtied. But we |
| 4215 | * might have been freed after the dirty. |
| 4216 | */ |
| 4217 | if (db->db_state == DB_UNCACHED) { |
| 4218 | /* This buffer has been freed since it was dirtied */ |
| 4219 | ASSERT(db->db.db_data == NULL); |
| 4220 | } else if (db->db_state == DB_FILL) { |
| 4221 | /* This buffer was freed and is now being re-filled */ |
| 4222 | ASSERT(db->db.db_data != dr->dt.dl.dr_data); |
| 4223 | } else { |
| 4224 | ASSERT(db->db_state == DB_CACHED || db->db_state == DB_NOFILL); |
| 4225 | } |
| 4226 | DBUF_VERIFY(db); |
| 4227 | |
| 4228 | if (db->db_blkid == DMU_SPILL_BLKID) { |
| 4229 | mutex_enter(&dn->dn_mtx); |
| 4230 | if (!(dn->dn_phys->dn_flags & DNODE_FLAG_SPILL_BLKPTR)) { |
| 4231 | /* |
| 4232 | * In the previous transaction group, the bonus buffer |
| 4233 | * was entirely used to store the attributes for the |
| 4234 | * dnode which overrode the dn_spill field. However, |
| 4235 | * when adding more attributes to the file a spill |
| 4236 | * block was required to hold the extra attributes. |
| 4237 | * |
| 4238 | * Make sure to clear the garbage left in the dn_spill |
| 4239 | * field from the previous attributes in the bonus |
| 4240 | * buffer. Otherwise, after writing out the spill |
| 4241 | * block to the new allocated dva, it will free |
| 4242 | * the old block pointed to by the invalid dn_spill. |
| 4243 | */ |
| 4244 | db->db_blkptr = NULL; |
| 4245 | } |
| 4246 | dn->dn_phys->dn_flags |= DNODE_FLAG_SPILL_BLKPTR; |
| 4247 | mutex_exit(&dn->dn_mtx); |
| 4248 | } |
| 4249 | |
| 4250 | /* |
| 4251 | * If this is a bonus buffer, simply copy the bonus data into the |
| 4252 | * dnode. It will be written out when the dnode is synced (and it |
| 4253 | * will be synced, since it must have been dirty for dbuf_sync to |
| 4254 | * be called). |
| 4255 | */ |
| 4256 | if (db->db_blkid == DMU_BONUS_BLKID) { |
no test coverage detected