From a5d8cdaf169ff183d367f56de69c82be081f54d0 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Mon, 23 May 2016 14:34:11 -0700 Subject: [PATCH] Fix ZAP upgrade deadlock The rw_tryupgrade() implementation the SPL behaves slightly differently than the illumos version. Specifically, the Linux kernel provides no upgrade function so the lock must be released before attempting the upgrade. For many use cases this isn't a problem but when upgrading a ZAP it can result in a deadlock with the l_rwlock. This minor optimization is disabled under Linux to prevent this issue. Signed-off-by: Brian Behlendorf --- module/zfs/zap.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/module/zfs/zap.c b/module/zfs/zap.c index 454b4be62ed3..005b5d7c5609 100644 --- a/module/zfs/zap.c +++ b/module/zfs/zap.c @@ -129,10 +129,20 @@ zap_tryupgradedir(zap_t *zap, dmu_tx_t *tx) { if (RW_WRITE_HELD(&zap->zap_rwlock)) return (1); + +#ifndef __linux__ + /* + * Unsafe under Linux because the rw_tryupgrade() implementation must + * release the lock before attempting to upgrade. This can result in + * a lock inversion with the l_rwlock unless the leaf lock is dropped + * first and reaquired. Rather than restruct this code disable this + * minor optimization under Linux. + */ if (rw_tryupgrade(&zap->zap_rwlock)) { dmu_buf_will_dirty(zap->zap_dbuf, tx); return (1); } +#endif return (0); }