summaryrefslogtreecommitdiff
path: root/tools/perf/scripts/python
diff options
context:
space:
mode:
authorCen Zhang <zzzccc427@gmail.com>2026-10-27 18:14:49 +0800
committerAndrew Morton <akpm@linux-foundation.org>2026-11-02 19:18:57 -0800
commit61469249aab03799b0d3294b7a0cd25dd303017a (patch)
tree281bc253eeda02a056261331ddc30edf50f2e432 /tools/perf/scripts/python
parent723982e7052e65c3b31e8e8c815ffaf2ecfeaa8f (diff)
ocfs2/dlm: serialize migration MLE cleanup on failure
A migration MLE has a base reference for the mastering answer and an in-use reference held by dlm_migrate_lockres(). The finishing assertion consumes the base reference, but migration failure drops it again without checking whether the assertion already consumed it. The target queues its migration worker before it acknowledges the ALL_DONE packet, so its finishing assertion can be handled while the sender still waits for the status. If the connection fails before the status arrives, dlm_send_one_lockres() returns an error for a migration that the target has already completed: Old-master sender Finishing assertion ----------------- ------------------- publish MLE; take in-use reference send ALL_DONE; wait for status take lookup reference unlink MLE put lookup and base references send returns a connection error put base reference again; free MLE put in-use reference; access freed MLE dlm_assert_master_handler() holds dlm->spinlock from the MLE lookup to the final puts, and it takes dlm->master_lock around the unlink and the puts. Decide under the same locks: if the MLE is already unhashed, the assertion consumed the base reference, so drop only the sender's in-use reference. Otherwise unlink it before consuming the base reference so a later assertion no longer finds it. An assertion that got there first has also made the target the owner and cleared DLM_LOCK_RES_MIGRATING. Treating the attempt as failed at that point would leave the lockres owned by the target while this node still holds the other nodes' locks and refmap bits, so it could neither be purged nor migrated again. Finish our side as a completed migration does instead: drop those locks under res->spinlock if the target still owns the lockres, and recalculate its usage. Use the same cleanup for the pre-send failure, the send failure and the target-death failure paths. The sender's in-use reference keeps the MLE alive until its final put outside the nested locks. Successful migration retains its existing in-use-only put. A target that has died cannot assert after the sender has seen its death. The o2net node-down callback runs before the DLM one; it disconnects the node and flushes the workqueue that runs the message handlers, so an assertion already received has been handled by the time the DLM removes the node from the domain map. A node that leaves the domain cleanly sends its exit message only after its assertions have been answered. Two windows of the hand-over itself are left as they are: the handler switches the owner and the sender drops the other nodes' locks moments later, and an assertion from a live target that arrives after the sender has given up still meets the owner check in the handler. Waiting for the target before giving up would only stretch the first window into the time in which recovery of the target can observe it. KASAN report, only the relevant frames are kept: BUG: KASAN: slab-use-after-free in dlm_put_mle_inuse+0xce/0xe0 Read of size 8 at addr ffff8881190e3c20 by task umount/593 Call Trace: <TASK> dlm_put_mle_inuse+0xce/0xe0 dlm_migrate_lockres+0x16af/0x20d0 dlm_empty_lockres+0x60a/0xbd0 dlm_unregister_domain+0x53b/0x11d0 o2cb_cluster_disconnect+0xa5/0x110 ocfs2_cluster_disconnect+0x73/0xc0 ocfs2_dlm_shutdown+0x311/0x440 ocfs2_dismount_volume+0x696/0x940 generic_shutdown_super+0x15f/0x490 kill_block_super+0x40/0xa0 deactivate_locked_super+0xae/0x120 deactivate_super+0xa2/0xc0 cleanup_mnt+0x217/0x450 task_work_run+0x144/0x230 </TASK> Allocated by task 593: kmem_cache_alloc_noprof+0x20b/0x5c0 dlm_migrate_lockres+0x20e/0x20d0 dlm_empty_lockres+0x60a/0xbd0 dlm_unregister_domain+0x53b/0x11d0 o2cb_cluster_disconnect+0xa5/0x110 ocfs2_cluster_disconnect+0x73/0xc0 ocfs2_dlm_shutdown+0x311/0x440 ocfs2_dismount_volume+0x696/0x940 Freed by task 593: kmem_cache_free+0x242/0x580 __dlm_put_mle+0x4b2/0x660 dlm_migrate_lockres+0x1690/0x20d0 dlm_empty_lockres+0x60a/0xbd0 dlm_unregister_domain+0x53b/0x11d0 o2cb_cluster_disconnect+0xa5/0x110 ocfs2_cluster_disconnect+0x73/0xc0 ocfs2_dlm_shutdown+0x311/0x440 The buggy address belongs to the object at ffff8881190e3c00 which belongs to the cache o2dlm_mle of size 480 The buggy address is located 32 bytes inside of freed 480-byte region [ffff8881190e3c00, ffff8881190e3de0) Link: https://lore.kernel.org/pm-ocfs2-objects-candidate-0038-v9-659f247ea980d5f3fbeb@gmail.com Fixes: 6714d8e86bf4 ("[PATCH] OCFS2: The Second Oracle Cluster Filesystem") Signed-off-by: Cen Zhang <zzzccc427@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com> Assisted-by: LLM Cc: Mark Fasheh <mark@fasheh.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Heming Zhao <heming.zhao@suse.com> Cc: Jia-Ju Bai <baijiaju1990@gmail.com> Cc: <jjzuming@gmail.com> Cc: <stable@vger.kernel.org>
Diffstat (limited to 'tools/perf/scripts/python')
0 files changed, 0 insertions, 0 deletions