[PATCH] sysctl: Add a feature to drop caches selectively

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



To clean the page cache one can use /proc/sys/vm/drop_caches. But this
drops the whole page cache. In contrast to that sdrop_caches enables
ability to drop the page cache selectively by path string.

Suggested-by: Thomas Knauth <thomas.knauth@xxxxxx>
Signed-off-by: Maksym Planeta <mcsim.planeta@xxxxxxxxx>
---
 Documentation/sysctl/vm.txt |  15 ++++++
 fs/Makefile                 |   2 +-
 fs/sdrop_caches.c           | 124 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+), 1 deletion(-)
 create mode 100644 fs/sdrop_caches.c

diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index bd4b34c..faad01d 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -28,6 +28,7 @@ Currently, these files are in /proc/sys/vm:
 - dirty_ratio
 - dirty_writeback_centisecs
 - drop_caches
+- sdrop_caches
 - extfrag_threshold
 - hugepages_treat_as_movable
 - hugetlb_shm_group
@@ -211,6 +212,20 @@ with your system.  To disable them, echo 4 (bit 3) into drop_caches.
 
 ==============================================================
 
+sdrop_caches
+
+Writing to this will cause the kernel to drop clean caches starting from
+specified path.
+
+To free pagecache of a file:
+	echo /home/user/file > /proc/sys/vm/sdrop_caches
+To free pagecache of a directory and all files in it.
+	echo /home/user/directly > /proc/sys/vm/sdrop_caches
+
+Restrictions are the same as for drop_caches.
+
+==============================================================
+
 extfrag_threshold
 
 This parameter affects whether the kernel will compact memory or direct
diff --git a/fs/Makefile b/fs/Makefile
index 4030cbf..366c7b9 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -44,7 +44,7 @@ obj-$(CONFIG_FS_MBCACHE)	+= mbcache.o
 obj-$(CONFIG_FS_POSIX_ACL)	+= posix_acl.o
 obj-$(CONFIG_NFS_COMMON)	+= nfs_common/
 obj-$(CONFIG_COREDUMP)		+= coredump.o
-obj-$(CONFIG_SYSCTL)		+= drop_caches.o
+obj-$(CONFIG_SYSCTL)		+= drop_caches.o sdrop_caches.o
 
 obj-$(CONFIG_FHANDLE)		+= fhandle.o
 
diff --git a/fs/sdrop_caches.c b/fs/sdrop_caches.c
new file mode 100644
index 0000000..c193655
--- /dev/null
+++ b/fs/sdrop_caches.c
@@ -0,0 +1,124 @@
+/*
+ * Implement the manual selective drop pagecache function
+ */
+
+#include <linux/module.h>
+
+
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/uaccess.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/writeback.h>
+#include <linux/sysctl.h>
+#include <linux/gfp.h>
+#include <linux/limits.h>
+#include <linux/namei.h>
+
+static void clean_mapping(struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (!inode)
+		return;
+
+	if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
+	    (inode->i_mapping->nrpages == 0)) {
+		return;
+	}
+
+	invalidate_mapping_pages(inode->i_mapping, 0, -1);
+}
+
+static void clean_all_dentries_locked(struct dentry *dentry)
+{
+	struct dentry *child;
+
+	list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
+		clean_all_dentries_locked(child);
+	}
+
+	clean_mapping(dentry);
+}
+
+static void clean_all_dentries(struct dentry *dentry)
+{
+	spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
+	clean_all_dentries_locked(dentry);
+	spin_unlock(&dentry->d_lock);
+}
+
+static int drop_pagecache(const char * __user filename)
+{
+	unsigned int lookup_flags = LOOKUP_FOLLOW;
+	struct path path;
+	int error;
+
+retry:
+	error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
+	if (!error) {
+		/* clean */
+		clean_all_dentries(path.dentry);
+	}
+	if (retry_estale(error, lookup_flags)) {
+		lookup_flags |= LOOKUP_REVAL;
+		goto retry;
+	}
+	return error;
+}
+
+static int sdrop_ctl_handler(struct ctl_table *table, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	char __user *pathname = buffer + *lenp - 1;
+
+	put_user('\0', pathname);
+
+	if (!write)
+		return 0;
+
+	return drop_pagecache(buffer);
+}
+
+static struct ctl_path vm_path[] = { { .procname = "vm", }, { } };
+static struct ctl_table sdrop_ctl_table[] = {
+	{
+		.procname = "sdrop_caches",
+		.mode = 0644,
+		.proc_handler = sdrop_ctl_handler,
+	},
+	{ }
+};
+
+static struct ctl_table_header *sdrop_proc_entry;
+
+/* Init function called on module entry */
+int sdrop_init(void)
+{
+	int ret = 0;
+
+	sdrop_proc_entry = register_sysctl_paths(vm_path, sdrop_ctl_table);
+
+	if (sdrop_proc_entry == NULL) {
+		ret = -ENOMEM;
+		pr_err("sdrop_caches: Couldn't create proc entry\n");
+	}
+
+	return ret;
+}
+
+/* Cleanup function called on module exit */
+void sdrop_cleanup(void)
+{
+	unregister_sysctl_table(sdrop_proc_entry);
+}
+
+module_init(sdrop_init);
+module_exit(sdrop_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Selective pagecache drop module");
+MODULE_AUTHOR("Maksym Planeta");
-- 
2.0.0

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux