All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maksym Planeta <mcsim.planeta@gmail.com>
To: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Thomas Knauth <thomas.knauth@gmx.de>,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	Maksym Planeta <mcsim.planeta@gmail.com>
Subject: [PATCH] sysctl: Add a feature to drop caches selectively
Date: Tue, 24 Jun 2014 18:10:13 +0200	[thread overview]
Message-ID: <1403626213-7691-1-git-send-email-mcsim.planeta@gmail.com> (raw)

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@gmx.de>
Signed-off-by: Maksym Planeta <mcsim.planeta@gmail.com>
---
 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


             reply	other threads:[~2014-06-24 16:15 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-24 16:10 Maksym Planeta [this message]
2014-06-24 21:59 ` [PATCH] sysctl: Add a feature to drop caches selectively David Rientjes
2014-06-25  6:25   ` Artem Bityutskiy
2014-06-25  8:25     ` Thomas Knauth
2014-06-25  9:56       ` Artem Bityutskiy
2014-06-25 13:23         ` Thomas Knauth
2014-06-25 13:30           ` Artem Bityutskiy
2014-06-25 13:42           ` Artem Bityutskiy
2014-06-26  9:30             ` Maksym Planeta
2014-06-25 10:03       ` Artem Bityutskiy
2014-06-25 13:19         ` Thomas Knauth
2014-06-25 22:15       ` Pavel Machek
2014-06-26  1:06       ` Dave Chinner
2014-06-26  6:13         ` Artem Bityutskiy
2014-06-26 10:36           ` Bernd Schubert
2014-06-26 11:31             ` Artem Bityutskiy
2014-06-26 11:57               ` Lukáš Czerner
2014-06-26 12:10                 ` Bernd Schubert
2014-06-27  2:55                   ` Dave Chinner
2014-06-27  2:55                     ` Dave Chinner
2014-06-27  8:58                     ` Bernd Schubert
2014-06-27  8:41                 ` Matthias Schniedermeyer
2014-06-27  9:04                   ` Lukáš Czerner
2014-06-27  9:08                   ` Artem Bityutskiy
2014-06-27  9:08                     ` Artem Bityutskiy
2014-06-27  9:09                     ` Bityutskiy, Artem
2014-06-27  9:09                       ` Bityutskiy, Artem
2014-06-27  2:48           ` Dave Chinner
     [not found] <CACVxJT_6sp=KDy=jCNBypYapKv_59W8LxFU4OiJEm6gt_SuZKg@mail.gmail.com>
2014-06-25 11:21 ` Alexey Dobriyan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1403626213-7691-1-git-send-email-mcsim.planeta@gmail.com \
    --to=mcsim.planeta@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=thomas.knauth@gmx.de \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.