Merge tag 'v3.10.84' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / mm / rmap.c
index fbf0040a73424b56b35ebaeb66db64135d255630..b79d0b7ade61a755f25bb5438231c8709a762fb8 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
 
 #include "internal.h"
 
+#define MUTEX_RETRY_COUNT (65536)
+#define MUTEX_RETRY_RESCHED (1024)
+
+
+
 static struct kmem_cache *anon_vma_cachep;
 static struct kmem_cache *anon_vma_chain_cachep;
 
@@ -103,7 +108,8 @@ static inline void anon_vma_free(struct anon_vma *anon_vma)
         * LOCK should suffice since the actual taking of the lock must
         * happen _before_ what follows.
         */
-       if (rwsem_is_locked(&anon_vma->root->rwsem)) {
+       might_sleep();
+       if (anon_vma->root && rwsem_is_locked(&anon_vma->root->rwsem)) {
                anon_vma_lock_write(anon_vma);
                anon_vma_unlock_write(anon_vma);
        }
@@ -426,8 +432,9 @@ struct anon_vma *page_get_anon_vma(struct page *page)
         * above cannot corrupt).
         */
        if (!page_mapped(page)) {
+               rcu_read_unlock();
                put_anon_vma(anon_vma);
-               anon_vma = NULL;
+               return NULL;
        }
 out:
        rcu_read_unlock();
@@ -477,9 +484,9 @@ struct anon_vma *page_lock_anon_vma_read(struct page *page)
        }
 
        if (!page_mapped(page)) {
+               rcu_read_unlock();
                put_anon_vma(anon_vma);
-               anon_vma = NULL;
-               goto out;
+               return NULL;
        }
 
        /* we pinned the anon_vma, its safe to sleep */
@@ -812,7 +819,9 @@ static int page_referenced_file(struct page *page,
         */
        BUG_ON(!PageLocked(page));
 
-       mutex_lock(&mapping->i_mmap_mutex);
+       //To avoid deadlock
+       if (!mutex_trylock(&mapping->i_mmap_mutex))
+               return 1; //put in active list
 
        /*
         * i_mmap_mutex does not stabilize mapcount at all, but mapcount
@@ -1526,11 +1535,23 @@ static int try_to_unmap_file(struct page *page, enum ttu_flags flags)
        unsigned long max_nl_cursor = 0;
        unsigned long max_nl_size = 0;
        unsigned int mapcount;
+       int retry = 0;
+
 
        if (PageHuge(page))
                pgoff = page->index << compound_order(page);
 
-       mutex_lock(&mapping->i_mmap_mutex);
+       while (!mutex_trylock(&mapping->i_mmap_mutex)) {
+                retry++;
+                if (!(retry % MUTEX_RETRY_RESCHED))
+                        cond_resched();
+                if (retry > MUTEX_RETRY_COUNT) {
+                        printk(KERN_ERR ">> failed to lock i_mmap_mutex in try_to_unmap_file <<\n");
+                        return SWAP_FAIL;
+                }
+        }
+
+
        vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) {
                unsigned long address = vma_address(page, vma);
                ret = try_to_unmap_one(page, vma, address, flags);
@@ -1675,10 +1696,9 @@ void __put_anon_vma(struct anon_vma *anon_vma)
 {
        struct anon_vma *root = anon_vma->root;
 
-       if (root != anon_vma && atomic_dec_and_test(&root->refcount))
-               anon_vma_free(root);
-
        anon_vma_free(anon_vma);
+       if (root && root != anon_vma && atomic_dec_and_test(&root->refcount))
+               anon_vma_free(root);
 }
 
 #ifdef CONFIG_MIGRATION