Skip to content

Commit

Permalink
Revert "Use SA_HDL_PRIVATE for SA xattrs"
Browse files Browse the repository at this point in the history
This reverts commit ec2626a which
caused consistency problems between the shared and private handles.
Reverting this change should resolve issues #709 and #727.  It
will also reintroduce an arc_anon memory leak which is addressed
by the next commit.

Signed-off-by: Brian Behlendorf <[email protected]>
Closes #709
Closes #727
  • Loading branch information
behlendorf committed Aug 25, 2012
1 parent 15a9e03 commit f828e63
Showing 1 changed file with 5 additions and 28 deletions.
33 changes: 5 additions & 28 deletions module/zfs/zfs_sa.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ int
zfs_sa_get_xattr(znode_t *zp)
{
zfs_sb_t *zsb = ZTOZSB(zp);
sa_handle_t *sa;
char *obj;
int size;
int error;
Expand All @@ -197,14 +196,8 @@ zfs_sa_get_xattr(znode_t *zp)
ASSERT(!zp->z_xattr_cached);
ASSERT(zp->z_is_sa);

error = sa_handle_get(zsb->z_os, zp->z_id, NULL, SA_HDL_PRIVATE, &sa);
if (error)
return (error);

error = sa_size(sa, SA_ZPL_DXATTR(zsb), &size);
error = sa_size(zp->z_sa_hdl, SA_ZPL_DXATTR(zsb), &size);
if (error) {
sa_handle_destroy(sa);

if (error == ENOENT)
return nvlist_alloc(&zp->z_xattr_cached,
NV_UNIQUE_NAME, KM_SLEEP);
Expand All @@ -214,12 +207,11 @@ zfs_sa_get_xattr(znode_t *zp)

obj = sa_spill_alloc(KM_SLEEP);

error = sa_lookup(sa, SA_ZPL_DXATTR(zsb), obj, size);
error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DXATTR(zsb), obj, size);
if (error == 0)
error = nvlist_unpack(obj, size, &zp->z_xattr_cached, KM_SLEEP);

sa_spill_free(obj);
sa_handle_destroy(sa);

return (error);
}
Expand All @@ -228,7 +220,6 @@ int
zfs_sa_set_xattr(znode_t *zp)
{
zfs_sb_t *zsb = ZTOZSB(zp);
sa_handle_t *sa;
dmu_tx_t *tx;
char *obj;
size_t size;
Expand All @@ -249,30 +240,16 @@ zfs_sa_set_xattr(znode_t *zp)
if (error)
goto out_free;

/*
* A private SA handle must be used to ensure we can drop the hold
* on the spill block prior to calling dmu_tx_commit(). If we call
* dmu_tx_commit() before sa_handle_destroy(), then our hold will
* trigger a copy of the buffer at txg sync time. This is done to
* prevent data from leaking in to the syncing txg. As a result
* the original dirty spill block will be remain dirty in the arc
* while the copy is written and laundered.
*/
error = sa_handle_get(zsb->z_os, zp->z_id, NULL, SA_HDL_PRIVATE, &sa);
if (error)
goto out_free;

tx = dmu_tx_create(zsb->z_os);
dmu_tx_hold_sa_create(tx, size);
dmu_tx_hold_sa(tx, sa, B_TRUE);
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE);

error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
sa_handle_destroy(sa);
} else {
error = sa_update(sa, SA_ZPL_DXATTR(zsb), obj, size, tx);
sa_handle_destroy(sa);
error = sa_update(zp->z_sa_hdl, SA_ZPL_DXATTR(zsb),
obj, size, tx);
if (error)
dmu_tx_abort(tx);
else
Expand Down

0 comments on commit f828e63

Please sign in to comment.