From 36686e99e6e09c4043c34cf0c44f84f1e52f7ac9 Mon Sep 17 00:00:00 2001 From: Haren Myneni Date: Thu, 22 Jun 2023 00:42:46 -0700 Subject: [PATCH] powerpc/pseries/vas: Hold mmap_mutex after mmap lock during window close VAS mmap (coproc_mmap()) and its fault handler (vas_mmap_fault()) are called after holding mmap lock and acquire mmap_mutex to update VAS window status. The migration / DLPAR window close can hang while trying to acquire mmap lock if it is issued at the same time with the user space ioctl mmap or VAS fault handler execution. So this patch adds changes to acquire mmap lock before holding mmap_mutex. Fixes: 8ef7b9e1765a ("powerpc/pseries/vas: Close windows with DLPAR core removal") Signed-off-by: Haren Myneni Signed-off-by: Michael Ellerman Link: https://msgid.link/20230622074246.144729-1-haren@linux.ibm.com --- arch/powerpc/platforms/pseries/vas.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c index 9a44a98ba3420..3fbc2a6aa319d 100644 --- a/arch/powerpc/platforms/pseries/vas.c +++ b/arch/powerpc/platforms/pseries/vas.c @@ -744,6 +744,12 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds, } task_ref = &win->vas_win.task_ref; + /* + * VAS mmap (coproc_mmap()) and its fault handler + * (vas_mmap_fault()) are called after holding mmap lock. + * So hold mmap mutex after mmap_lock to avoid deadlock. + */ + mmap_write_lock(task_ref->mm); mutex_lock(&task_ref->mmap_mutex); vma = task_ref->vma; /* @@ -752,7 +758,6 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds, */ win->vas_win.status |= flag; - mmap_write_lock(task_ref->mm); /* * vma is set in the original mapping. But this mapping * is done with mmap() after the window is opened with ioctl. @@ -762,8 +767,8 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds, if (vma) zap_vma_pages(vma); - mmap_write_unlock(task_ref->mm); mutex_unlock(&task_ref->mmap_mutex); + mmap_write_unlock(task_ref->mm); /* * Close VAS window in the hypervisor, but do not * free vas_window struct since it may be reused