Merge branch 'akpm' (patches from Andrew)
[firefly-linux-kernel-4.4.55.git] / fs / dcache.c
index e368d4f412f97ed11039e3329c77358b3fc1fea0..7d34f04ec7aa9fed7030d455a118f56ab47fe2e4 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/prefetch.h>
 #include <linux/ratelimit.h>
 #include <linux/list_lru.h>
+#include <linux/kasan.h>
+
 #include "internal.h"
 #include "mount.h"
 
@@ -400,19 +402,20 @@ static void d_shrink_add(struct dentry *dentry, struct list_head *list)
  * LRU lists entirely, while shrink_move moves it to the indicated
  * private list.
  */
-static void d_lru_isolate(struct dentry *dentry)
+static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry)
 {
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags &= ~DCACHE_LRU_LIST;
        this_cpu_dec(nr_dentry_unused);
-       list_del_init(&dentry->d_lru);
+       list_lru_isolate(lru, &dentry->d_lru);
 }
 
-static void d_lru_shrink_move(struct dentry *dentry, struct list_head *list)
+static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry,
+                             struct list_head *list)
 {
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags |= DCACHE_SHRINK_LIST;
-       list_move_tail(&dentry->d_lru, list);
+       list_lru_isolate_move(lru, &dentry->d_lru, list);
 }
 
 /*
@@ -869,8 +872,8 @@ static void shrink_dentry_list(struct list_head *list)
        }
 }
 
-static enum lru_status
-dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg)
+static enum lru_status dentry_lru_isolate(struct list_head *item,
+               struct list_lru_one *lru, spinlock_t *lru_lock, void *arg)
 {
        struct list_head *freeable = arg;
        struct dentry   *dentry = container_of(item, struct dentry, d_lru);
@@ -890,7 +893,7 @@ dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg)
         * another pass through the LRU.
         */
        if (dentry->d_lockref.count) {
-               d_lru_isolate(dentry);
+               d_lru_isolate(lru, dentry);
                spin_unlock(&dentry->d_lock);
                return LRU_REMOVED;
        }
@@ -921,7 +924,7 @@ dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg)
                return LRU_ROTATE;
        }
 
-       d_lru_shrink_move(dentry, freeable);
+       d_lru_shrink_move(lru, dentry, freeable);
        spin_unlock(&dentry->d_lock);
 
        return LRU_REMOVED;
@@ -930,30 +933,28 @@ dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg)
 /**
  * prune_dcache_sb - shrink the dcache
  * @sb: superblock
- * @nr_to_scan : number of entries to try to free
- * @nid: which node to scan for freeable entities
+ * @sc: shrink control, passed to list_lru_shrink_walk()
  *
- * Attempt to shrink the superblock dcache LRU by @nr_to_scan entries. This is
- * done when we need more memory an called from the superblock shrinker
+ * Attempt to shrink the superblock dcache LRU by @sc->nr_to_scan entries. This
+ * is done when we need more memory and called from the superblock shrinker
  * function.
  *
  * This function may fail to free any resources if all the dentries are in
  * use.
  */
-long prune_dcache_sb(struct super_block *sb, unsigned long nr_to_scan,
-                    int nid)
+long prune_dcache_sb(struct super_block *sb, struct shrink_control *sc)
 {
        LIST_HEAD(dispose);
        long freed;
 
-       freed = list_lru_walk_node(&sb->s_dentry_lru, nid, dentry_lru_isolate,
-                                      &dispose, &nr_to_scan);
+       freed = list_lru_shrink_walk(&sb->s_dentry_lru, sc,
+                                    dentry_lru_isolate, &dispose);
        shrink_dentry_list(&dispose);
        return freed;
 }
 
 static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
-                                               spinlock_t *lru_lock, void *arg)
+               struct list_lru_one *lru, spinlock_t *lru_lock, void *arg)
 {
        struct list_head *freeable = arg;
        struct dentry   *dentry = container_of(item, struct dentry, d_lru);
@@ -966,7 +967,7 @@ static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
        if (!spin_trylock(&dentry->d_lock))
                return LRU_SKIP;
 
-       d_lru_shrink_move(dentry, freeable);
+       d_lru_shrink_move(lru, dentry, freeable);
        spin_unlock(&dentry->d_lock);
 
        return LRU_REMOVED;
@@ -1430,6 +1431,9 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
                }
                atomic_set(&p->u.count, 1);
                dname = p->name;
+               if (IS_ENABLED(CONFIG_DCACHE_WORD_ACCESS))
+                       kasan_unpoison_shadow(dname,
+                               round_up(name->len + 1, sizeof(unsigned long)));
        } else  {
                dname = dentry->d_iname;
        }