mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-25 02:49:32 +03:00
dbuf_free_range() overzealously frees dbufs
When called to free a spill block from a dnode, dbuf_free_range() has a bug that results in all dbufs for the dnode getting freed. A variety of problems may result from this bug, but a common one was a zap lookup tripping an ASSERT because the zap buffers had been zeroed out. This could happen on a dataset with xattr=sa set when extended attributes are written and removed on a directory concurrently with I/O to files in that directory. Signed-off-by: Ned Bass <bass6@llnl.gov> Signed-off-by: Tim Chase <tim@chase2k.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Fixes #3195 Fixes #3204 Fixes #3222
This commit is contained in:
parent
ded576e28f
commit
58806b4cdc
@ -898,9 +898,14 @@ dbuf_free_range(dnode_t *dn, uint64_t start, uint64_t end, dmu_tx_t *tx)
|
||||
db_next = list_next(&dn->dn_dbufs, db);
|
||||
ASSERT(db->db_blkid != DMU_BONUS_BLKID);
|
||||
|
||||
/* Skip indirect blocks. */
|
||||
if (db->db_level != 0)
|
||||
continue;
|
||||
if ((db->db_blkid < start || db->db_blkid > end) && !freespill)
|
||||
/* Skip direct blocks outside the range. */
|
||||
if (!freespill && (db->db_blkid < start || db->db_blkid > end))
|
||||
continue;
|
||||
/* Skip all direct blocks, only free spill blocks. */
|
||||
if (freespill && (db->db_blkid != DMU_SPILL_BLKID))
|
||||
continue;
|
||||
|
||||
/* found a level 0 buffer in the range */
|
||||
|
Loading…
Reference in New Issue
Block a user