In this scenario, dmu_object_free has been called and this calls dnode_free_range using dnode_free_range(dn, 0, DMU_OBJECT_END, tx)
In this case, in dnode_free_range len is DMU_OBJECT_ENDand offset is 0, so..:
if (len == DMU_OBJECT_END) {
len = UINT64_MAX - off;
trunc = TRUE;
}
makes len is UINT64_MAX and trunc = TRUE. If one follows the code through we have this stanza:
blkid = off >> blkshift;
nblks = len >> blkshift;
if (trunc)
nblks += 1;
and this is the last place nblks gets updated. This implies blkshift is zero, nblks = UINT64_MAX >> 0 is UINT64_MAX, trunc is TRUE so nblks +=1 wraps nblks back to 0, hence the assert later on.
For blkshift to be zero blksz dn->dn_datablksz is zero, so this looks like some form of corruption.
In this scenario, dmu_object_free has been called and this calls dnode_free_range using dnode_free_ range(dn, 0, DMU_OBJECT_END, tx)
In this case, in dnode_free_range len is DMU_OBJECT_ENDand offset is 0, so..:
if (len == DMU_OBJECT_END) {
len = UINT64_MAX - off;
trunc = TRUE;
}
makes len is UINT64_MAX and trunc = TRUE. If one follows the code through we have this stanza:
blkid = off >> blkshift;
nblks = len >> blkshift;
if (trunc)
nblks += 1;
and this is the last place nblks gets updated. This implies blkshift is zero, nblks = UINT64_MAX >> 0 is UINT64_MAX, trunc is TRUE so nblks +=1 wraps nblks back to 0, hence the assert later on.
For blkshift to be zero blksz dn->dn_datablksz is zero, so this looks like some form of corruption.