Linux Container Development
 help / color / mirror / Atom feed
From: Pavel Emelyanov <xemul-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
To: Serge Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>,
	"Eric W. Biederman"
	<ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>,
	Daniel Lezcano <dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>,
	Cedric Le Goater <clg-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
Cc: Linux Containers <containers-qjLDD68F18O7TbgM5vRIOg@public.gmane.org>
Subject: [PATCH 1/3] The sysctl shadows
Date: Tue, 20 Nov 2007 14:43:42 +0300	[thread overview]
Message-ID: <4742C86E.6060705@openvz.org> (raw)
In-Reply-To: <4742C73C.3010904-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>

The sysctl shadow is nothing but a ctl_table_head, that
hides behind some other one and which is used in
proc_sys_readdir, proc_sys_lookup, etc when scanning
through the list of these heads.

Each "shadow" carries its own set of ctl_tables that
are relevant to this shadow. The appropriate shadow
is get via the ->shadow() callback on the head.

When putting the shadow back (unuse it) one should
work with the shadow->origin head.

The API:
 * register_sysctl_table_shadow: registers the ctl
   table and tells that is will be shadowed with
   the specified callback;
 * create_sysctl_shadow: clones the original head's
   table and creates a shadow for it. The caller then
   may move the ctl_table->data pointer on the new
   (shadow) tables to point to another variables.
   It may also change names for tables, etc;
 * free_sysctl_shadow: destroys the shadow.

Signed-off-by: Pavel Emelyanov <xemul-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>

---

diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 4f5047d..064f132 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -1057,9 +1057,16 @@ struct ctl_table_header
 	struct list_head ctl_entry;
 	int used;
 	struct completion *unregistering;
+	struct ctl_table_header *(*shadow)(struct ctl_table_header *);
+	struct ctl_table_header *origin;
 };
 
 struct ctl_table_header *register_sysctl_table(struct ctl_table * table);
