sa: fix sa_add_projid lock ordering
sa_add_projid() currently acquires hdl->sa_lock before zp->z_lock. Several same-znode update paths take zp->z_lock and then call sa_update() or sa_bulk_update() on the same SA handle. On Linux, FS_IOC_FSSETXATTR reaches zfs_setattr() through zpl_ioctl_setxattr() without outer inode serialization. This makes the reversed lock order a real ABBA deadlock rather than a lockdep false positive when projid is added to an old-format inode while another thread updates the same znode. Acquire zp->z_lock before hdl->sa_lock in sa_add_projid() to match the existing znode update ordering. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: ZhengYuan Huang <gality369@gmail.com> Co-authored-by: gality369 <gality369@example.com> Closes #18503
This commit is contained in:
+2
-2
@@ -1605,8 +1605,8 @@ sa_add_projid(sa_handle_t *hdl, dmu_tx_t *tx, uint64_t projid)
|
||||
|
||||
bulk = kmem_zalloc(sizeof (sa_bulk_attr_t) * ZPL_END, KM_SLEEP);
|
||||
attrs = kmem_zalloc(sizeof (sa_bulk_attr_t) * ZPL_END, KM_SLEEP);
|
||||
mutex_enter(&hdl->sa_lock);
|
||||
mutex_enter(&zp->z_lock);
|
||||
mutex_enter(&hdl->sa_lock);
|
||||
|
||||
err = sa_lookup_locked(hdl, SA_ZPL_PROJID(zfsvfs), &projid,
|
||||
sizeof (uint64_t));
|
||||
@@ -1750,8 +1750,8 @@ sa_add_projid(sa_handle_t *hdl, dmu_tx_t *tx, uint64_t projid)
|
||||
zp->z_is_sa = B_TRUE;
|
||||
|
||||
out:
|
||||
mutex_exit(&zp->z_lock);
|
||||
mutex_exit(&hdl->sa_lock);
|
||||
mutex_exit(&zp->z_lock);
|
||||
kmem_free(attrs, sizeof (sa_bulk_attr_t) * ZPL_END);
|
||||
kmem_free(bulk, sizeof (sa_bulk_attr_t) * ZPL_END);
|
||||
if (dxattr_obj)
|
||||
|
||||
Reference in New Issue
Block a user