Report holes when there are only metadata changes

Update the dirty check in dmu_offset_next() such that dnode's
are only considered dirty for the purpose or reporting holes
when there are pending data blocks or frees to be synced.  This
ensures that when there are only metadata updates to be synced
(atime) that holes are reported.

Reviewed-by: Debabrata Banerjee <dbanerje@akamai.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #6958 
Closes #8505
This commit is contained in:
Brian Behlendorf 2019-03-21 10:30:15 -07:00 committed by GitHub
parent 066da71e7f
commit ec4f9b8f30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 28 additions and 3 deletions

View File

@ -2366,15 +2366,40 @@ dmu_offset_next(objset_t *os, uint64_t object, boolean_t hole, uint64_t *off)
return (err); return (err);
/* /*
* Check if dnode is dirty * Check if there are dirty data blocks or frees which have not been
* synced. Dirty spill and bonus blocks which are external to the
* object can ignored when reporting holes.
*/ */
mutex_enter(&dn->dn_mtx);
for (i = 0; i < TXG_SIZE; i++) { for (i = 0; i < TXG_SIZE; i++) {
if (multilist_link_active(&dn->dn_dirty_link[i])) { if (multilist_link_active(&dn->dn_dirty_link[i])) {
if (dn->dn_free_ranges[i] != NULL) {
clean = B_FALSE;
break;
}
list_t *list = &dn->dn_dirty_records[i];
dbuf_dirty_record_t *dr;
for (dr = list_head(list); dr != NULL;
dr = list_next(list, dr)) {
dmu_buf_impl_t *db = dr->dr_dbuf;
if (db->db_blkid == DMU_SPILL_BLKID ||
db->db_blkid == DMU_BONUS_BLKID)
continue;
clean = B_FALSE; clean = B_FALSE;
break; break;
} }
} }
if (clean == B_FALSE)
break;
}
mutex_exit(&dn->dn_mtx);
/* /*
* If compatibility option is on, sync any current changes before * If compatibility option is on, sync any current changes before
* we go trundling through the block pointers. * we go trundling through the block pointers.