Skip to content

Commit

Permalink
Undirty removed spill blocks.
Browse files Browse the repository at this point in the history
If a spill block's dbuf hasn't yet been written when a the spill block
is removed, the unwritten version will still be written.  This patch
undirties the dbuf in this case to prevent it to be written.

The most common case in which this could happen is when xattr=sa is being
used and a long xattr is immediately replaced by a short xattr as in:

	setfattr -n user.test -v very_very_very..._long_value  <file>
	setfattr -n user.test -v short_value  <file>

The first value must be sufficiently long that a spill block is generated
and the second value must be short enough to not require a spill block.
In practice, this would typically happen due to internal xattr operations
as a result of setting acltype=posixacl.
  • Loading branch information
dweeezil committed Nov 11, 2014
1 parent 11662bf commit 1cd65a2
Showing 1 changed file with 15 additions and 0 deletions.
15 changes: 15 additions & 0 deletions module/zfs/dbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,21 @@ dbuf_free_range(dnode_t *dn, uint64_t start, uint64_t end, dmu_tx_t *tx)

mutex_enter(&dn->dn_dbufs_mtx);
if (start >= dn->dn_unlisted_l0_blkid * dn->dn_datablksz) {
/*
* Don't re-write a spill block when it's being removed.
*/
if (start == DMU_SPILL_BLKID && end == DMU_SPILL_BLKID) {
dmu_buf_impl_t *xdb, *xdb_next;

for (xdb = list_head(&dn->dn_dbufs); xdb != NULL; xdb = xdb_next) {
xdb_next = list_next(&dn->dn_dbufs, xdb);
if (xdb->db_blkid == DMU_SPILL_BLKID) {
(void) dbuf_undirty(xdb, tx);
break;
}
}
}

/* There can't be any dbufs in this range; no need to search. */
mutex_exit(&dn->dn_dbufs_mtx);
return;
Expand Down

0 comments on commit 1cd65a2

Please sign in to comment.