ryao 12/06/25 00:50:51
Added: zfs-0.6.0_rc9-range-lock-caller-allocate.patch
Log:
Fix swap deadlock involving zfs_range_lock() and zvols
(Portage version: 2.1.10.49/cvs/Linux x86_64)
Revision Changes Path
1.1 sys-fs/zfs/files/zfs-0.6.0_rc9-range-lock-caller-allocate.patch
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/zfs/files/zfs-0.6.0_rc9-range-lock-caller-allocate.patch?rev=1.1&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-fs/zfs/files/zfs-0.6.0_rc9-range-lock-caller-allocate.patch?rev=1.1&content-type=text/plain
Index: zfs-0.6.0_rc9-range-lock-caller-allocate.patch
===================================================================
commit 59c247716c71837b0071fb933f731e7b82c98dd8
Author: Gunnar Beutner <gunnar@...>
Date: Mon Jun 18 11:44:34 2012 -0400
Fix znode corruption when using xattr=sa.
Using a separate SA handle (rather than zp->z_sa_hdl) to update
attributes corrupts the znode's mode flags (and possibly other
attributes as well).
This patch changes the zfs_sa_get_xattr/zfs_sa_set_xattr functions
so that they use zp->z_sa_hdl.
Signed-off-by: Richard Yao <ryao@...>
diff --git a/module/zfs/zfs_sa.c b/module/zfs/zfs_sa.c
index f35f6f6..7f14706 100644
--- a/module/zfs/zfs_sa.c
+++ b/module/zfs/zfs_sa.c
@@ -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;
@@ -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);
@@ -212,14 +205,13 @@ zfs_sa_get_xattr(znode_t *zp)
return (error);
}
- obj = sa_spill_alloc(KM_SLEEP);
+ obj = kmem_alloc(size, 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);
+ kmem_free(obj, size);
return (error);
}
@@ -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;
@@ -242,44 +233,27 @@ zfs_sa_set_xattr(znode_t *zp)
if (error)
goto out;
- obj = sa_spill_alloc(KM_SLEEP);
+ obj = kmem_alloc(size, KM_SLEEP);
error = nvlist_pack(zp->z_xattr_cached, &obj, &size,
NV_ENCODE_XDR, KM_SLEEP);
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;
+ goto out;
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);
- if (error)
- dmu_tx_abort(tx);
- else
- dmu_tx_commit(tx);
+ VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_DXATTR(zsb), obj,
+ size, tx));
+ dmu_tx_commit(tx);
}
-out_free:
- sa_spill_free(obj);
+
+ kmem_free(obj, size);
out:
return (error);
}
|