+struct ctl_table_header *register_sysctl_table_shadow(struct ctl_table * table,
+		struct ctl_table_header *(*shadow)(struct ctl_table_header *));
+
+struct ctl_table_header *create_sysctl_shadow(struct ctl_table_header *h);
+void free_sysctl_shadow(struct ctl_table_header *h);
 
 void unregister_sysctl_table(struct ctl_table_header * table);
 int sysctl_check_table(struct ctl_table *table);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 489b0d1..bfea4fa 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1320,6 +1320,9 @@ void sysctl_head_finish(struct ctl_table_header *head)
 {
 	if (!head)
 		return;
+	if (head->origin)
+		head = head->origin;
+
 	spin_lock(&sysctl_lock);
 	unuse_table(head);
 	spin_unlock(&sysctl_lock);
@@ -1331,6 +1334,9 @@ struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
 	struct list_head *tmp;
 	spin_lock(&sysctl_lock);
 	if (prev) {
+		if (prev->origin != NULL)
+			prev = prev->origin;
+
 		tmp = &prev->ctl_entry;
 		unuse_table(prev);
 		goto next;
@@ -1342,6 +1348,10 @@ struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
 		if (!use_table(head))
 			goto next;
 		spin_unlock(&sysctl_lock);
+
+		if (head->shadow)
+			head = head->shadow(head);
+
 		return head;
 	next:
 		tmp = tmp->next;
@@ -1582,7 +1592,8 @@ core_initcall(sysctl_init);
  * This routine returns %NULL on a failure to register, and a pointer
  * to the table header on success.
  */
-struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
+struct ctl_table_header *register_sysctl_table_shadow(struct ctl_table * table,
+		struct ctl_table_header *(*shadow)(struct ctl_table_header *))
 {
 	struct ctl_table_header *tmp;
 	tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
@@ -1592,6 +1603,8 @@ struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
 	INIT_LIST_HEAD(&tmp->ctl_entry);
 	tmp->used = 0;
 	tmp->unregistering = NULL;
+	tmp->shadow = shadow;
+	tmp->origin = NULL;
 	sysctl_set_parent(NULL, table);
 	if (sysctl_check_table(tmp->ctl_table)) {
 		kfree(tmp);
@@ -1603,6 +1616,11 @@ struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
 	return tmp;
 }
 
+struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
+{
+	return register_sysctl_table_shadow(table, NULL);
+}
+
 /**
  * unregister_sysctl_table - unregister a sysctl table hierarchy
  * @header: the header returned from register_sysctl_table
@@ -1619,6 +1637,84 @@ void unregister_sysctl_table(struct ctl_table_header * header)
 	kfree(header);
 }
 
+/*
+ * ctl tables shadow management
+ */
+static void ctl_free_table(struct ctl_table *t)
+{
+	struct ctl_table *tmp;
+
+	for (tmp = t; tmp->ctl_name || tmp->procname; tmp++)
+		if (tmp->child)
+			ctl_free_table(tmp->child);
+
+	kfree(t);
+}
+
+static struct ctl_table *ctl_dup_table(struct ctl_table *parent,
+		struct ctl_table *t)
+{
+	int i;
+	struct ctl_table *copy;
+
+	for (copy = t, i = 1; copy->ctl_name || copy->procname; copy++, i++);
+
+	copy = kmemdup(t, i * sizeof(struct ctl_table), GFP_KERNEL);
+	if (copy == NULL)
+		goto out;
+
+	for (i = 0; copy[i].ctl_name || copy[i].procname; i++) {
+		copy[i].parent = parent;
+		if (copy[i].child == NULL)
+			continue;
+
+		copy[i].child = ctl_dup_table(&copy[i], t[i].child);
+		if (copy[i].child == NULL)
+			goto unroll;
+	}
+
+	return copy;
+
+unroll:
+	for (i--; i >= 0; i--)
+		if (copy[i].child)
+			ctl_free_table(copy[i].child);
+	kfree(copy);
+out:
+	return NULL;
+}
+
+struct ctl_table_header *create_sysctl_shadow(struct ctl_table_header *h)
+{
+	struct ctl_table_header *ret;
+	struct ctl_table *tbl;
+
+	ret = kmemdup(h, sizeof(struct ctl_table_header *), GFP_KERNEL);
+	if (ret == NULL)
+		goto err_header;
+
+	ret->shadow = NULL;
+	ret->origin = h;
+
+	tbl = ctl_dup_table(NULL, h->ctl_table);
+	if (tbl == NULL)
+		goto err_table;
+
+	ret->ctl_table = tbl;
+	return ret;
+
+err_table:
+	kfree(ret);
+err_header:
+	return NULL;
+}
+
+void free_sysctl_shadow(struct ctl_table_header *shadow)
+{
+	ctl_free_table(shadow->ctl_table);
+	kfree(shadow);
+}
+
 #else /* !CONFIG_SYSCTL */
 struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
 {

  parent reply	other threads:[~2007-11-20 11:43 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-20 11:38 [PATCH 0/3] Sysctl shadow management Pavel Emelyanov
     [not found] ` <4742C73C.3010904-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2007-11-20 11:43   ` Pavel Emelyanov [this message]
     [not found]     ` <4742C86E.6060705-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2007-11-20 17:16       ` [PATCH 1/3] The sysctl shadows Dave Hansen
2007-11-21  9:20         ` Pavel Emelyanov
2007-11-20 11:45   ` [PATCH 2/3] Switch UTS namespace to use shadows Pavel Emelyanov
2007-11-20 11:47   ` [PATCH 3/3] Switch IPC namespace to use sysctl shadows Pavel Emelyanov
     [not found]     ` <4742C95D.1040907-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2007-11-20 17:24       ` Dave Hansen
2007-11-21  9:21         ` Pavel Emelyanov
2007-11-20 13:05   ` [PATCH 0/3] Sysctl shadow management Eric W. Biederman
     [not found]     ` <m1y7ctrrrd.fsf-T1Yj925okcoyDheHMi7gv2pdwda3JcWeAL8bYrjMMd8@public.gmane.org>
2007-11-20 13:21       ` Pavel Emelyanov
     [not found]         ` <4742DF51.8060402-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2007-11-20 15:21           ` Eric W. Biederman
     [not found]             ` <m1tznhrli5.fsf-T1Yj925okcoyDheHMi7gv2pdwda3JcWeAL8bYrjMMd8@public.gmane.org>
2007-11-20 15:36               ` Pavel Emelyanov
     [not found]                 ` <4742FEF6.6080609-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2007-11-20 19:47                   ` Eric W. Biederman
     [not found]                     ` <m1myt8snqp.fsf-T1Yj925okcoyDheHMi7gv2pdwda3JcWeAL8bYrjMMd8@public.gmane.org>
2007-11-21  9:52                       ` Pavel Emelyanov
2007-11-29 17:40 ` [PATCH 0/4] Sysctl namespace support Eric W. Biederman
     [not found]   ` <m1odddc5mf.fsf-T1Yj925okcoyDheHMi7gv2pdwda3JcWeAL8bYrjMMd8@public.gmane.org>
2007-11-29 17:45     ` [PATCH 1/4] sysctl: Add register_sysctl_paths function Eric W. Biederman
2007-11-29 17:46       ` [PATCH 2/4] sysctl: Remember the ctl_table we passed to register_sysctl_paths Eric W. Biederman
2007-11-29 17:51         ` [PATCH 3/4] sysctl: Infrastructure for per namespace sysctls Eric W. Biederman
2007-11-29 17:53           ` [PATCH 4/4] net: Implement the per network namespace sysctl infrastructure Eric W. Biederman
2007-11-30 16:18             ` Serge E. Hallyn
2007-11-30 16:23               ` Pavel Emelyanov
2007-11-30 21:49               ` Eric W. Biederman
2007-12-01  0:01                 ` Serge E. Hallyn
2007-11-30 12:56   ` [PATCH 0/4] Sysctl namespace support Herbert Xu
     [not found]     ` <20071130125627.GH26848-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org>
2007-11-30 13:25       ` Eric W. Biederman

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=4742C86E.6060705@openvz.org \
    --to=xemul-gefaqzzx7r8dnm+yrofe0a@public.gmane.org \
    --cc=clg-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org \
    --cc=containers-qjLDD68F18O7TbgM5vRIOg@public.gmane.org \
    --cc=dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org \
    --cc=ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org \
    --cc=serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox