Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/drop_caches.c
26131 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Implement the manual drop-all-pagecache function
4
*/
5
6
#include <linux/pagemap.h>
7
#include <linux/kernel.h>
8
#include <linux/mm.h>
9
#include <linux/fs.h>
10
#include <linux/writeback.h>
11
#include <linux/sysctl.h>
12
#include <linux/gfp.h>
13
#include <linux/swap.h>
14
#include "internal.h"
15
16
/* A global variable is a bit ugly, but it keeps the code simple */
17
static int sysctl_drop_caches;
18
19
static void drop_pagecache_sb(struct super_block *sb, void *unused)
20
{
21
struct inode *inode, *toput_inode = NULL;
22
23
spin_lock(&sb->s_inode_list_lock);
24
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
25
spin_lock(&inode->i_lock);
26
/*
27
* We must skip inodes in unusual state. We may also skip
28
* inodes without pages but we deliberately won't in case
29
* we need to reschedule to avoid softlockups.
30
*/
31
if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
32
(mapping_empty(inode->i_mapping) && !need_resched())) {
33
spin_unlock(&inode->i_lock);
34
continue;
35
}
36
__iget(inode);
37
spin_unlock(&inode->i_lock);
38
spin_unlock(&sb->s_inode_list_lock);
39
40
invalidate_mapping_pages(inode->i_mapping, 0, -1);
41
iput(toput_inode);
42
toput_inode = inode;
43
44
cond_resched();
45
spin_lock(&sb->s_inode_list_lock);
46
}
47
spin_unlock(&sb->s_inode_list_lock);
48
iput(toput_inode);
49
}
50
51
static int drop_caches_sysctl_handler(const struct ctl_table *table, int write,
52
void *buffer, size_t *length, loff_t *ppos)
53
{
54
int ret;
55
56
ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
57
if (ret)
58
return ret;
59
if (write) {
60
static int stfu;
61
62
if (sysctl_drop_caches & 1) {
63
lru_add_drain_all();
64
iterate_supers(drop_pagecache_sb, NULL);
65
count_vm_event(DROP_PAGECACHE);
66
}
67
if (sysctl_drop_caches & 2) {
68
drop_slab();
69
count_vm_event(DROP_SLAB);
70
}
71
if (!stfu) {
72
pr_info("%s (%d): drop_caches: %d\n",
73
current->comm, task_pid_nr(current),
74
sysctl_drop_caches);
75
}
76
stfu |= sysctl_drop_caches & 4;
77
}
78
return 0;
79
}
80
81
static const struct ctl_table drop_caches_table[] = {
82
{
83
.procname = "drop_caches",
84
.data = &sysctl_drop_caches,
85
.maxlen = sizeof(int),
86
.mode = 0200,
87
.proc_handler = drop_caches_sysctl_handler,
88
.extra1 = SYSCTL_ONE,
89
.extra2 = SYSCTL_FOUR,
90
},
91
};
92
93
static int __init init_vm_drop_caches_sysctls(void)
94
{
95
register_sysctl_init("vm", drop_caches_table);
96
return 0;
97
}
98
fs_initcall(init_vm_drop_caches_sysctls);
99
100