Skip to contentSkip to conversation

cgroup: make cgroup_event specific to memcg

PATCH In review Tejun Heo 4 participants 30 messages Aug 4, 2013 – Aug 9, 2013

Subsystems (5)
lore
Share & tools
lore

Tejun Heo

author maintainer
#0 lore raw

PATCH 1/1 cgroup: make cgroup_event specific to memcg

Hello,

Like many other things in cgroup, cgroup_event is way too flexible and complex - it strives to provide completely flexible event monitoring facility in cgroup proper which allows any number of users to monitor custom events. This is overboard, to say the least, and I strongly think that cgroup should not any new usages of this facility and preferably deprecate the existing usages if at all possible.

Fortunately, memcg along with vmpressure is the only user of the facility and gets to keep it. This patchset makes cgroup_event specific to memcg, moves all related code into mm/memcontrol.c and renames it to mem_cgroup_event so that its usage can't spread to other subsystems and later deprecation and cleanup can be localized.

Note that after this patchset, cgroup.event_control file exists only for the hierarchy which has memcg attached to it. This is a userland visible change but unlikely to be noticeable as the file has never been meaningful outside memcg. If this ever becomes problematic, we can add a dummy file on hierarchies w/o memcg when !sane_behavior.

This patchset is consited of the following five patches.

0001-cgroup-implement-CFTYPE_NO_PREFIX.patch 0002-cgroup-export-__cgroup_from_dentry-and-__cgroup_dput.patch 0003-cgroup-memcg-move-cgroup_event-implementation-to-mem.patch 0004-cgroup-memcg-move-cgroup-event_list-_lock-and-event-.patch 0005-memcg-rename-cgroup_event-to-mem_cgroup_event.patch

The patchset is on top of

cgroup/for-3.12 61584e3f4 ("cgroup: Merge branch 'for-3.11-fixes' into for-3.12")
+ [1] cgroup: use cgroup_subsys_state as the primary subsystem interface handle

and available in the following branch.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git review-memcg_event

diffstat follows.

 Documentation/cgroups/cgroups.txt |   19 --
 include/linux/cgroup.h            |   29 ---
 include/linux/vmpressure.h        |    1
 kernel/cgroup.c                   |  265 +--------------------------------
 mm/memcontrol.c                   |  302 ++++++++++++++++++++++++++++++++++++--
 5 files changed, 315 insertions(+), 301 deletions(-)

Thanks.

--
tejun

[1] https://lkml.org/lkml/2013/8/1/722

author maintainer
#1 lore raw

PATCH 1/5 cgroup: implement CFTYPE_NO_PREFIX

When cgroup files are created, cgroup core automatically prepends the name of the subsystem as prefix. This patch adds CFTYPE_NO_ which disables the automatic prefix. This is to work around historical baggages and shouldn't be used for new files.

This will be used to move "cgroup.event_control" from cgroup core to memcg.

Cc Glauber Costa <[email protected]>
---
 include/linux/cgroup.h | 1 +
 kernel/cgroup.c        | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)
include/linux/cgroup.h +1 -0
index c40e508..30d6ec4 100644
@@ -405,6 +405,7 @@ enum {
 	CFTYPE_ONLY_ON_ROOT	= (1 << 0),	/* only create on root cgrp */
 	CFTYPE_NOT_ON_ROOT	= (1 << 1),	/* don't create on root cgrp */
 	CFTYPE_INSANE		= (1 << 2),	/* don't create if sane_behavior */
+	CFTYPE_NO_PREFIX	= (1 << 3),	/* (DON'T USE FOR NEW FILES) no subsys prefix */
 };
 
 #define MAX_CFTYPE_NAME		64
kernel/cgroup.c +2 -1
index c02a288..1b87e2b 100644
@@ -2749,7 +2749,8 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft)
 	umode_t mode;
 	char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
 
-	if (cft->ss && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) {
+	if (cft->ss && !(cft->flags & CFTYPE_NO_PREFIX) &&
+	    !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) {
 		strcpy(name, cft->ss->name);
 		strcat(name, ".");
 	}
Signature · 7 lines
1.8.3.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
author maintainer
#2 lore raw

PATCH 2/5 cgroup: export __cgroup_from_dentry() and __cgroup_dput()

In reply to Tejun Heo

cgroup_event will no longer be supported as cgroup generic mechanism and be moved to memcg. To enable the relocation, implement and export __cgroup_from_dentry() which combines cgroup file dentry -> croup mapping and cft discovery, and prefix cgroup_dput() with __ and export it.

These functions exist and are exported only to enable moving cgroup_event implementation to memcg and shouldn't grow any new users and thus the __ prefix.

This patch is pure reorganization and doesn't introduce any functional difference.

---
 include/linux/cgroup.h |  4 ++++
 kernel/cgroup.c        | 31 +++++++++++++++++--------------
 2 files changed, 21 insertions(+), 14 deletions(-)
include/linux/cgroup.h +4 -0
index 30d6ec4..2ac1021 100644
@@ -923,6 +923,10 @@ bool css_is_ancestor(struct cgroup_subsys_state *cg,
 unsigned short css_id(struct cgroup_subsys_state *css);
 struct cgroup_subsys_state *cgroup_css_from_dir(struct file *f, int id);
 
+/* do not add new users of the following two functions */
+struct cgroup *__cgroup_from_dentry(struct dentry *dentry, struct cftype **cftp);
+void __cgroup_dput(struct cgroup *cgrp);
+
 #else /* !CONFIG_CGROUPS */
 
 static inline int cgroup_init_early(void) { return 0; }
kernel/cgroup.c +17 -14
index 1b87e2b..2583b7b 100644
@@ -2661,15 +2661,18 @@ static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, un
 	return NULL;
 }
 
-/*
- * Check if a file is a control file
- */
-static inline struct cftype *__file_cft(struct file *file)
+/* do not add new users */
+struct cgroup *__cgroup_from_dentry(struct dentry *dentry, struct cftype **cftp)
 {
-	if (file_inode(file)->i_fop != &cgroup_file_operations)
-		return ERR_PTR(-EINVAL);
-	return __d_cft(file->f_dentry);
+	if (!dentry->d_inode ||
+	    dentry->d_inode->i_op != &cgroup_file_inode_operations)
+		return NULL;
+
+	if (cftp)
+		*cftp = __d_cft(dentry);
+	return __d_cgrp(dentry->d_parent);
 }
+EXPORT_SYMBOL_GPL(__cgroup_from_dentry);
 
 static int cgroup_create_file(struct dentry *dentry, umode_t mode,
 				struct super_block *sb)
@@ -3953,7 +3956,7 @@ static int cgroup_write_notify_on_release(struct cgroup_subsys_state *css,
  *
  * That's why we hold a reference before dput() and drop it right after.
  */
-static void cgroup_dput(struct cgroup *cgrp)
+void __cgroup_dput(struct cgroup *cgrp)
 {
 	struct super_block *sb = cgrp->root->sb;
 
@@ -3961,6 +3964,7 @@ static void cgroup_dput(struct cgroup *cgrp)
 	dput(cgrp->dentry);
 	deactivate_super(sb);
 }
+EXPORT_SYMBOL_GPL(__cgroup_dput);
 
 /*
  * Unregister event and free resources.
@@ -3983,7 +3987,7 @@ static void cgroup_event_remove(struct work_struct *work)
 
 	eventfd_ctx_put(event->eventfd);
 	kfree(event);
-	cgroup_dput(cgrp);
+	__cgroup_dput(cgrp);
 }
 
 /*
@@ -4095,9 +4099,9 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css,
 	if (ret < 0)
 		goto out_put_cfile;
 
-	event->cft = __file_cft(cfile);
-	if (IS_ERR(event->cft)) {
-		ret = PTR_ERR(event->cft);
+	cgrp_cfile = __cgroup_from_dentry(cfile->f_dentry, &event->cft);
+	if (!cgrp_cfile) {
+		ret = -EINVAL;
 		goto out_put_cfile;
 	}
 
@@ -4105,7 +4109,6 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css,
 	 * The file to be monitored must be in the same cgroup as
 	 * cgroup.event_control is.
 	 */
-	cgrp_cfile = __d_cgrp(cfile->f_dentry->d_parent);
 	if (cgrp_cfile != cgrp) {
 		ret = -EINVAL;
 		goto out_put_cfile;
@@ -4272,7 +4275,7 @@ static void css_dput_fn(struct work_struct *work)
 	struct cgroup_subsys_state *css =
 		container_of(work, struct cgroup_subsys_state, dput_work);
 
-	cgroup_dput(css->cgroup);
+	__cgroup_dput(css->cgroup);
 }
 
 static void css_release(struct percpu_ref *ref)
Signature · 7 lines
1.8.3.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#3 lore raw

Re: [PATCH 2/5] cgroup: export __cgroup_from_dentry() and __cgroup_dput()

Quoted 4 lines
kernel/cgroup.c +1 -2
+struct cgroup *__cgroup_from_dentry(struct dentry *dentry, struct cftype **cftp)
 {
-	if (file_inode(file)->i_fop != &cgroup_file_operations)
-		return ERR_PTR(-EINVAL);

kernel/cgroup.c static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, un · line 2675

Quoted 10 lines
kernel/cgroup.c +8 -1
-	return __d_cft(file->f_dentry);
+	if (!dentry->d_inode ||
+	    dentry->d_inode->i_op != &cgroup_file_inode_operations)
+		return NULL;
+
+	if (cftp)
+		*cftp = __d_cft(dentry);
+	return __d_cgrp(dentry->d_parent);
 }
+EXPORT_SYMBOL_GPL(__cgroup_from_dentry);

As we don't expect new users, why export this symbol? memcg can't be built as a module.

Quoted 13 lines

static int cgroup_create_file(struct dentry *dentry, umode_t mode,

kernel/cgroup.c +1 -1
 				struct super_block *sb)
@@ -3953,7 +3956,7 @@ static int cgroup_write_notify_on_release(struct cgroup_subsys_state *css,
  *
  * That's why we hold a reference before dput() and drop it right after.
  */
-static void cgroup_dput(struct cgroup *cgrp)
+void __cgroup_dput(struct cgroup *cgrp)
 {
 	struct super_block *sb = cgrp->root->sb;
 

kernel/cgroup.c static void cgroup_dput(struct cgroup *cgrp) · line 3967

Quoted 4 lines
kernel/cgroup.c +1 -0
@@ -3961,6 +3964,7 @@ static void cgroup_dput(struct cgroup *cgrp)
 	dput(cgrp->dentry);
 	deactivate_super(sb);
 }
+EXPORT_SYMBOL_GPL(__cgroup_dput);

ditto

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author maintainer
#4 lore raw

Re: [PATCH 2/5] cgroup: export __cgroup_from_dentry() and __cgroup_dput()

Quoted 9 lines · Li Zefan
Quoted 9 lines
kernel/cgroup.c +5 -3
+struct cgroup *__cgroup_from_dentry(struct dentry *dentry, struct cftype **cftp)
 {
-	if (file_inode(file)->i_fop != &cgroup_file_operations)
-		return ERR_PTR(-EINVAL);
-	return __d_cft(file->f_dentry);
+	if (!dentry->d_inode ||
+	    dentry->d_inode->i_op != &cgroup_file_inode_operations)
+		return NULL;
+
Quoted 8 lines

kernel/cgroup.c static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, un · line 2675

Quoted 5 lines
kernel/cgroup.c +4 -0
+	if (cftp)
+		*cftp = __d_cft(dentry);
+	return __d_cgrp(dentry->d_parent);
 }
+EXPORT_SYMBOL_GPL(__cgroup_from_dentry);

As we don't expect new users, why export this symbol? memcg can't be built as a module.

Yeah, I for some reason was thinking memcg could be bulit as module. Brainfart. Dropped.

Thanks.

Signature · 1 line
tejun
author maintainer
#5 lore raw

PATCH v2 2/5 cgroup: make __cgroup_from_dentry() and __cgroup_dput() global

In reply to Tejun Heo

From eb06a03636eb8477ea034780c37463a086112115 Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Mon, 5 Aug 2013 12:00:23 -0400

cgroup_event will no longer be supported as cgroup generic mechanism and be moved to memcg. To enable the relocation, implement and expose __cgroup_from_dentry() which combines cgroup file dentry -> croup mapping and cft discovery, and prefix cgroup_dput() with __ and make it global.

These functions exist and are exported only to enable moving cgroup_event implementation to memcg and shouldn't grow any new users and thus the __ prefix.

This patch is pure reorganization and doesn't introduce any functional difference.

v2: The original patch had EXPORT_SYMBOL_GPL() for the two functions
because I for some reason thought that memcg could be built as module. Removed as suggested by Li Zefan.

---
 include/linux/cgroup.h |  4 ++++
 kernel/cgroup.c        | 29 +++++++++++++++--------------
 2 files changed, 19 insertions(+), 14 deletions(-)
include/linux/cgroup.h +4 -0
index 30d6ec4..2ac1021 100644
@@ -923,6 +923,10 @@ bool css_is_ancestor(struct cgroup_subsys_state *cg,
 unsigned short css_id(struct cgroup_subsys_state *css);
 struct cgroup_subsys_state *cgroup_css_from_dir(struct file *f, int id);
 
+/* do not add new users of the following two functions */
+struct cgroup *__cgroup_from_dentry(struct dentry *dentry, struct cftype **cftp);
+void __cgroup_dput(struct cgroup *cgrp);
+
 #else /* !CONFIG_CGROUPS */
 
 static inline int cgroup_init_early(void) { return 0; }
kernel/cgroup.c +15 -14
index 1b87e2b..568d031 100644
@@ -2661,14 +2661,16 @@ static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, un
 	return NULL;
 }
 
-/*
- * Check if a file is a control file
- */
-static inline struct cftype *__file_cft(struct file *file)
+/* do not add new users */
+struct cgroup *__cgroup_from_dentry(struct dentry *dentry, struct cftype **cftp)
 {
-	if (file_inode(file)->i_fop != &cgroup_file_operations)
-		return ERR_PTR(-EINVAL);
-	return __d_cft(file->f_dentry);
+	if (!dentry->d_inode ||
+	    dentry->d_inode->i_op != &cgroup_file_inode_operations)
+		return NULL;
+
+	if (cftp)
+		*cftp = __d_cft(dentry);
+	return __d_cgrp(dentry->d_parent);
 }
 
 static int cgroup_create_file(struct dentry *dentry, umode_t mode,
@@ -3953,7 +3955,7 @@ static int cgroup_write_notify_on_release(struct cgroup_subsys_state *css,
  *
  * That's why we hold a reference before dput() and drop it right after.
  */
-static void cgroup_dput(struct cgroup *cgrp)
+void __cgroup_dput(struct cgroup *cgrp)
 {
 	struct super_block *sb = cgrp->root->sb;
 
@@ -3983,7 +3985,7 @@ static void cgroup_event_remove(struct work_struct *work)
 
 	eventfd_ctx_put(event->eventfd);
 	kfree(event);
-	cgroup_dput(cgrp);
+	__cgroup_dput(cgrp);
 }
 
 /*
@@ -4095,9 +4097,9 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css,
 	if (ret < 0)
 		goto out_put_cfile;
 
-	event->cft = __file_cft(cfile);
-	if (IS_ERR(event->cft)) {
-		ret = PTR_ERR(event->cft);
+	cgrp_cfile = __cgroup_from_dentry(cfile->f_dentry, &event->cft);
+	if (!cgrp_cfile) {
+		ret = -EINVAL;
 		goto out_put_cfile;
 	}
 
@@ -4105,7 +4107,6 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *css,
 	 * The file to be monitored must be in the same cgroup as
 	 * cgroup.event_control is.
 	 */
-	cgrp_cfile = __d_cgrp(cfile->f_dentry->d_parent);
 	if (cgrp_cfile != cgrp) {
 		ret = -EINVAL;
 		goto out_put_cfile;
@@ -4272,7 +4273,7 @@ static void css_dput_fn(struct work_struct *work)
 	struct cgroup_subsys_state *css =
 		container_of(work, struct cgroup_subsys_state, dput_work);
 
-	cgroup_dput(css->cgroup);
+	__cgroup_dput(css->cgroup);
 }
 
 static void css_release(struct percpu_ref *ref)
Signature · 1 line
1.8.3.1
author maintainer
#6 lore raw

PATCH 3/5 cgroup, memcg: move cgroup_event implementation to memcg

In reply to Tejun Heo

cgroup_event is way over-designed and tries to build a generic flexible event mechanism into cgroup - fully customizable event specification for each user of the interface. This is utterly unnecessary and overboard especially in the light of the planned unified hierarchy as there's gonna be single agent. Simply generating events at fixed points, or if that's too restrictive, configureable cadence or single set of configureable points should be enough.

Thankfully, memcg is the only user and gets to keep it. Replacing it with something simpler on sane_behavior is strongly recommended.

This patch moves cgroup_event and "cgroup.event_control" implementation to mm/memcontrol.c. Clearing of events on cgroup destruction is moved from cgroup_destroy_locked() to mem_cgroup_css_offline(), which shouldn't make any noticeable difference.

Note that "cgroup.event_control" will now exist only on the hierarchy with memcg attached to it. While this change is visible to userland, it is unlikely to be noticeable as the file has never been meaningful outside memcg.

Cc Johannes Weiner <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Balbir Singh <[email protected]>
---
 kernel/cgroup.c | 237 -------------------------------------------------------
 mm/memcontrol.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 238 insertions(+), 237 deletions(-)
kernel/cgroup.c +0 -237
index 2583b7b..a0b5e22 100644
@@ -56,7 +56,6 @@
 #include <linux/pid_namespace.h>
 #include <linux/idr.h>
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
-#include <linux/eventfd.h>
 #include <linux/poll.h>
 #include <linux/flex_array.h> /* used in cgroup_attach_task */
 #include <linux/kthread.h>
@@ -154,36 +153,6 @@ struct css_id {
 	unsigned short stack[0]; /* Array of Length (depth+1) */
 };
 
-/*
- * cgroup_event represents events which userspace want to receive.
- */
-struct cgroup_event {
-	/*
-	 * css which the event belongs to.
-	 */
-	struct cgroup_subsys_state *css;
-	/*
-	 * Control file which the event associated.
-	 */
-	struct cftype *cft;
-	/*
-	 * eventfd to signal userspace about the event.
-	 */
-	struct eventfd_ctx *eventfd;
-	/*
-	 * Each of these stored in a list by the cgroup.
-	 */
-	struct list_head list;
-	/*
-	 * All fields below needed to unregister event when
-	 * userspace closes eventfd.
-	 */
-	poll_table pt;
-	wait_queue_head_t *wqh;
-	wait_queue_t wait;
-	struct work_struct remove;
-};
-
 /* The list of hierarchy roots */
 
 static LIST_HEAD(cgroup_roots);
@@ -3966,194 +3935,6 @@ void __cgroup_dput(struct cgroup *cgrp)
 }
 EXPORT_SYMBOL_GPL(__cgroup_dput);
 
-/*
- * Unregister event and free resources.
- *
- * Gets called from workqueue.
- */
-static void cgroup_event_remove(struct work_struct *work)
-{
-	struct cgroup_event *event = container_of(work, struct cgroup_event,
-			remove);
-	struct cgroup_subsys_state *css = event->css;
-	struct cgroup *cgrp = css->cgroup;
-
-	remove_wait_queue(event->wqh, &event->wait);
-
-	event->cft->unregister_event(css, event->cft, event->eventfd);
-
-	/* Notify userspace the event is going away. */
-	eventfd_signal(event->eventfd, 1);
-
-	eventfd_ctx_put(event->eventfd);
-	kfree(event);
-	__cgroup_dput(cgrp);
-}
-
-/*
- * Gets called on POLLHUP on eventfd when user closes it.
- *
- * Called with wqh->lock held and interrupts disabled.
- */
-static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
-		int sync, void *key)
-{
-	struct cgroup_event *event = container_of(wait,
-			struct cgroup_event, wait);
-	struct cgroup *cgrp = event->css->cgroup;
-	unsigned long flags = (unsigned long)key;
-
-	if (flags & POLLHUP) {
-		/*
-		 * If the event has been detached at cgroup removal, we
-		 * can simply return knowing the other side will cleanup
-		 * for us.
-		 *
-		 * We can't race against event freeing since the other
-		 * side will require wqh->lock via remove_wait_queue(),
-		 * which we hold.
-		 */
-		spin_lock(&cgrp->event_list_lock);
-		if (!list_empty(&event->list)) {
-			list_del_init(&event->list);
-			/*
-			 * We are in atomic context, but cgroup_event_remove()
-			 * may sleep, so we have to call it in workqueue.
-			 */
-			schedule_work(&event->remove);
-		}
-		spin_unlock(&cgrp->event_list_lock);
-	}
-
-	return 0;
-}
-
-static void cgroup_event_ptable_queue_proc(struct file *file,
-		wait_queue_head_t *wqh, poll_table *pt)
-{
-	struct cgroup_event *event = container_of(pt,
-			struct cgroup_event, pt);
-
-	event->wqh = wqh;
-	add_wait_queue(wqh, &event->wait);
-}
-
-/*
- * Parse input and register new cgroup event handler.
- *
- * Input must be in format '<event_fd> <control_fd> <args>'.
- * Interpretation of args is defined by control file implementation.
- */
-static int cgroup_write_event_control(struct cgroup_subsys_state *css,
-				      struct cftype *cft, const char *buffer)
-{
-	struct cgroup *cgrp = css->cgroup;
-	struct cgroup_event *event;
-	struct cgroup *cgrp_cfile;
-	unsigned int efd, cfd;
-	struct file *efile;
-	struct file *cfile;
-	char *endp;
-	int ret;
-
-	efd = simple_strtoul(buffer, &endp, 10);
-	if (*endp != ' ')
-		return -EINVAL;
-	buffer = endp + 1;
-
-	cfd = simple_strtoul(buffer, &endp, 10);
-	if ((*endp != ' ') && (*endp != '\0'))
-		return -EINVAL;
-	buffer = endp + 1;
-
-	event = kzalloc(sizeof(*event), GFP_KERNEL);
-	if (!event)
-		return -ENOMEM;
-	event->css = css;
-	INIT_LIST_HEAD(&event->list);
-	init_poll_funcptr(&event->pt, cgroup_event_ptable_queue_proc);
-	init_waitqueue_func_entry(&event->wait, cgroup_event_wake);
-	INIT_WORK(&event->remove, cgroup_event_remove);
-
-	efile = eventfd_fget(efd);
-	if (IS_ERR(efile)) {
-		ret = PTR_ERR(efile);
-		goto out_kfree;
-	}
-
-	event->eventfd = eventfd_ctx_fileget(efile);
-	if (IS_ERR(event->eventfd)) {
-		ret = PTR_ERR(event->eventfd);
-		goto out_put_efile;
-	}
-
-	cfile = fget(cfd);
-	if (!cfile) {
-		ret = -EBADF;
-		goto out_put_eventfd;
-	}
-
-	/* the process need read permission on control file */
-	/* AV: shouldn't we check that it's been opened for read instead? */
-	ret = inode_permission(file_inode(cfile), MAY_READ);
-	if (ret < 0)
-		goto out_put_cfile;
-
-	cgrp_cfile = __cgroup_from_dentry(cfile->f_dentry, &event->cft);
-	if (!cgrp_cfile) {
-		ret = -EINVAL;
-		goto out_put_cfile;
-	}
-
-	/*
-	 * The file to be monitored must be in the same cgroup as
-	 * cgroup.event_control is.
-	 */
-	if (cgrp_cfile != cgrp) {
-		ret = -EINVAL;
-		goto out_put_cfile;
-	}
-
-	if (!event->cft->register_event || !event->cft->unregister_event) {
-		ret = -EINVAL;
-		goto out_put_cfile;
-	}
-
-	ret = event->cft->register_event(css, event->cft,
-			event->eventfd, buffer);
-	if (ret)
-		goto out_put_cfile;
-
-	efile->f_op->poll(efile, &event->pt);
-
-	/*
-	 * Events should be removed after rmdir of cgroup directory, but before
-	 * destroying subsystem state objects. Let's take reference to cgroup
-	 * directory dentry to do that.
-	 */
-	dget(cgrp->dentry);
-
-	spin_lock(&cgrp->event_list_lock);
-	list_add(&event->list, &cgrp->event_list);
-	spin_unlock(&cgrp->event_list_lock);
-
-	fput(cfile);
-	fput(efile);
-
-	return 0;
-
-out_put_cfile:
-	fput(cfile);
-out_put_eventfd:
-	eventfd_ctx_put(event->eventfd);
-out_put_efile:
-	fput(efile);
-out_kfree:
-	kfree(event);
-
-	return ret;
-}
-
 static u64 cgroup_clone_children_read(struct cgroup_subsys_state *css,
 				      struct cftype *cft)
 {
@@ -4179,11 +3960,6 @@ static struct cftype cgroup_base_files[] = {
 		.mode = S_IRUGO | S_IWUSR,
 	},
 	{
-		.name = "cgroup.event_control",
-		.write_string = cgroup_write_event_control,
-		.mode = S_IWUGO,
-	},
-	{
 		.name = "cgroup.clone_children",
 		.flags = CFTYPE_INSANE,
 		.read_u64 = cgroup_clone_children_read,
@@ -4567,7 +4343,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
 	__releases(&cgroup_mutex) __acquires(&cgroup_mutex)
 {
 	struct dentry *d = cgrp->dentry;
-	struct cgroup_event *event, *tmp;
 	struct cgroup_subsys *ss;
 	bool empty;
 
@@ -4638,18 +4413,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
 	dget(d);
 	cgroup_d_remove_dir(d);
 
-	/*
-	 * Unregister events and notify userspace.
-	 * Notify userspace about cgroup removing only after rmdir of cgroup
-	 * directory to avoid race between userspace and kernelspace.
-	 */
-	spin_lock(&cgrp->event_list_lock);
-	list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
-		list_del_init(&event->list);
-		schedule_work(&event->remove);
-	}
-	spin_unlock(&cgrp->event_list_lock);
-
 	return 0;
 };
 
mm/memcontrol.c +238 -0

262 lines not on this page · raw message

Signature · 7 lines
1.8.3.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#7 lore raw

Re: [PATCH 3/5] cgroup, memcg: move cgroup_event implementation to memcg

ÓÚ 2013/8/5 0:07, Tejun Heo дµÀ:

Quoted 22 lines

cgroup_event is way over-designed and tries to build a generic flexible event mechanism into cgroup - fully customizable event specification for each user of the interface. This is utterly unnecessary and overboard especially in the light of the planned unified hierarchy as there's gonna be single agent. Simply generating events at fixed points, or if that's too restrictive, configureable cadence or single set of configureable points should be enough.

Thankfully, memcg is the only user and gets to keep it. Replacing it with something simpler on sane_behavior is strongly recommended.

This patch moves cgroup_event and "cgroup.event_control" implementation to mm/memcontrol.c. Clearing of events on cgroup destruction is moved from cgroup_destroy_locked() to mem_cgroup_css_offline(), which shouldn't make any noticeable difference.

Note that "cgroup.event_control" will now exist only on the hierarchy with memcg attached to it. While this change is visible to userland, it is unlikely to be noticeable as the file has never been meaningful outside memcg.

Quoted 9 lines
Cc Johannes Weiner <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Balbir Singh <[email protected]>
---
 kernel/cgroup.c | 237 -------------------------------------------------------
 mm/memcontrol.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 238 insertions(+), 237 deletions(-)

init/Kconfig needs to be updated too:

menuconfig CGROUPS
boolean "Control Group support"
depends on EVENTFD
...
config SCHED_AUTOGROUP
bool "Automatic process group scheduling"
select EVENTFD
select CGROUPS

kernel/cgroup.c line 59

Quoted 10 lines
kernel/cgroup.c +0 -1
index 2583b7b..a0b5e22 100644
@@ -56,7 +56,6 @@
 #include <linux/pid_namespace.h>
 #include <linux/idr.h>
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
-#include <linux/eventfd.h>
 #include <linux/poll.h>

poll.h also can be removed.

Quoted 6 lines
kernel/cgroup.c +0 -0
 #include <linux/flex_array.h> /* used in cgroup_attach_task */
 #include <linux/kthread.h>
@@ -154,36 +153,6 @@ struct css_id {
 	unsigned short stack[0]; /* Array of Length (depth+1) */
 };
 

[...]

mm/memcontrol.c

Quoted 5 lines
mm/memcontrol.c +0 -0
index 2885e3e..3700b65 100644

#include <linux/eventfd.h>
#include <linux/poll.h>

mm/memcontrol.c struct mem_cgroup_eventfd_list { · line 240

Quoted 3 lines
mm/memcontrol.c +0 -0
@@ -239,6 +239,36 @@ struct mem_cgroup_eventfd_list {
 	struct eventfd_ctx *eventfd;
 };

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author maintainer
#8 lore raw

PATCH v2 3/5 cgroup, memcg: move cgroup_event implementation to memcg

In reply to Tejun Heo

From ab9c79598563898b0af18aa26b8a218fe5cbfda6 Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Mon, 5 Aug 2013 12:00:23 -0400

cgroup_event is way over-designed and tries to build a generic flexible event mechanism into cgroup - fully customizable event specification for each user of the interface. This is utterly unnecessary and overboard especially in the light of the planned unified hierarchy as there's gonna be single agent. Simply generating events at fixed points, or if that's too restrictive, configureable cadence or single set of configureable points should be enough.

Thankfully, memcg is the only user and gets to keep it. Replacing it with something simpler on sane_behavior is strongly recommended.

This patch moves cgroup_event and "cgroup.event_control" implementation to mm/memcontrol.c. Clearing of events on cgroup destruction is moved from cgroup_destroy_locked() to mem_cgroup_css_offline(), which shouldn't make any noticeable difference.

Note that "cgroup.event_control" will now exist only on the hierarchy with memcg attached to it. While this change is visible to userland, it is unlikely to be noticeable as the file has never been meaningful outside memcg.

v2: Per Li Zefan's comments, init/Kconfig updated accordingly and
poll.h inclusion moved from cgroup.c to memcontrol.c.

Cc Li Zefan <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Balbir Singh <[email protected]>
---
 init/Kconfig    |   3 +-
 kernel/cgroup.c | 238 -------------------------------------------------------
 mm/memcontrol.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 240 insertions(+), 240 deletions(-)
init/Kconfig +1 -2
index 54d3fa5..b806453 100644
@@ -844,7 +844,6 @@ config NUMA_BALANCING
 
 menuconfig CGROUPS
 	boolean "Control Group support"
-	depends on EVENTFD
 	help
 	  This option adds support for grouping sets of processes together, for
 	  use with process control subsystems such as Cpusets, CFS, memory
@@ -911,6 +910,7 @@ config MEMCG
 	bool "Memory Resource Controller for Control Groups"
 	depends on RESOURCE_COUNTERS
 	select MM_OWNER
+	select EVENTFD
 	help
 	  Provides a memory resource controller that manages both anonymous
 	  memory and page cache. (See Documentation/cgroups/memory.txt)
@@ -1163,7 +1163,6 @@ config UIDGID_STRICT_TYPE_CHECKS
 
 config SCHED_AUTOGROUP
 	bool "Automatic process group scheduling"
-	select EVENTFD
 	select CGROUPS
 	select CGROUP_SCHED
 	select FAIR_GROUP_SCHED
kernel/cgroup.c +0 -238

274 lines not on this page · raw message

mm/memcontrol.c +239 -0

269 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#9 lore raw

Re: [PATCH v2 3/5] cgroup, memcg: move cgroup_event implementation to memcg

mm/memcontrol.c static struct cftype mem_cgroup_files[] = { · line 6199

Quoted 12 lines

static struct cftype mem_cgroup_files[] = {

mm/memcontrol.c +5 -0
 	{
 		.name = "usage_in_bytes",
@@ -5973,6 +6192,12 @@ static struct cftype mem_cgroup_files[] = {
 		.read_u64 = mem_cgroup_hierarchy_read,
 	},
 	{
+		.name = "cgroup.event_control",
+		.write_string = cgroup_write_event_control,
+		.flags = CFTYPE_NO_PREFIX,
+		.mode = S_IWUGO,
+	},

One of the misdesign of cgroup eventfd is, cgroup.event_control is totally redunant...

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#10 lore raw

Re: [PATCH v2 3/5] cgroup, memcg: move cgroup_event implementation to memcg

Quoted 7 lines · Li Zefan
Quoted 7 lines

static struct cftype mem_cgroup_files[] = {

mm/memcontrol.c +0 -0
 	{
 		.name = "usage_in_bytes",
@@ -5973,6 +6192,12 @@ static struct cftype mem_cgroup_files[] = {
 		.read_u64 = mem_cgroup_hierarchy_read,
 	},
 	{
Quoted 9 lines

mm/memcontrol.c static struct cftype mem_cgroup_files[] = { · line 6199

Quoted 5 lines
mm/memcontrol.c +5 -0
+		.name = "cgroup.event_control",
+		.write_string = cgroup_write_event_control,
+		.flags = CFTYPE_NO_PREFIX,
+		.mode = S_IWUGO,
+	},

One of the misdesign of cgroup eventfd is, cgroup.event_control is totally redunant...

ok. write_string() is needed to accept arguments and pass them to the event register function. still not good.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#11 lore raw

Re: [PATCH 3/5] cgroup, memcg: move cgroup_event implementation to memcg

In reply to Tejun Heo
Quoted 5 lines · Tejun Heo

cgroup_event is way over-designed and tries to build a generic flexible event mechanism into cgroup - fully customizable event specification for each user of the interface. This is utterly unnecessary and overboard especially in the light of the planned unified hierarchy as there's gonna be single agent. Simply generating

[off-topic] Has the unified hierarchy been agreed upon? I did not follow that thread

Quoted 3 lines

events at fixed points, or if that's too restrictive, configureable cadence or single set of configureable points should be enough.

Nit-pick: typo on the spelling of configurable

Quoted 9 lines

Thankfully, memcg is the only user and gets to keep it. Replacing it with something simpler on sane_behavior is strongly recommended.

This patch moves cgroup_event and "cgroup.event_control" implementation to mm/memcontrol.c. Clearing of events on cgroup destruction is moved from cgroup_destroy_locked() to mem_cgroup_css_offline(), which shouldn't make any noticeable difference.

Quoted 5 lines

Note that "cgroup.event_control" will now exist only on the hierarchy with memcg attached to it. While this change is visible to userland, it is unlikely to be noticeable as the file has never been meaningful outside memcg.

Tejun, I think the framework was designed to be flexible. Do you see cgroup subsystems never using this?

Quoted 9 lines
Cc Johannes Weiner <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Balbir Singh <[email protected]>
---
 kernel/cgroup.c | 237 -------------------------------------------------------
 mm/memcontrol.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 238 insertions(+), 237 deletions(-)

...

Quoted 117 lines
mm/memcontrol.c +110 -0
+/*
+ * cgroup_event represents events which userspace want to receive.
+ */
+struct cgroup_event {
+       /*
+        * css which the event belongs to.
+        */
+       struct cgroup_subsys_state *css;
+       /*
+        * Control file which the event associated.
+        */
+       struct cftype *cft;
+       /*
+        * eventfd to signal userspace about the event.
+        */
+       struct eventfd_ctx *eventfd;
+       /*
+        * Each of these stored in a list by the cgroup.
+        */
+       struct list_head list;
+       /*
+        * All fields below needed to unregister event when
+        * userspace closes eventfd.
+        */
+       poll_table pt;
+       wait_queue_head_t *wqh;
+       wait_queue_t wait;
+       struct work_struct remove;
+};
+
 static void mem_cgroup_threshold(struct mem_cgroup *memcg);
 static void mem_cgroup_oom_notify(struct mem_cgroup *memcg);
@@ -5926,6 +5956,194 @@ static void kmem_cgroup_css_offline(struct mem_cgroup *memcg)
 }
 #endif
 
+/*
+ * Unregister event and free resources.
+ *
+ * Gets called from workqueue.
+ */
+static void cgroup_event_remove(struct work_struct *work)
+{
+       struct cgroup_event *event = container_of(work, struct cgroup_event,
+                       remove);
+       struct cgroup_subsys_state *css = event->css;
+       struct cgroup *cgrp = css->cgroup;
+
+       remove_wait_queue(event->wqh, &event->wait);
+
+       event->cft->unregister_event(css, event->cft, event->eventfd);
+
+       /* Notify userspace the event is going away. */
+       eventfd_signal(event->eventfd, 1);
+
+       eventfd_ctx_put(event->eventfd);
+       kfree(event);
+       __cgroup_dput(cgrp);
+}
+
+/*
+ * Gets called on POLLHUP on eventfd when user closes it.
+ *
+ * Called with wqh->lock held and interrupts disabled.
+ */
+static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
+               int sync, void *key)
+{
+       struct cgroup_event *event = container_of(wait,
+                       struct cgroup_event, wait);
+       struct cgroup *cgrp = event->css->cgroup;
+       unsigned long flags = (unsigned long)key;
+
+       if (flags & POLLHUP) {
+               /*
+                * If the event has been detached at cgroup removal, we
+                * can simply return knowing the other side will cleanup
+                * for us.
+                *
+                * We can't race against event freeing since the other
+                * side will require wqh->lock via remove_wait_queue(),
+                * which we hold.
+                */
+               spin_lock(&cgrp->event_list_lock);
+               if (!list_empty(&event->list)) {
+                       list_del_init(&event->list);
+                       /*
+                        * We are in atomic context, but cgroup_event_remove()
+                        * may sleep, so we have to call it in workqueue.
+                        */
+                       schedule_work(&event->remove);
+               }
+               spin_unlock(&cgrp->event_list_lock);
+       }
+
+       return 0;
+}
+
+static void cgroup_event_ptable_queue_proc(struct file *file,
+               wait_queue_head_t *wqh, poll_table *pt)
+{
+       struct cgroup_event *event = container_of(pt,
+                       struct cgroup_event, pt);
+
+       event->wqh = wqh;
+       add_wait_queue(wqh, &event->wait);
+}
+
+/*
+ * Parse input and register new memcg event handler.
+ *
+ * Input must be in format '<event_fd> <control_fd> <args>'.
+ * Interpretation of args is defined by control file implementation.
+ */
+static int cgroup_write_event_control(struct cgroup_subsys_state *css,
+                                     struct cftype *cft, const char *buffer)

mm/memcontrol.c static void kmem_cgroup_css_offline(struct mem_cgroup *memcg) · line 6048

Quoted 10 lines
mm/memcontrol.c +10 -0
+{
+       struct cgroup *cgrp = css->cgroup;
+       struct cgroup_event *event;
+       struct cgroup *cgrp_cfile;
+       unsigned int efd, cfd;
+       struct file *efile;
+       struct file *cfile;
+       char *endp;
+       int ret;
+

Can we assert that buffer is NOT NULL here?

mm/memcontrol.c static void kmem_cgroup_css_offline(struct mem_cgroup *memcg) · line 6056

Quoted 8 lines
mm/memcontrol.c +8 -0
+       efd = simple_strtoul(buffer, &endp, 10);
+       if (*endp != ' ')
+               return -EINVAL;
+       buffer = endp + 1;
+
+       cfd = simple_strtoul(buffer, &endp, 10);
+       if ((*endp != ' ') && (*endp != '\0'))
+               return -EINVAL;

Shouldn't we be using kstroull(), I thought the simple functions were obsolete now.

Quoted 94 lines
mm/memcontrol.c +90 -0
+       buffer = endp + 1;
+
+       event = kzalloc(sizeof(*event), GFP_KERNEL);
+       if (!event)
+               return -ENOMEM;
+       event->css = css;
+       INIT_LIST_HEAD(&event->list);
+       init_poll_funcptr(&event->pt, cgroup_event_ptable_queue_proc);
+       init_waitqueue_func_entry(&event->wait, cgroup_event_wake);
+       INIT_WORK(&event->remove, cgroup_event_remove);
+
+       efile = eventfd_fget(efd);
+       if (IS_ERR(efile)) {
+               ret = PTR_ERR(efile);
+               goto out_kfree;
+       }
+
+       event->eventfd = eventfd_ctx_fileget(efile);
+       if (IS_ERR(event->eventfd)) {
+               ret = PTR_ERR(event->eventfd);
+               goto out_put_efile;
+       }
+
+       cfile = fget(cfd);
+       if (!cfile) {
+               ret = -EBADF;
+               goto out_put_eventfd;
+       }
+
+       /* the process need read permission on control file */
+       /* AV: shouldn't we check that it's been opened for read instead? */
+       ret = inode_permission(file_inode(cfile), MAY_READ);
+       if (ret < 0)
+               goto out_put_cfile;
+
+       cgrp_cfile = __cgroup_from_dentry(cfile->f_dentry, &event->cft);
+       if (!cgrp_cfile) {
+               ret = -EINVAL;
+               goto out_put_cfile;
+       }
+
+       /*
+        * The file to be monitored must be in the same cgroup as
+        * cgroup.event_control is.
+        */
+       if (cgrp_cfile != cgrp) {
+               ret = -EINVAL;
+               goto out_put_cfile;
+       }
+
+       if (!event->cft->register_event || !event->cft->unregister_event) {
+               ret = -EINVAL;
+               goto out_put_cfile;
+       }
+
+       ret = event->cft->register_event(css, event->cft,
+                       event->eventfd, buffer);
+       if (ret)
+               goto out_put_cfile;
+
+       efile->f_op->poll(efile, &event->pt);
+
+       /*
+        * Events should be removed after rmdir of cgroup directory, but before
+        * destroying subsystem state objects. Let's take reference to cgroup
+        * directory dentry to do that.
+        */
+       dget(cgrp->dentry);
+
+       spin_lock(&cgrp->event_list_lock);
+       list_add(&event->list, &cgrp->event_list);
+       spin_unlock(&cgrp->event_list_lock);
+
+       fput(cfile);
+       fput(efile);
+
+       return 0;
+
+out_put_cfile:
+       fput(cfile);
+out_put_eventfd:
+       eventfd_ctx_put(event->eventfd);
+out_put_efile:
+       fput(efile);
+out_kfree:
+       kfree(event);
+
+       return ret;
+}
+
 static struct cftype mem_cgroup_files[] = {
        {
                .name = "usage_in_bytes",

mm/memcontrol.c static struct cftype mem_cgroup_files[] = { · line 6197

Quoted 7 lines
mm/memcontrol.c +4 -0
@@ -5973,6 +6191,12 @@ static struct cftype mem_cgroup_files[] = {
                .read_u64 = mem_cgroup_hierarchy_read,
        },
        {
+               .name = "cgroup.event_control",
+               .write_string = cgroup_write_event_control,
+               .flags = CFTYPE_NO_PREFIX,
+               .mode = S_IWUGO,

So everyone has write permissions? I guess we don't want to break this

mm/memcontrol.c static void mem_cgroup_invalidate_reclaim_iterators(struct mem_cgroup *memcg) · line 6532

Quoted 10 lines
mm/memcontrol.c +3 -0
+       },
+       {
                .name = "swappiness",
                .read_u64 = mem_cgroup_swappiness_read,
                .write_u64 = mem_cgroup_swappiness_write,
@@ -6305,6 +6529,20 @@ static void mem_cgroup_invalidate_reclaim_iterators(struct mem_cgroup *memcg)
 static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct cgroup *cgrp = css->cgroup;

With the new refactoring, I presume css and cgroup always co-exist, so css->cgroup cannot change.

Quoted 17 lines
mm/memcontrol.c +13 -1
+       struct cgroup_event *event, *tmp;
+
+       /*
+        * Unregister events and notify userspace.
+        * Notify userspace about cgroup removing only after rmdir of cgroup
+        * directory to avoid race between userspace and kernelspace.
+        */
+       spin_lock(&cgrp->event_list_lock);
+       list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
+               list_del_init(&event->list);
+               schedule_work(&event->remove);
+       }
+       spin_unlock(&cgrp->event_list_lock);
 
        kmem_cgroup_css_offline(memcg);
 
--
Quoted 2 lines

1.8.3.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author maintainer
#12 lore raw

Re: [PATCH 3/5] cgroup, memcg: move cgroup_event implementation to memcg

Hello, Balbir.

Quoted 2 lines · Balbir Singh

[off-topic] Has the unified hierarchy been agreed upon? I did not follow that thread

I consider it agreed upon enough. There of course are objections but I feel fairly comfortable with the amount of existing consensus and considering the current state of cgroup in general, especially the API leaks, I don't think we have many other choices. The devil is always in the details but unless we meet a major technical barrier, I'm pretty sure it's happening.

Quoted 4 lines
Quoted 2 lines

events at fixed points, or if that's too restrictive, configureable cadence or single set of configureable points should be enough.

Nit-pick: typo on the spelling of configurable

Will update.

Quoted 2 lines

Tejun, I think the framework was designed to be flexible. Do you see cgroup subsystems never using this?

I can't be a hundred percent sure that we won't need events which are configureable per-listener but it's highly unlikely given that we're moving onto single agent model and the nature of event delivery - spurious events are unlikely to be noticeable unless the frequency is very high. In general, as anything, aiming for extremes isn't a healthy design practice. Maximum flexibility sounds good in isolation but nothing is free and it entails unneeded complexity both in implementation and usage. Note that even for memcg, both oom and vmpressure don't benefit in any way from all the added complexity at all. The only other place that I can see event being useful at the moment is freezer state change notification and that also would only require unconditional file modified notification.

Quoted 6 lines
Quoted 6 lines
mm/memcontrol.c +6 -0
+static int cgroup_write_event_control(struct cgroup_subsys_state *css,
+                                     struct cftype *cft, const char *buffer)
+{
+       struct cgroup *cgrp = css->cgroup;
+       struct cgroup_event *event;
+       struct cgroup *cgrp_cfile;
Quoted 8 lines

mm/memcontrol.c static void kmem_cgroup_css_offline(struct mem_cgroup *memcg) · line 6048

Quoted 6 lines
mm/memcontrol.c +6 -0
+       unsigned int efd, cfd;
+       struct file *efile;
+       struct file *cfile;
+       char *endp;
+       int ret;
+

Can we assert that buffer is NOT NULL here?

The patch moves the code as-is as things become difficult to review otherwise. After the patchset, it belongs to memcg, please feel free to modify as memcg people see fit.

Thanks.

Signature · 7 lines
tejun

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#13 lore raw

Re: [PATCH 3/5] cgroup, memcg: move cgroup_event implementation to memcg

Quoted 6 lines · Tejun Heo

Hello, Balbir.

Quoted 2 lines · Balbir Singh

[off-topic] Has the unified hierarchy been agreed upon? I did not follow that thread

Quoted 7 lines

I consider it agreed upon enough. There of course are objections but I feel fairly comfortable with the amount of existing consensus and considering the current state of cgroup in general, especially the API leaks, I don't think we have many other choices. The devil is always in the details but unless we meet a major technical barrier, I'm pretty sure it's happening.

I guess we'll need to see what the details look like :)

Quoted 10 lines
Quoted 4 lines
Quoted 2 lines

events at fixed points, or if that's too restrictive, configureable cadence or single set of configureable points should be enough.

Nit-pick: typo on the spelling of configurable

Will update.

Quoted 2 lines

Tejun, I think the framework was designed to be flexible. Do you see cgroup subsystems never using this?

Quoted 13 lines

I can't be a hundred percent sure that we won't need events which are configureable per-listener but it's highly unlikely given that we're moving onto single agent model and the nature of event delivery - spurious events are unlikely to be noticeable unless the frequency is very high. In general, as anything, aiming for extremes isn't a healthy design practice. Maximum flexibility sounds good in isolation but nothing is free and it entails unneeded complexity both in implementation and usage. Note that even for memcg, both oom and vmpressure don't benefit in any way from all the added complexity at all. The only other place that I can see event being useful at the moment is freezer state change notification and that also would only require unconditional file modified notification.

Hmm.. I think it would be interesting to set thresholds on other resources instead of pure monitoring. One might want to set thresholds for CPUACCT usage for example. Freezer is another example like you mentioned.

Quoted 15 lines
Quoted 6 lines
Quoted 6 lines
mm/memcontrol.c +6 -0
+static int cgroup_write_event_control(struct cgroup_subsys_state *css,
+                                     struct cftype *cft, const char *buffer)
+{
+       struct cgroup *cgrp = css->cgroup;
+       struct cgroup_event *event;
+       struct cgroup *cgrp_cfile;
Quoted 8 lines

mm/memcontrol.c static void kmem_cgroup_css_offline(struct mem_cgroup *memcg) · line 6048

Quoted 6 lines
mm/memcontrol.c +6 -0
+       unsigned int efd, cfd;
+       struct file *efile;
+       struct file *cfile;
+       char *endp;
+       int ret;
+

Can we assert that buffer is NOT NULL here?

Quoted 3 lines

The patch moves the code as-is as things become difficult to review otherwise. After the patchset, it belongs to memcg, please feel free to modify as memcg people see fit.

OK, Thanks

Balbir Singh

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author maintainer
#14 lore raw

PATCH 4/5 cgroup, memcg: move cgroup->event_list[_lock] and event callbacks into memcg

In reply to Tejun Heo

cgroup_event is being moved from cgroup core to memcg and the implementation is already moved by the previous patch. This patch moves the data fields and callbacks.

* cgroup->event_list[_lock] are moved to mem_cgroup.

* cftype->[un]register_event() are moved to cgroup_event. This makes it impossible for individual cftype definitions to specify their event callbacks. This is worked around by simply hard-coding filename to event callback mapping in cgroup_write_event_control(). This is awkward and inflexible, which is actually desirable given that we don't want to grow more usages of this feature.

* eventfd_ctx declaration is removed from cgroup.h, which makes vmpressure.h miss eventfd_ctx declaration. Include eventfd.h from vmpressure.h.

Cc Johannes Weiner <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Balbir Singh <[email protected]>
---
 include/linux/cgroup.h     | 24 ---------------
 include/linux/vmpressure.h |  1 +
 kernel/cgroup.c            |  2 --
 mm/memcontrol.c            | 75 ++++++++++++++++++++++++++++++++--------------
 4 files changed, 54 insertions(+), 48 deletions(-)
include/linux/cgroup.h +0 -24
index 2ac1021..e33eb7b 100644
@@ -29,7 +29,6 @@ struct cgroup_subsys;
 struct inode;
 struct cgroup;
 struct css_id;
-struct eventfd_ctx;
 
 extern int cgroup_init_early(void);
 extern int cgroup_init(void);
@@ -233,10 +232,6 @@ struct cgroup {
 	struct work_struct destroy_work;
 	atomic_t css_kill_cnt;
 
-	/* List of events which userspace want to receive */
-	struct list_head event_list;
-	spinlock_t event_list_lock;
-
 	/* directory xattrs */
 	struct simple_xattrs xattrs;
 };
@@ -500,25 +495,6 @@ struct cftype {
 	int (*trigger)(struct cgroup_subsys_state *css, unsigned int event);
 
 	int (*release)(struct inode *inode, struct file *file);
-
-	/*
-	 * register_event() callback will be used to add new userspace
-	 * waiter for changes related to the cftype. Implement it if
-	 * you want to provide this functionality. Use eventfd_signal()
-	 * on eventfd to send notification to userspace.
-	 */
-	int (*register_event)(struct cgroup_subsys_state *css,
-			      struct cftype *cft, struct eventfd_ctx *eventfd,
-			      const char *args);
-	/*
-	 * unregister_event() callback will be called when userspace
-	 * closes the eventfd or on cgroup removing.
-	 * This callback must be implemented, if you want provide
-	 * notification functionality.
-	 */
-	void (*unregister_event)(struct cgroup_subsys_state *css,
-				 struct cftype *cft,
-				 struct eventfd_ctx *eventfd);
 };
 
 /*
include/linux/vmpressure.h +1 -0
index b239482..324ea7a 100644
@@ -7,6 +7,7 @@
 #include <linux/gfp.h>
 #include <linux/types.h>
 #include <linux/cgroup.h>
+#include <linux/eventfd.h>
 
 struct vmpressure {
 	unsigned long scanned;
kernel/cgroup.c +0 -2
index a0b5e22..2bc45d3 100644
@@ -1352,8 +1352,6 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
 	INIT_LIST_HEAD(&cgrp->pidlists);
 	mutex_init(&cgrp->pidlist_mutex);
 	cgrp->dummy_css.cgroup = cgrp;
-	INIT_LIST_HEAD(&cgrp->event_list);
-	spin_lock_init(&cgrp->event_list_lock);
 	simple_xattrs_init(&cgrp->xattrs);
 }
 
mm/memcontrol.c +53 -22

176 lines not on this page · raw message

Signature · 7 lines
1.8.3.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
author maintainer
#15 lore raw

PATCH 5/5 memcg: rename cgroup_event to mem_cgroup_event

In reply to Tejun Heo

cgroup_event is only available in memcg now. Let's brand it that way. While at it, add a comment encouraging deprecation of the feature and remove the respective section from cgroup documentation.

This patch is cosmetic.

---
 Documentation/cgroups/cgroups.txt | 19 -------------
 mm/memcontrol.c                   | 57 +++++++++++++++++++++++++--------------
 2 files changed, 37 insertions(+), 39 deletions(-)
Documentation/cgroups/cgroups.txt +0 -19
index 638bf17..ca5aee9 100644
@@ -472,25 +472,6 @@ you give a subsystem a name.
 The name of the subsystem appears as part of the hierarchy description
 in /proc/mounts and /proc/<pid>/cgroups.
 
-2.4 Notification API
---------------------
-
-There is mechanism which allows to get notifications about changing
-status of a cgroup.
-
-To register a new notification handler you need to:
- - create a file descriptor for event notification using eventfd(2);
- - open a control file to be monitored (e.g. memory.usage_in_bytes);
- - write "<event_fd> <control_fd> <args>" to cgroup.event_control.
-   Interpretation of args is defined by control file implementation;
-
-eventfd will be woken up by control file implementation or when the
-cgroup is removed.
-
-To unregister a notification handler just close eventfd.
-
-NOTE: Support of notifications should be implemented for the control
-file. See documentation for the subsystem.
 
 3. Kernel API
 =============
mm/memcontrol.c +37 -20

127 lines not on this page · raw message

Signature · 7 lines
1.8.3.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#16 lore raw

Re: [PATCH 5/5] memcg: rename cgroup_event to mem_cgroup_event

Quoted 17 lines · Tejun Heo

cgroup_event is only available in memcg now. Let's brand it that way. While at it, add a comment encouraging deprecation of the feature and remove the respective section from cgroup documentation.

This patch is cosmetic.

---
 Documentation/cgroups/cgroups.txt | 19 -------------
 mm/memcontrol.c                   | 57 +++++++++++++++++++++++++--------------
 2 files changed, 37 insertions(+), 39 deletions(-)
Documentation/cgroups/cgroups.txt +0 -0
index 638bf17..ca5aee9 100644

Documentation/cgroups/cgroups.txt you give a subsystem a name. · line 474

Quoted 3 lines
Documentation/cgroups/cgroups.txt +0 -0
@@ -472,25 +472,6 @@ you give a subsystem a name.
 The name of the subsystem appears as part of the hierarchy description
 in /proc/mounts and /proc/<pid>/cgroups.
 

2. Usage Examples and Syntax
2.1 Basic Usage
2.2 Attaching processes
2.3 Mounting hierarchies by name
2.4 Notification API

remove the index ?

Quoted 10 lines
Documentation/cgroups/cgroups.txt +0 -10
-2.4 Notification API
---------------------
-
-There is mechanism which allows to get notifications about changing
-status of a cgroup.
-
-To register a new notification handler you need to:
- - create a file descriptor for event notification using eventfd(2);
- - open a control file to be monitored (e.g. memory.usage_in_bytes);
- - write "<event_fd> <control_fd> <args>" to cgroup.event_control.

Documentation/cgroups/cgroups.txt you give a subsystem a name. · line 475

Quoted 10 lines
Documentation/cgroups/cgroups.txt +0 -9
-   Interpretation of args is defined by control file implementation;
-
-eventfd will be woken up by control file implementation or when the
-cgroup is removed.
-
-To unregister a notification handler just close eventfd.
-
-NOTE: Support of notifications should be implemented for the control
-file. See documentation for the subsystem.
 

Why not move this section to Documentation/cgroups/memory.txt?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author maintainer
#17 lore raw

PATCH v2 5/5 memcg: rename cgroup_event to mem_cgroup_event

In reply to Tejun Heo

From 2d3340a32a52602ec4cda348b26affeae52d1964 Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Mon, 5 Aug 2013 12:00:24 -0400

cgroup_event is only available in memcg now. Let's brand it that way. While at it, add a comment encouraging deprecation of the feature and remove the respective section from cgroup documentation.

This patch is cosmetic.

v2: Index in cgroups.txt updated accordingly as suggested by Li Zefan.

---
 Documentation/cgroups/cgroups.txt | 20 --------------
 mm/memcontrol.c                   | 57 +++++++++++++++++++++++++--------------
 2 files changed, 37 insertions(+), 40 deletions(-)
Documentation/cgroups/cgroups.txt +0 -20
index 638bf17..821de56 100644
@@ -24,7 +24,6 @@ CONTENTS:
   2.1 Basic Usage
   2.2 Attaching processes
   2.3 Mounting hierarchies by name
-  2.4 Notification API
 3. Kernel API
   3.1 Overview
   3.2 Synchronization
@@ -472,25 +471,6 @@ you give a subsystem a name.
 The name of the subsystem appears as part of the hierarchy description
 in /proc/mounts and /proc/<pid>/cgroups.
 
-2.4 Notification API
---------------------
-
-There is mechanism which allows to get notifications about changing
-status of a cgroup.
-
-To register a new notification handler you need to:
- - create a file descriptor for event notification using eventfd(2);
- - open a control file to be monitored (e.g. memory.usage_in_bytes);
- - write "<event_fd> <control_fd> <args>" to cgroup.event_control.
-   Interpretation of args is defined by control file implementation;
-
-eventfd will be woken up by control file implementation or when the
-cgroup is removed.
-
-To unregister a notification handler just close eventfd.
-
-NOTE: Support of notifications should be implemented for the control
-file. See documentation for the subsystem.
 
 3. Kernel API
 =============
mm/memcontrol.c +37 -20

127 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#18 lore raw
In reply to Tejun Heo
Quoted 1 line · Tejun Heo

Hello,

Hi Tejun,

Quoted 4 lines

Like many other things in cgroup, cgroup_event is way too flexible and complex - it strives to provide completely flexible event monitoring facility in cgroup proper which allows any number of users to monitor custom events. This is overboard, to say the least,

Could you be more specific about what is so "overboard" about this interface? I am not familiar with internals much, so I cannot judge the complexity part, but I thought that eventfd was intended for this kind of kernel->userspace notifications.

Quoted 3 lines

and I strongly think that cgroup should not any new usages of this facility and preferably deprecate the existing usages if at all possible.

So you think that vmpressure, oom notification or thresholds are an abuse of this interface? What would you consider a reasonable replacement for those notifications? Or do you think that controller shouldn't be signaling any conditions to the userspace at all?

[...]

Signature · 2 lines
Michal Hocko
SUSE Labs
author maintainer
#19 lore raw

Hello, Michal.

Quoted 4 lines · Michal Hocko

Could you be more specific about what is so "overboard" about this interface? I am not familiar with internals much, so I cannot judge the complexity part, but I thought that eventfd was intended for this kind of kernel->userspace notifications.

It's just way over-engineered like many other things in cgroup, most likely misguided by the appearance that cgroup could be delegated and accessed by multiple actors concurrently.

The most clear example would be the vmpressure event. When it could have just called fsnotify_modify() unconditionally when the state changes, now it involves parsing, dynamic list of events and so on without actually adding any benefits. For the usage ones, configurability makes some sense but even then just giving it a single array of event points of limited size would be sufficient.

It's just way over-done.

Quoted 4 lines

So you think that vmpressure, oom notification or thresholds are an abuse of this interface? What would you consider a reasonable replacement for those notifications? Or do you think that controller shouldn't be signaling any conditions to the userspace at all?

I don't think the ability to generate events are an abuse, just that the facility itself is way over-engineered. Just generate a file changed event unconditionally for vmpressure and oom and maybe implement configureable cadence or single set of threshold array for threshold events. These are things which can and should be done in a a few tens of lines of code with far simpler interface. There's no need for this obsecenely flexible event infrastructure, which of course leads to things like shared contiguous threshold table without any size limit and allocated with kmalloc().

So, let's please move towards something simple.

Thanks.

Signature · 7 lines
tejun

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#20 lore raw
Quoted 11 lines · Tejun Heo

Hello, Michal.

Quoted 4 lines · Michal Hocko

Could you be more specific about what is so "overboard" about this interface? I am not familiar with internals much, so I cannot judge the complexity part, but I thought that eventfd was intended for this kind of kernel->userspace notifications.

It's just way over-engineered like many other things in cgroup, most likely misguided by the appearance that cgroup could be delegated and accessed by multiple actors concurrently.

I keep hearing that over and over. And I also keep hearing that there are users who do not like many simplifications because they are breaking their usecases. Users are those who matter to me. Hey some of them are even sane...

Quoted 4 lines

The most clear example would be the vmpressure event. When it could have just called fsnotify_modify() unconditionally when the state changes, now it involves parsing, dynamic list of events and so on without actually adding any benefits.

I am neither author nor user of this interface but my understanding is that there are different requirements from different usecases and it would be hard to satisfy them without having a way for userspace to tell the kernel what it is interested in. There was a discussion about edge vs. all-events triggered signaling recently for example.

Besides that, is fsnotify really an interface to be used under memory pressure? I might be wrong but from a quick look fsnotify depends on GFP_KERNEL allocation which would be no-go for oom_control at least. How does the reclaim context gets to struct file to notify? I am pretty sure we would get to more and more questions when digging further.

I am all for simplifications, but removing interfaces just because you feel they are "over-done" is not a way to go IMHO. In this particular case you are removing an interface from cgroup core which has users, and will have to support them for very long time. "It is just memcg so move it there" is not a way that different subsystems should work together and I am _not_ going to ack such a move. All the flexibility that you are so complaining about is hidden from the cgroup core in register callbacks and the rest is only the core infrastructure (registration and unregistration).

And btw. a common notification interface at least makes things consistent and prevents controllers to invent their one purpose solutions.

So I am really skeptical about this patch set. It doesn't give anything. It just moves a code which you do not like out of your sight hoping that something will change.

There were mistakes done in the past. And some interfaces are really too flexible but that doesn't mean we should be militant about everything.

Quoted 3 lines

For the usage ones, configurability makes some sense but even then just giving it a single array of event points of limited size would be sufficient.

This would be a question for users. I am not one of those so I cannot tell you but I certainly cannot claim that something more coarse would be sufficient either.

Quoted 7 lines

It's just way over-done.

Quoted 4 lines

So you think that vmpressure, oom notification or thresholds are an abuse of this interface? What would you consider a reasonable replacement for those notifications? Or do you think that controller shouldn't be signaling any conditions to the userspace at all?

Quoted 6 lines

I don't think the ability to generate events are an abuse, just that the facility itself is way over-engineered. Just generate a file changed event unconditionally for vmpressure and oom and maybe implement configureable cadence or single set of threshold array for threshold events. These are things which can and should be done in a a few tens of lines of code with far simpler interface.

These are strong words without any justification.

[...]

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
author maintainer
#21 lore raw

Hey, Michal.

Quoted 4 lines · Michal Hocko

I keep hearing that over and over. And I also keep hearing that there are users who do not like many simplifications because they are breaking their usecases. Users are those who matter to me. Hey some of them are even sane...

There needs to be some balance between serving use cases and cutting off edge ones which pollutes the code with unjustified complexity. We went way far to one end and are trying to cut back, so complaints are expected.

Quoted 3 lines

Besides that, is fsnotify really an interface to be used under memory pressure? I might be wrong but from a quick look fsnotify depends on GFP_KERNEL allocation which would be no-go for oom_control at least.

Yeap, I'm pretty sure you're wrong. I didn't follow the development but this is wrapper to combine inotify and dnotify and kernel's main FS event mechanism and none of the two mechanisms required memory allocation during delivery.

Quoted 2 lines

How does the reclaim context gets to struct file to notify? I am pretty sure we would get to more and more questions when digging further.

The file is optional and probably just to extract path for dnotify, I think. Not sure about namespace implications but I'll build cgroup level interface for it so that controllers won't have to deal with it directly. ie. there'll be css_notify_file(css, cfe) interface.

Quoted 2 lines

I am all for simplifications, but removing interfaces just because you feel they are "over-done" is not a way to go IMHO. In this particular

We can keep it around but it's a pretty good time to gradually move towards something saner as we're essentially doing v2 of the interface. Note that there's no reason for the interface to disappear immediately. You can keep it and there won't be any problem for it to co-exist with simpler mechanism.

Quoted 7 lines

case you are removing an interface from cgroup core which has users, and will have to support them for very long time. "It is just memcg so move it there" is not a way that different subsystems should work together and I am _not_ going to ack such a move. All the flexibility that you are so complaining about is hidden from the cgroup core in register callbacks and the rest is only the core infrastructure (registration and unregistration).

memcg is the only user and will stay that way. If you wanna keep it around, be my guest. Also, cftype is planned to be simplified so that it just provides seq_file interface and the types become helper routines like a normal file callback interface. There'll be nothing tying the event file handling to cgroup core and it surely won't be used by anyone else. memcg is and will be the only user. It's the natural place for the code.

Quoted 3 lines

And btw. a common notification interface at least makes things consistent and prevents controllers to invent their one purpose solutions.

We'll surely have a common notification interface which is simple - basically just one function - as it should be.

Quoted 7 lines

So I am really skeptical about this patch set. It doesn't give anything. It just moves a code which you do not like out of your sight hoping that something will change.

There were mistakes done in the past. And some interfaces are really too flexible but that doesn't mean we should be militant about everything.

Quoted 7 lines
Quoted 3 lines

For the usage ones, configurability makes some sense but even then just giving it a single array of event points of limited size would be sufficient.

This would be a question for users. I am not one of those so I cannot tell you but I certainly cannot claim that something more coarse would be sufficient either.

I can tell you because there will be a single agent of the hierarchy with unified hierarchy and both control and events will be routed through it. As such usage restriction rises from inherent properties of the current cgroup design and implementation, it isn't something which can be properly worked around.

Quoted 7 lines
Quoted 7 lines

It's just way over-done.

Quoted 4 lines

So you think that vmpressure, oom notification or thresholds are an abuse of this interface? What would you consider a reasonable replacement for those notifications? Or do you think that controller shouldn't be signaling any conditions to the userspace at all?

Quoted 8 lines
Quoted 6 lines

I don't think the ability to generate events are an abuse, just that the facility itself is way over-engineered. Just generate a file changed event unconditionally for vmpressure and oom and maybe implement configureable cadence or single set of threshold array for threshold events. These are things which can and should be done in a a few tens of lines of code with far simpler interface.

These are strong words without any justification.

If you think this level of flexibility is healthy, we'll have to agree to disagree. Just look at it this way - this is memcg specific piece of code and this patchset is just natural reorganization of code.

Thanks.

Signature · 7 lines
tejun

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#22 lore raw
Quoted 3 lines · Tejun Heo

Hey, Michal.

On Mon, Aug 05, 2013 at 09:16:41PM +0200, Michal Hocko wrote:

[...]

Quoted 8 lines
Quoted 3 lines

Besides that, is fsnotify really an interface to be used under memory pressure? I might be wrong but from a quick look fsnotify depends on GFP_KERNEL allocation which would be no-go for oom_control at least.

Yeap, I'm pretty sure you're wrong. I didn't follow the development but this is wrapper to combine inotify and dnotify and kernel's main FS event mechanism and none of the two mechanisms required memory allocation during delivery.

I might be really wrong here (I see memory allocations down the fsnotify_modify callpath) but this is totally irrelevant to the patchset.

If there is a better interface in the future then I have no objection to move to it and keep the old one just for legacy usage for certain amount of time. I am definitely not arguing for eventfd being the best interface.

I am objecting to moving the generic part of that code into memcg. The memcg part and the additional complexity (all the parsing and conditions for signalling) is already in the memcg code.

Quoted 7 lines
Quoted 2 lines

How does the reclaim context gets to struct file to notify? I am pretty sure we would get to more and more questions when digging further.

The file is optional and probably just to extract path for dnotify, I think. Not sure about namespace implications but I'll build cgroup level interface for it so that controllers won't have to deal with it directly. ie. there'll be css_notify_file(css, cfe) interface.

Such an interface would be really welcome but I would also ask how it would implement/allow context passing. E.g. how do we know which treshold has been reached? How do we find out the vmpressure level? Is the consumer supposed to do an additional action after it gets notification?
Etc.

Quoted 8 lines
Quoted 2 lines

I am all for simplifications, but removing interfaces just because you feel they are "over-done" is not a way to go IMHO. In this particular

We can keep it around but it's a pretty good time to gradually move towards something saner as we're essentially doing v2 of the interface. Note that there's no reason for the interface to disappear immediately. You can keep it and there won't be any problem for it to co-exist with simpler mechanism.

Yes that is an expectation of the users...

Quoted 10 lines
Quoted 7 lines

case you are removing an interface from cgroup core which has users, and will have to support them for very long time. "It is just memcg so move it there" is not a way that different subsystems should work together and I am _not_ going to ack such a move. All the flexibility that you are so complaining about is hidden from the cgroup core in register callbacks and the rest is only the core infrastructure (registration and unregistration).

memcg is the only user and will stay that way. If you wanna keep it around, be my guest.

OK, so why do you move the generic part to the memcg then?

Quoted 6 lines

Also, cftype is planned to be simplified so that
it just provides seq_file interface and the types become helper routines like a normal file callback interface. There'll be nothing tying the event file handling to cgroup core and it surely won't be used by anyone else. memcg is and will be the only user. It's the natural place for the code.

Really that natural? So memcg should touch internals like cgroup dentry reference counting. You seem have forgotten all the hassles with cgroup_mutex, haven't you?
No that part doesn't belong to memcg! You can discourage from new usage of this interface of course.

Signature · 2 lines
Michal Hocko
SUSE Labs
author maintainer
#23 lore raw

Hello, Michal.

Quoted 3 lines · Michal Hocko

I am objecting to moving the generic part of that code into memcg. The memcg part and the additional complexity (all the parsing and conditions for signalling) is already in the memcg code.

But how is it generic if it's specific to memcg? The practical purpose here is making it clear that the interface is only used by memcg and preventing any new usages from sprining up and the best way to achieve that is making the code actually memcg-specific. It also helps cleaning up cftype in general. I'm not sure what you're objecting to here.

Quoted 6 lines

Such an interface would be really welcome but I would also ask how it would implement/allow context passing. E.g. how do we know which treshold has been reached? How do we find out the vmpressure level? Is the consumer supposed to do an additional action after it gets notification?
Etc.

Yeap, exactly and that's how it should have been from the beginning. Attaching information to notification itself isn't a particularly good design (anyone remembers rtsig?) if there's polling mechanism to report the current state. It essentially amounts to duplicate delivery mechanisms for the same information, which you usually don't want. Here, the inconvenience / performance implications are negligible or even net-positive. Plain file modified notification is way more familiar / conventional and the overhead of an extra read call, which is highly unlikely to be relevant given the expected frequency of the events we're talking about, is small compared to the action of event delivery and context switch.

Quoted 1 line

Really that natural? So memcg should touch internals like cgroup dentry

Functionally, it is completely specific to memcg at this point. It's the only user and will stay the only user.

Quoted 2 lines

reference counting. You seem have forgotten all the hassles with cgroup_mutex, haven't you?

Was the above sentence necessary?

Quoted 2 lines

No that part doesn't belong to memcg! You can discourage from new usage of this interface of course.

Oh, if you're objecting to the details of the implementation, we of course can clean it up. It should conceptually and functionally be part of memcg and that is the guiding line we follow. Implementations follow the concepts and functions, not the other way around. The refcnt of course can be replaced with memcg css refcnting and we can of course factor out dentry comparison in a prettier form.

Compare it to the other way around - having event callbacks in cftype and clearing code embedded in cgroup core destruction path when both of which are completely irrelevant to all other controllers. Let's clean up the implementation details and put things where they belong. What's the excuse for not doing so when it's almost trivially doable?

Thanks.

Signature · 7 lines
tejun

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#24 lore raw
Quoted 8 lines · Tejun Heo

Hello, Michal.

Quoted 3 lines · Michal Hocko

I am objecting to moving the generic part of that code into memcg. The memcg part and the additional complexity (all the parsing and conditions for signalling) is already in the memcg code.

But how is it generic if it's specific to memcg?

How is it specific to memcg? The fact only memcg uses the interface doesn't imply it is memcg specific.

Quoted 4 lines

The practical
purpose here is making it clear that the interface is only used by memcg and preventing any new usages from sprining up and the best way to achieve that is making the code actually memcg-specific.

There are other ways to achieve the same. E.g. not ack new usage of register callback users. We have done similar with other things like use_hierarchy...

Quoted 2 lines

It also helps cleaning up cftype in general. I'm not sure what you're objecting to here.

The cleanup is removing 2 callbacks with a cost of moving non-memcg specific code inside memcg. That is what I am objecting to.

Quoted 11 lines
Quoted 6 lines

Such an interface would be really welcome but I would also ask how it would implement/allow context passing. E.g. how do we know which treshold has been reached? How do we find out the vmpressure level? Is the consumer supposed to do an additional action after it gets notification?
Etc.

Yeap, exactly and that's how it should have been from the beginning. Attaching information to notification itself isn't a particularly good design (anyone remembers rtsig?) if there's polling mechanism to report the current state.

There are pros and cons for both approaches and it should be discussed in a separate thread with a code to back all the claims.

Quoted 29 lines

It essentially amounts to duplicate delivery mechanisms for the same information, which you usually don't want. Here, the inconvenience / performance implications are negligible or even net-positive. Plain file modified notification is way more familiar / conventional and the overhead of an extra read call, which is highly unlikely to be relevant given the expected frequency of the events we're talking about, is small compared to the action of event delivery and context switch.

Quoted 1 line

Really that natural? So memcg should touch internals like cgroup dentry

Functionally, it is completely specific to memcg at this point. It's the only user and will stay the only user.

Quoted 2 lines

reference counting. You seem have forgotten all the hassles with cgroup_mutex, haven't you?

Was the above sentence necessary?

Quoted 2 lines

No that part doesn't belong to memcg! You can discourage from new usage of this interface of course.

Oh, if you're objecting to the details of the implementation, we of course can clean it up. It should conceptually and functionally be part of memcg and that is the guiding line we follow. Implementations follow the concepts and functions, not the other way around. The refcnt of course can be replaced with memcg css refcnting and we can of course factor out dentry comparison in a prettier form.

Quoted 5 lines

Compare it to the other way around - having event callbacks in cftype and clearing code embedded in cgroup core destruction path when both of which are completely irrelevant to all other controllers. Let's clean up the implementation details and put things where they belong. What's the excuse for not doing so when it's almost trivially doable?

I will not repeat myself. We seem to disagree on where the code belongs. As I've said I will not ack this code, try to find somebody else who think it is a good idea. I do not see any added value.

Signature · 8 lines
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
author maintainer
#25 lore raw

Hello, Michal.

Quoted 2 lines · Michal Hocko

How is it specific to memcg? The fact only memcg uses the interface doesn't imply it is memcg specific.

I don't follow. It's only for memcg. That is *by definition* memcg specific. It's the verbatim meaning of the word. Now, I do understand that it can be a concern the implementation details as-is could be a bit too invasive into cgroup core to be moved to memcg, but that's something we can work on, right? Can you at least agree that the feature is nmemcg specific and it'd be better to be located in memcg if possible? That really isn't not much to ask and is a logical thing to do.

Quoted 3 lines

There are other ways to achieve the same. E.g. not ack new usage of register callback users. We have done similar with other things like use_hierarchy...

Yes, but those are all inferior to actually moving the code where it belongs. Those makes the code harder to follow and people misunderstand and waste time working on stuff (either in the core or controllers) which eventually end up getting nacked. Why do that when we can easily do better? What's the rationale behind that?

Quoted 2 lines

The cleanup is removing 2 callbacks with a cost of moving non-memcg specific code inside memcg. That is what I am objecting to.

I don't really get your "non-memcg" specific code assertion when it is by definition memcg-specific. What are you talking about?

Quoted 3 lines

I will not repeat myself. We seem to disagree on where the code belongs. As I've said I will not ack this code, try to find somebody else who think it is a good idea. I do not see any added value.

Nacking is part of your authority as maintainer but you should still provide plausible rationale for that. Are you saying that even if the code is restructured so that it's not invasive into cgroup core, you are still gonna disagree with it because it's still somehow not memcg-specifc? Please don't repeat yourself but do explain your rationale. That's part of your duty as a maintainer too.

Thanks.

Signature · 7 lines
tejun

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#26 lore raw
Quoted 8 lines · Tejun Heo

Hello, Michal.

Quoted 2 lines · Michal Hocko

How is it specific to memcg? The fact only memcg uses the interface doesn't imply it is memcg specific.

I don't follow. It's only for memcg. That is *by definition* memcg specific. It's the verbatim meaning of the word.

My understanding of "memcg specific" is that it uses memcg specific code/data structures. But let's not play with words.

Quoted 4 lines

Now, I do
understand that it can be a concern the implementation details as-is could be a bit too invasive into cgroup core to be moved to memcg, but that's something we can work on, right?

Does it really make sense to work on this interface if it is planned to be replaced by something different. Isn't that just a waste of time?

Quoted 3 lines

Can you at least agree that the feature is nmemcg specific and it'd be better to be located in memcg if possible? That really isn't not much to ask and is a logical thing to do.

I would rather see it not changed unless it really is a big win in the cgroup core. So far I do not see anything like that (just look at __cgroup_from_dentry which needs to be exported to allow for the move). You reduce the amount of code in cgroup.c, alright, but the code doesn't go away really. It just moves out of your sight and moves the same burden on somebody else without providing a new generic interface.

Quoted 9 lines
Quoted 3 lines

There are other ways to achieve the same. E.g. not ack new usage of register callback users. We have done similar with other things like use_hierarchy...

Yes, but those are all inferior to actually moving the code where it belongs. Those makes the code harder to follow and people misunderstand and waste time working on stuff (either in the core or controllers) which eventually end up getting nacked. Why do that when we can easily do better? What's the rationale behind that?

If somebody needs a notification interface (and there is no one available right now) then you cannot prevent from such a pointless work anyway...

Quoted 5 lines
Quoted 2 lines

The cleanup is removing 2 callbacks with a cost of moving non-memcg specific code inside memcg. That is what I am objecting to.

I don't really get your "non-memcg" specific code assertion when it is by definition memcg-specific. What are you talking about?

cgroup_event_* don't sound memcg specific at all. They are playing with cgroup dentry reference counting and do a generic functionality which memcg doesn't need to know about.

Quoted 6 lines
Quoted 3 lines

I will not repeat myself. We seem to disagree on where the code belongs. As I've said I will not ack this code, try to find somebody else who think it is a good idea. I do not see any added value.

Nacking is part of your authority as maintainer but you should still provide plausible rationale for that.

I didn't say I Nack it. I said I won't Ack it. If Johannes or Kamezawa think this is OK and another bloat in memcg is not a big deal I will not block it. I won't be happy but how is the life.

Quoted 4 lines

Are you saying that even if the
code is restructured so that it's not invasive into cgroup core, you are still gonna disagree with it because it's still somehow not memcg-specifc?

I wouldn't object to having non-cgroup internals playing variant. I just do not think it makes sense to invest time to something that should go away long term.

Quoted 2 lines

Please don't repeat yourself but do explain your rationale. That's part of your duty as a maintainer too.

I think I am clear what I do not like about this move.

Signature · 2 lines
Michal Hocko
SUSE Labs
author maintainer
#27 lore raw

Hello, Michal.

Quoted 3 lines · Michal Hocko

I would rather see it not changed unless it really is a big win in the cgroup core. So far I do not see anything like that (just look at __cgroup_from_dentry which needs to be exported to allow for the move).

The end goal is cleaning up cftype so that it becomes a thin wrapper around seq_file and I'd really like to keep the interface minimal so that it's difficult to misunderstand.

Quoted 3 lines

You reduce the amount of code in cgroup.c, alright, but the code doesn't go away really. It just moves out of your sight and moves the same burden on somebody else without providing a new generic interface.

If the implementation details are all that you're objecting, I'll be happy to restructure it. I just didn't pay too much attention to it because I considered it to be mostly deprecated. I don't think it'll be too much work and strongly think it'll be worth the effort. Our code base is extremely nasty is and I'll try to get any ounce of cleanup I can get.

Quoted 2 lines

If somebody needs a notification interface (and there is no one available right now) then you cannot prevent from such a pointless work anyway...

I'm gonna add one for freezer state transitions. It'll be simple "this file changed" thing and will probably apply that to at least oom and vmpressure. I'm relatively confident that it's gonna be pretty simple and that's gonna be the cgroup event mechanism.

Quoted 3 lines

cgroup_event_* don't sound memcg specific at all. They are playing with cgroup dentry reference counting and do a generic functionality which memcg doesn't need to know about.

Sure, I'll try to clean it up so that it doesn't meddle with cgroup internals directly.

Quoted 3 lines

I wouldn't object to having non-cgroup internals playing variant. I just do not think it makes sense to invest time to something that should go away long term.

I suppose it's priority thing. To me, cleaning up cgroup core API is quite important and I'd be happy to sink time and effort into it and it's not like we can drop the event thing in a release cycle or two. We'd have to carry it for years, so I think the effort is justified.

Thanks.

Signature · 7 lines
tejun

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#28 lore raw
Quoted 8 lines
Quoted 2 lines

If somebody needs a notification interface (and there is no one available right now) then you cannot prevent from such a pointless work anyway...

I'm gonna add one for freezer state transitions. It'll be simple "this file changed" thing and will probably apply that to at least oom and vmpressure. I'm relatively confident that it's gonna be pretty simple and that's gonna be the cgroup event mechanism.

I would like to see this happen. I have a feeling that we're deprecating features a bit aggressively without providing alternatives.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author maintainer
#29 lore raw

Hello, Li.

Quoted 2 lines · Li Zefan

I would like to see this happen. I have a feeling that we're deprecating features a bit aggressively without providing alternatives.

I'd rework it prolly next week but this has to go one way or another. There's no way we're implementing userland interface this complex in cgroup proper. It is a gross layering violation. We don't implement userland visible interface this complex in low level subsystems. It's wrong both in principle and leads to all sorts of problems in practice like ending up worrying about userland abuses in memcg event source implementation, which is utterly bonkers if you ask me.

Thanks.

Signature · 7 lines
tejun

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>