diff options
Diffstat (limited to 'fs/dcache.c')
| -rw-r--r-- | fs/dcache.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index e368d4f412f9..7d34f04ec7aa 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -38,6 +38,8 @@ | |||
| 38 | #include <linux/prefetch.h> | 38 | #include <linux/prefetch.h> |
| 39 | #include <linux/ratelimit.h> | 39 | #include <linux/ratelimit.h> |
| 40 | #include <linux/list_lru.h> | 40 | #include <linux/list_lru.h> |
| 41 | #include <linux/kasan.h> | ||
| 42 | |||
| 41 | #include "internal.h" | 43 | #include "internal.h" |
| 42 | #include "mount.h" | 44 | #include "mount.h" |
| 43 | 45 | ||
| @@ -400,19 +402,20 @@ static void d_shrink_add(struct dentry *dentry, struct list_head *list) | |||
| 400 | * LRU lists entirely, while shrink_move moves it to the indicated | 402 | * LRU lists entirely, while shrink_move moves it to the indicated |
| 401 | * private list. | 403 | * private list. |
| 402 | */ | 404 | */ |
| 403 | static void d_lru_isolate(struct dentry *dentry) | 405 | static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry) |
| 404 | { | 406 | { |
| 405 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); | 407 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); |
| 406 | dentry->d_flags &= ~DCACHE_LRU_LIST; | 408 | dentry->d_flags &= ~DCACHE_LRU_LIST; |
| 407 | this_cpu_dec(nr_dentry_unused); | 409 | this_cpu_dec(nr_dentry_unused); |
| 408 | list_del_init(&dentry->d_lru); | 410 | list_lru_isolate(lru, &dentry->d_lru); |
| 409 | } | 411 | } |
| 410 | 412 | ||
| 411 | static void d_lru_shrink_move(struct dentry *dentry, struct list_head *list) | 413 | static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry, |
| 414 | struct list_head *list) | ||
| 412 | { | 415 | { |
| 413 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); | 416 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); |
| 414 | dentry->d_flags |= DCACHE_SHRINK_LIST; | 417 | dentry->d_flags |= DCACHE_SHRINK_LIST; |
| 415 | list_move_tail(&dentry->d_lru, list); | 418 | list_lru_isolate_move(lru, &dentry->d_lru, list); |
| 416 | } | 419 | } |
| 417 | 420 | ||
| 418 | /* | 421 | /* |
| @@ -869,8 +872,8 @@ static void shrink_dentry_list(struct list_head *list) | |||
| 869 | } | 872 | } |
| 870 | } | 873 | } |
| 871 | 874 | ||
| 872 | static enum lru_status | 875 | static enum lru_status dentry_lru_isolate(struct list_head *item, |
| 873 | dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg) | 876 | struct list_lru_one *lru, spinlock_t *lru_lock, void *arg) |
| 874 | { | 877 | { |
| 875 | struct list_head *freeable = arg; | 878 | struct list_head *freeable = arg; |
| 876 | struct dentry *dentry = container_of(item, struct dentry, d_lru); | 879 | 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) | |||
| 890 | * another pass through the LRU. | 893 | * another pass through the LRU. |
| 891 | */ | 894 | */ |
| 892 | if (dentry->d_lockref.count) { | 895 | if (dentry->d_lockref.count) { |
| 893 | d_lru_isolate(dentry); | 896 | d_lru_isolate(lru, dentry); |
| 894 | spin_unlock(&dentry->d_lock); | 897 | spin_unlock(&dentry->d_lock); |
| 895 | return LRU_REMOVED; | 898 | return LRU_REMOVED; |
| 896 | } | 899 | } |
| @@ -921,7 +924,7 @@ dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg) | |||
| 921 | return LRU_ROTATE; | 924 | return LRU_ROTATE; |
| 922 | } | 925 | } |
| 923 | 926 | ||
| 924 | d_lru_shrink_move(dentry, freeable); | 927 | d_lru_shrink_move(lru, dentry, freeable); |
| 925 | spin_unlock(&dentry->d_lock); | 928 | spin_unlock(&dentry->d_lock); |
| 926 | 929 | ||
| 927 | return LRU_REMOVED; | 930 | return LRU_REMOVED; |
| @@ -930,30 +933,28 @@ dentry_lru_isolate(struct list_head *item, spinlock_t *lru_lock, void *arg) | |||
| 930 | /** | 933 | /** |
| 931 | * prune_dcache_sb - shrink the dcache | 934 | * prune_dcache_sb - shrink the dcache |
| 932 | * @sb: superblock | 935 | * @sb: superblock |
| 933 | * @nr_to_scan : number of entries to try to free | 936 | * @sc: shrink control, passed to list_lru_shrink_walk() |
| 934 | * @nid: which node to scan for freeable entities | ||
| 935 | * | 937 | * |
| 936 | * Attempt to shrink the superblock dcache LRU by @nr_to_scan entries. This is | 938 | * Attempt to shrink the superblock dcache LRU by @sc->nr_to_scan entries. This |
| 937 | * done when we need more memory an called from the superblock shrinker | 939 | * is done when we need more memory and called from the superblock shrinker |
| 938 | * function. | 940 | * function. |
| 939 | * | 941 | * |
| 940 | * This function may fail to free any resources if all the dentries are in | 942 | * This function may fail to free any resources if all the dentries are in |
| 941 | * use. | 943 | * use. |
| 942 | */ | 944 | */ |
| 943 | long prune_dcache_sb(struct super_block *sb, unsigned long nr_to_scan, | 945 | long prune_dcache_sb(struct super_block *sb, struct shrink_control *sc) |
| 944 | int nid) | ||
| 945 | { | 946 | { |
| 946 | LIST_HEAD(dispose); | 947 | LIST_HEAD(dispose); |
| 947 | long freed; | 948 | long freed; |
| 948 | 949 | ||
| 949 | freed = list_lru_walk_node(&sb->s_dentry_lru, nid, dentry_lru_isolate, | 950 | freed = list_lru_shrink_walk(&sb->s_dentry_lru, sc, |
| 950 | &dispose, &nr_to_scan); | 951 | dentry_lru_isolate, &dispose); |
| 951 | shrink_dentry_list(&dispose); | 952 | shrink_dentry_list(&dispose); |
| 952 | return freed; | 953 | return freed; |
| 953 | } | 954 | } |
| 954 | 955 | ||
| 955 | static enum lru_status dentry_lru_isolate_shrink(struct list_head *item, | 956 | static enum lru_status dentry_lru_isolate_shrink(struct list_head *item, |
| 956 | spinlock_t *lru_lock, void *arg) | 957 | struct list_lru_one *lru, spinlock_t *lru_lock, void *arg) |
| 957 | { | 958 | { |
| 958 | struct list_head *freeable = arg; | 959 | struct list_head *freeable = arg; |
| 959 | struct dentry *dentry = container_of(item, struct dentry, d_lru); | 960 | 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, | |||
| 966 | if (!spin_trylock(&dentry->d_lock)) | 967 | if (!spin_trylock(&dentry->d_lock)) |
| 967 | return LRU_SKIP; | 968 | return LRU_SKIP; |
| 968 | 969 | ||
| 969 | d_lru_shrink_move(dentry, freeable); | 970 | d_lru_shrink_move(lru, dentry, freeable); |
| 970 | spin_unlock(&dentry->d_lock); | 971 | spin_unlock(&dentry->d_lock); |
| 971 | 972 | ||
| 972 | return LRU_REMOVED; | 973 | return LRU_REMOVED; |
| @@ -1430,6 +1431,9 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) | |||
| 1430 | } | 1431 | } |
| 1431 | atomic_set(&p->u.count, 1); | 1432 | atomic_set(&p->u.count, 1); |
| 1432 | dname = p->name; | 1433 | dname = p->name; |
| 1434 | if (IS_ENABLED(CONFIG_DCACHE_WORD_ACCESS)) | ||
| 1435 | kasan_unpoison_shadow(dname, | ||
| 1436 | round_up(name->len + 1, sizeof(unsigned long))); | ||
| 1433 | } else { | 1437 | } else { |
| 1434 | dname = dentry->d_iname; | 1438 | dname = dentry->d_iname; |
| 1435 | } | 1439 | } |
