diff options
| author | Dan Williams <dan.j.williams@intel.com> | 2019-03-11 15:37:55 -0400 |
|---|---|---|
| committer | Dan Williams <dan.j.williams@intel.com> | 2019-03-11 15:37:55 -0400 |
| commit | 4083014e32699af04a8e6eaa4855b08dba36a47a (patch) | |
| tree | fa37f9f9691fe64ca8a3c0cdc0315dc12462e6e4 /fs/dcache.c | |
| parent | 6fd96ff557963de8e62842a0dc360a6e3610d2bb (diff) | |
| parent | 78153dd45e7e0596ba32b15d02bda08e1513111e (diff) | |
Merge branch 'for-5.1/nfit/ars' into libnvdimm-for-next
Merge several updates to the ARS implementation. Highlights include:
* Support retrieval of short-ARS results if the ARS state is "requires
continuation", and even if the "no_init_ars" module parameter is
specified.
* Allow busy-polling of the kernel ARS state by allowing root to reset
the exponential back-off timer.
* Filter potentially stale ARS results by tracking query-ARS relative to
the previous start-ARS.
Diffstat (limited to 'fs/dcache.c')
| -rw-r--r-- | fs/dcache.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 2593153471cf..aac41adf4743 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -119,6 +119,7 @@ struct dentry_stat_t dentry_stat = { | |||
| 119 | 119 | ||
| 120 | static DEFINE_PER_CPU(long, nr_dentry); | 120 | static DEFINE_PER_CPU(long, nr_dentry); |
| 121 | static DEFINE_PER_CPU(long, nr_dentry_unused); | 121 | static DEFINE_PER_CPU(long, nr_dentry_unused); |
| 122 | static DEFINE_PER_CPU(long, nr_dentry_negative); | ||
| 122 | 123 | ||
| 123 | #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS) | 124 | #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS) |
| 124 | 125 | ||
| @@ -152,11 +153,22 @@ static long get_nr_dentry_unused(void) | |||
| 152 | return sum < 0 ? 0 : sum; | 153 | return sum < 0 ? 0 : sum; |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 156 | static long get_nr_dentry_negative(void) | ||
| 157 | { | ||
| 158 | int i; | ||
| 159 | long sum = 0; | ||
| 160 | |||
| 161 | for_each_possible_cpu(i) | ||
| 162 | sum += per_cpu(nr_dentry_negative, i); | ||
| 163 | return sum < 0 ? 0 : sum; | ||
| 164 | } | ||
| 165 | |||
| 155 | int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer, | 166 | int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer, |
| 156 | size_t *lenp, loff_t *ppos) | 167 | size_t *lenp, loff_t *ppos) |
| 157 | { | 168 | { |
| 158 | dentry_stat.nr_dentry = get_nr_dentry(); | 169 | dentry_stat.nr_dentry = get_nr_dentry(); |
| 159 | dentry_stat.nr_unused = get_nr_dentry_unused(); | 170 | dentry_stat.nr_unused = get_nr_dentry_unused(); |
| 171 | dentry_stat.nr_negative = get_nr_dentry_negative(); | ||
| 160 | return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); | 172 | return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); |
| 161 | } | 173 | } |
| 162 | #endif | 174 | #endif |
| @@ -317,6 +329,8 @@ static inline void __d_clear_type_and_inode(struct dentry *dentry) | |||
| 317 | flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU); | 329 | flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU); |
| 318 | WRITE_ONCE(dentry->d_flags, flags); | 330 | WRITE_ONCE(dentry->d_flags, flags); |
| 319 | dentry->d_inode = NULL; | 331 | dentry->d_inode = NULL; |
| 332 | if (dentry->d_flags & DCACHE_LRU_LIST) | ||
| 333 | this_cpu_inc(nr_dentry_negative); | ||
| 320 | } | 334 | } |
| 321 | 335 | ||
| 322 | static void dentry_free(struct dentry *dentry) | 336 | static void dentry_free(struct dentry *dentry) |
| @@ -371,6 +385,11 @@ static void dentry_unlink_inode(struct dentry * dentry) | |||
| 371 | * The per-cpu "nr_dentry_unused" counters are updated with | 385 | * The per-cpu "nr_dentry_unused" counters are updated with |
| 372 | * the DCACHE_LRU_LIST bit. | 386 | * the DCACHE_LRU_LIST bit. |
| 373 | * | 387 | * |
| 388 | * The per-cpu "nr_dentry_negative" counters are only updated | ||
| 389 | * when deleted from or added to the per-superblock LRU list, not | ||
| 390 | * from/to the shrink list. That is to avoid an unneeded dec/inc | ||
| 391 | * pair when moving from LRU to shrink list in select_collect(). | ||
| 392 | * | ||
| 374 | * These helper functions make sure we always follow the | 393 | * These helper functions make sure we always follow the |
| 375 | * rules. d_lock must be held by the caller. | 394 | * rules. d_lock must be held by the caller. |
| 376 | */ | 395 | */ |
| @@ -380,6 +399,8 @@ static void d_lru_add(struct dentry *dentry) | |||
| 380 | D_FLAG_VERIFY(dentry, 0); | 399 | D_FLAG_VERIFY(dentry, 0); |
| 381 | dentry->d_flags |= DCACHE_LRU_LIST; | 400 | dentry->d_flags |= DCACHE_LRU_LIST; |
| 382 | this_cpu_inc(nr_dentry_unused); | 401 | this_cpu_inc(nr_dentry_unused); |
| 402 | if (d_is_negative(dentry)) | ||
| 403 | this_cpu_inc(nr_dentry_negative); | ||
| 383 | WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru)); | 404 | WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru)); |
| 384 | } | 405 | } |
| 385 | 406 | ||
| @@ -388,6 +409,8 @@ static void d_lru_del(struct dentry *dentry) | |||
| 388 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); | 409 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); |
| 389 | dentry->d_flags &= ~DCACHE_LRU_LIST; | 410 | dentry->d_flags &= ~DCACHE_LRU_LIST; |
| 390 | this_cpu_dec(nr_dentry_unused); | 411 | this_cpu_dec(nr_dentry_unused); |
| 412 | if (d_is_negative(dentry)) | ||
| 413 | this_cpu_dec(nr_dentry_negative); | ||
| 391 | WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru)); | 414 | WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru)); |
| 392 | } | 415 | } |
| 393 | 416 | ||
| @@ -418,6 +441,8 @@ static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry) | |||
| 418 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); | 441 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); |
| 419 | dentry->d_flags &= ~DCACHE_LRU_LIST; | 442 | dentry->d_flags &= ~DCACHE_LRU_LIST; |
| 420 | this_cpu_dec(nr_dentry_unused); | 443 | this_cpu_dec(nr_dentry_unused); |
| 444 | if (d_is_negative(dentry)) | ||
| 445 | this_cpu_dec(nr_dentry_negative); | ||
| 421 | list_lru_isolate(lru, &dentry->d_lru); | 446 | list_lru_isolate(lru, &dentry->d_lru); |
| 422 | } | 447 | } |
| 423 | 448 | ||
| @@ -426,6 +451,8 @@ static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry, | |||
| 426 | { | 451 | { |
| 427 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); | 452 | D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); |
| 428 | dentry->d_flags |= DCACHE_SHRINK_LIST; | 453 | dentry->d_flags |= DCACHE_SHRINK_LIST; |
| 454 | if (d_is_negative(dentry)) | ||
| 455 | this_cpu_dec(nr_dentry_negative); | ||
| 429 | list_lru_isolate_move(lru, &dentry->d_lru, list); | 456 | list_lru_isolate_move(lru, &dentry->d_lru, list); |
| 430 | } | 457 | } |
| 431 | 458 | ||
| @@ -1188,15 +1215,11 @@ static enum lru_status dentry_lru_isolate_shrink(struct list_head *item, | |||
| 1188 | */ | 1215 | */ |
| 1189 | void shrink_dcache_sb(struct super_block *sb) | 1216 | void shrink_dcache_sb(struct super_block *sb) |
| 1190 | { | 1217 | { |
| 1191 | long freed; | ||
| 1192 | |||
| 1193 | do { | 1218 | do { |
| 1194 | LIST_HEAD(dispose); | 1219 | LIST_HEAD(dispose); |
| 1195 | 1220 | ||
| 1196 | freed = list_lru_walk(&sb->s_dentry_lru, | 1221 | list_lru_walk(&sb->s_dentry_lru, |
| 1197 | dentry_lru_isolate_shrink, &dispose, 1024); | 1222 | dentry_lru_isolate_shrink, &dispose, 1024); |
| 1198 | |||
| 1199 | this_cpu_sub(nr_dentry_unused, freed); | ||
| 1200 | shrink_dentry_list(&dispose); | 1223 | shrink_dentry_list(&dispose); |
| 1201 | } while (list_lru_count(&sb->s_dentry_lru) > 0); | 1224 | } while (list_lru_count(&sb->s_dentry_lru) > 0); |
| 1202 | } | 1225 | } |
| @@ -1820,6 +1843,11 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) | |||
| 1820 | WARN_ON(d_in_lookup(dentry)); | 1843 | WARN_ON(d_in_lookup(dentry)); |
| 1821 | 1844 | ||
| 1822 | spin_lock(&dentry->d_lock); | 1845 | spin_lock(&dentry->d_lock); |
| 1846 | /* | ||
| 1847 | * Decrement negative dentry count if it was in the LRU list. | ||
| 1848 | */ | ||
| 1849 | if (dentry->d_flags & DCACHE_LRU_LIST) | ||
| 1850 | this_cpu_dec(nr_dentry_negative); | ||
| 1823 | hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); | 1851 | hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); |
| 1824 | raw_write_seqcount_begin(&dentry->d_seq); | 1852 | raw_write_seqcount_begin(&dentry->d_seq); |
| 1825 | __d_set_inode_and_type(dentry, inode, add_flags); | 1853 | __d_set_inode_and_type(dentry, inode, add_flags); |
