]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Fix ASSERT logic in l2arc_evict()
authorGeorge Amanakis <gamanakis@gmail.com>
Mon, 16 Nov 2020 17:08:11 +0000 (18:08 +0100)
committerGitHub <noreply@github.com>
Mon, 16 Nov 2020 17:08:11 +0000 (09:08 -0800)
In case of cache device removal it is possible that at the end of
l2arc_evict() we have l2ad_hand = l2ad_evict. This can lead to the
following panic in case of a debug build:

VERIFY3(dev->l2ad_hand < dev->l2ad_evict) failed (321920512 < 321920512)
Call Trace:
 dump_stack+0x66/0x90
 spl_panic+0xef/0x117 [spl]
 l2arc_remove_vdev+0x11d/0x290 [zfs]
 spa_load_l2cache+0x275/0x5b0 [zfs]
 spa_vdev_remove+0x4a5/0x6e0 [zfs]
 zfs_ioc_vdev_remove+0x59/0xa0 [zfs]
 zfsdev_ioctl_common+0x5b3/0x630 [zfs]
 zfsdev_ioctl+0x53/0xe0 [zfs]
 do_vfs_ioctl+0x42e/0x6b0
 ksys_ioctl+0x5e/0x90
 do_syscall_64+0x5b/0x1a0
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

In case of cache device removal it also possible that l2ad_hand +
distance > l2ad_end since we do not iterate l2arc_evict() and l2ad_hand
is not reset. This has no functional consequence however as the cache
device is about to be removed.

Fix this by omitting the ASSERT in case of device removal.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: George Amanakis <gamanakis@gmail.com>
Closes #11205

module/zfs/arc.c

index 850e8032fbf6d7bd5350136d7376ef5fe21a1961..42c09e2e585f9270e9754915a4f3dd88fe59c4fc 100644 (file)
@@ -8886,9 +8886,16 @@ out:
                goto top;
        }
 
-       ASSERT3U(dev->l2ad_hand + distance, <, dev->l2ad_end);
-       if (!dev->l2ad_first)
-               ASSERT3U(dev->l2ad_hand, <, dev->l2ad_evict);
+       if (!all) {
+               /*
+                * In case of cache device removal (all) the following
+                * assertions may be violated without functional consequences
+                * as the device is about to be removed.
+                */
+               ASSERT3U(dev->l2ad_hand + distance, <, dev->l2ad_end);
+               if (!dev->l2ad_first)
+                       ASSERT3U(dev->l2ad_hand, <, dev->l2ad_evict);
+       }
 }
 
 /*