All mlock related syscalls prepare lock limits, lengths and
start parameters with the mmap_sem held. Move this logic
outside of the critical region. For the case of mlock, continue
incrementing the amount already locked by mm->locked_vm with
the rwsem taken.

Signed-off-by: Davidlohr Bueso <davidl...@hp.com>
Cc: Michel Lespinasse <wal...@google.com>
Cc: Vlastimil Babka <vba...@suse.cz>
---
 mm/mlock.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/mm/mlock.c b/mm/mlock.c
index d480cd6..aa7de13 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -689,19 +689,21 @@ SYSCALL_DEFINE2(mlock, unsigned long, start, size_t, len)
 
        lru_add_drain_all();    /* flush pagevec */
 
-       down_write(&current->mm->mmap_sem);
        len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
        start &= PAGE_MASK;
 
-       locked = len >> PAGE_SHIFT;
-       locked += current->mm->locked_vm;
-
        lock_limit = rlimit(RLIMIT_MEMLOCK);
        lock_limit >>= PAGE_SHIFT;
+       locked = len >> PAGE_SHIFT;
+
+       down_write(&current->mm->mmap_sem);
+
+       locked += current->mm->locked_vm;
 
        /* check against resource limits */
        if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
                error = do_mlock(start, len, 1);
+
        up_write(&current->mm->mmap_sem);
        if (!error)
                error = __mm_populate(start, len, 0);
@@ -712,11 +714,13 @@ SYSCALL_DEFINE2(munlock, unsigned long, start, size_t, 
len)
 {
        int ret;
 
-       down_write(&current->mm->mmap_sem);
        len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
        start &= PAGE_MASK;
+
+       down_write(&current->mm->mmap_sem);
        ret = do_mlock(start, len, 0);
        up_write(&current->mm->mmap_sem);
+
        return ret;
 }
 
@@ -761,12 +765,12 @@ SYSCALL_DEFINE1(mlockall, int, flags)
        if (flags & MCL_CURRENT)
                lru_add_drain_all();    /* flush pagevec */
 
-       down_write(&current->mm->mmap_sem);
-
        lock_limit = rlimit(RLIMIT_MEMLOCK);
        lock_limit >>= PAGE_SHIFT;
 
        ret = -ENOMEM;
+       down_write(&current->mm->mmap_sem);
+
        if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
            capable(CAP_IPC_LOCK))
                ret = do_mlockall(flags);
-- 
1.8.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to