At some point in the past, the call to get_user_pages() was changed to
get_user_pages_fast(). The former requires that mmap_sem be held when
making the call, which the driver respected. But the latter requires that
mmap_sem not be held, since it acquires it later. So mmap_sem was being
acquired by the driver, then again in get_user_pages_fast(). In between
these two acquisitions, another thread can come along and call mmap(),
which will wait on the same semaphore, and deadlock with the subsequent
get_user_pages_fast() attempt to get it again.
Thread 1 Thread 2
-------- --------
acquire mmap_sem .
call get_user_pages_fast() .
. mmap()
. acquire mmap_sem (blocks)
acquire mmap_sem (blocks)
Since get_user_pages_fast() acquires mmap_sem, the dax driver should
not do so.
Orabug:
26103487
Signed-off-by: Rob Gardner <rob.gardner@oracle.com>
Reviewed-by: Sanath Kumar <sanath.s.kumar@oracle.com>
Reviewed-by: Eric Saint-Etienne <eric.saint.etienne@oracle.com>
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
dax_dbg("virtp=0x%lx backed by huge page. No need to lock",
virtp);
} else {
- down_read(¤t->mm->mmap_sem);
ret = get_user_pages_fast(virtp, 1, 1, &page);
- up_read(¤t->mm->mmap_sem);
if (ret == 1) {
dax_ctx->pages[at][idx] = page;