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(©[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)
{
next prev parent reply other threads:[~2007-11-20 11:43 UTC|newest]
Thread overview: 31+ 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
2007-11-29 17:40 ` 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:45 ` 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:46 ` Eric W. Biederman
2007-11-29 17:51 ` [PATCH 3/4] sysctl: Infrastructure for per namespace sysctls Eric W. Biederman
2007-11-29 17:51 ` Eric W. Biederman
2007-11-29 17:53 ` [PATCH 4/4] net: Implement the per network namespace sysctl infrastructure Eric W. Biederman
2007-11-29 17:53 ` 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
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.