media: dw9807-vcm: Smooth the first user movement of the lens
[platform/kernel/linux-rpi.git] / mm / shmem.c
index b5860f4..342d1bc 100644 (file)
@@ -555,7 +555,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
        struct shmem_inode_info *info;
        struct page *page;
        unsigned long batch = sc ? sc->nr_to_scan : 128;
-       int removed = 0, split = 0;
+       int split = 0;
 
        if (list_empty(&sbinfo->shrinklist))
                return SHRINK_STOP;
@@ -570,7 +570,6 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
                /* inode is about to be evicted */
                if (!inode) {
                        list_del_init(&info->shrinklist);
-                       removed++;
                        goto next;
                }
 
@@ -578,12 +577,12 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
                if (round_up(inode->i_size, PAGE_SIZE) ==
                                round_up(inode->i_size, HPAGE_PMD_SIZE)) {
                        list_move(&info->shrinklist, &to_remove);
-                       removed++;
                        goto next;
                }
 
                list_move(&info->shrinklist, &list);
 next:
+               sbinfo->shrinklist_len--;
                if (!--batch)
                        break;
        }
@@ -603,7 +602,7 @@ next:
                inode = &info->vfs_inode;
 
                if (nr_to_split && split >= nr_to_split)
-                       goto leave;
+                       goto move_back;
 
                page = find_get_page(inode->i_mapping,
                                (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT);
@@ -617,38 +616,44 @@ next:
                }
 
                /*
-                * Leave the inode on the list if we failed to lock
-                * the page at this time.
+                * Move the inode on the list back to shrinklist if we failed
+                * to lock the page at this time.
                 *
                 * Waiting for the lock may lead to deadlock in the
                 * reclaim path.
                 */
                if (!trylock_page(page)) {
                        put_page(page);
-                       goto leave;
+                       goto move_back;
                }
 
                ret = split_huge_page(page);
                unlock_page(page);
                put_page(page);
 
-               /* If split failed leave the inode on the list */
+               /* If split failed move the inode on the list back to shrinklist */
                if (ret)
-                       goto leave;
+                       goto move_back;
 
                split++;
 drop:
                list_del_init(&info->shrinklist);
-               removed++;
-leave:
+               goto put;
+move_back:
+               /*
+                * Make sure the inode is either on the global list or deleted
+                * from any local list before iput() since it could be deleted
+                * in another thread once we put the inode (then the local list
+                * is corrupted).
+                */
+               spin_lock(&sbinfo->shrinklist_lock);
+               list_move(&info->shrinklist, &sbinfo->shrinklist);
+               sbinfo->shrinklist_len++;
+               spin_unlock(&sbinfo->shrinklist_lock);
+put:
                iput(inode);
        }
 
-       spin_lock(&sbinfo->shrinklist_lock);
-       list_splice_tail(&list, &sbinfo->shrinklist);
-       sbinfo->shrinklist_len -= removed;
-       spin_unlock(&sbinfo->shrinklist_lock);
-
        return split;
 }
 
@@ -2389,8 +2394,10 @@ int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
                                /* don't free the page */
                                goto out_unacct_blocks;
                        }
+
+                       flush_dcache_page(page);
                } else {                /* ZEROPAGE */
-                       clear_highpage(page);
+                       clear_user_highpage(page, dst_addr);
                }
        } else {
                page = *pagep;