summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/dmu.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/module/zfs/dmu.c b/module/zfs/dmu.c
index 162177284..3d8423af3 100644
--- a/module/zfs/dmu.c
+++ b/module/zfs/dmu.c
@@ -2366,14 +2366,39 @@ dmu_offset_next(objset_t *os, uint64_t object, boolean_t hole, uint64_t *off)
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++) {
if (multilist_link_active(&dn->dn_dirty_link[i])) {
- clean = B_FALSE;
- break;
+
+ 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;
+ break;
+ }
}
+
+ if (clean == B_FALSE)
+ break;
}
+ mutex_exit(&dn->dn_mtx);
/*
* If compatibility option is on, sync any current changes before