OpenVZ Forum


Home » Mailing lists » Devel » [Patch03/05]- Containers: Initialization and Configfs interface
[Patch03/05]- Containers: Initialization and Configfs interface [message #6370] Fri, 15 September 2006 01:41 Go to next message
Rohit Seth is currently offline  Rohit Seth
Messages: 101
Registered: August 2006
Senior Member
This patch contains containers interface with configfs. This patch
defines config group for containers underneath which different
containers can be created. This patch also contains initialization code
for creating work queue.

Signed-off-by: Rohit Seth <rohitseth@google.com>

kernel/container_configfs.c | 426 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 426 insertions(+)

--- linux-2.6.18-rc6-mm2.org/kernel/container_configfs.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.18-rc6-mm2.ctn/kernel/container_configfs.c 2006-09-14 16:18:45.000000000 -0700
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2006 Rohit Seth <rohitseth@google.com>
+ *
+ * Container initialization code and configfs registration code.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/container.h>
+#include <linux/configfs.h>
+#include <linux/workqueue.h>
+
+/*
+ * Per processor worker thread for handling over the limits scenarios.
+ */
+struct workqueue_struct *container_wq;
+
+/*
+ * Default limit for physical memory for a newly created container. Can
+ * be changed through /configfs/container/<container_name>/page_limit
+ */
+#define DEFAULT_PAGE_LIMIT ((900*1024*1024) >> PAGE_SHIFT)
+
+/*
+ * Default limit for number of tasks that can be created with in a container. Can
+ * be changed through /configfs/container/<container_name>/task_limit
+ */
+#define DEFAULT_TASK_LIMIT 100
+
+/*
+ * Following attributes are defined as the interface mechanism between configfs
+ * and containers.
+ * ca_name is the name as it gets shown in configfs
+ * ca_mode is the mode of that attribute
+ * idx is index of the attribute in the container. This is used to find out
+ * what specific operation is requested.
+ */
+static struct simple_containerfs_attr simple_containerfs_attr_id = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "id", .ca_mode = S_IRUGO },
+ .idx = CONFIGFS_CTN_ATTR_ID,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_num_tasks = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "num_tasks", .ca_mode = S_IRUGO },
+ .idx = CONFIGFS_CTN_ATTR_NUM_TASKS,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_num_files = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "num_files", .ca_mode = S_IRUGO },
+ .idx = CONFIGFS_CTN_ATTR_NUM_FILES,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_num_anon_pages = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "num_anon_pages", .ca_mode = S_IRUGO },
+ .idx = CONFIGFS_CTN_ATTR_NUM_ANON_PAGES,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_num_mapped_pages = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "num_mapped_pages", .ca_mode = S_IRUGO },
+ .idx = CONFIGFS_CTN_ATTR_NUM_MAPPED_PAGES,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_num_file_pages = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "num_file_pages", .ca_mode = S_IRUGO },
+ .idx = CONFIGFS_CTN_ATTR_NUM_FILE_PAGES,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_num_active_pages = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "num_active_pages", .ca_mode = S_IRUGO },
+ .idx = CONFIGFS_CTN_ATTR_NUM_ACTIVE_PAGES,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_page_limit = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "page_limit", .ca_mode = S_IRUGO | S_IWUSR },
+ .idx = CONFIGFS_CTN_ATTR_PAGE_LIMIT,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_task_limit = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "task_limit", .ca_mode = S_IRUGO | S_IWUSR },
+ .idx = CONFIGFS_CTN_ATTR_TASK_LIMIT,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_page_limit_hits = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "page_limit_hits", .ca_mode = S_IRUGO },
+ .idx = CONFIGFS_CTN_ATTR_PAGE_LIMIT_HITS,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_task_limit_hits = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "task_limit_hits", .ca_mode = S_IRUGO },
+ .idx = CONFIGFS_CTN_ATTR_TASK_LIMIT_HITS,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_freeing = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "freeing", .ca_mode = S_IRUGO | S_IWUSR },
+ .idx = CONFIGFS_CTN_ATTR_FREEING,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_addtask = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "addtask", .ca_mode = S_IRUGO | S_IWUSR },
+ .idx = CONFIGFS_CTN_ATTR_ADD_TASK,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_rmtask = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "rmtask", .ca_mode = S_IRUGO | S_IWUSR },
+ .idx = CONFIGFS_CTN_ATTR_RM_TASK,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_addfile = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "addfile", .ca_mode = S_IRUGO | S_IWUSR },
+ .idx = CONFIGFS_CTN_ATTR_ADD_FILE,
+};
+
+static struct simple_containerfs_attr simple_containerfs_attr_rmfile = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "rmfile", .ca_mode = S_IRUGO | S_IWUSR },
+ .idx = CONFIGFS_CTN_ATTR_RM_FILE,
+};
+
+/*
+ * Array of all the attributes defined for containers. Used at the time when
+ * container is created.
+ */
+static struct configfs_attribute *simple_containerfs_attrs[] = {
+ &simple_containerfs_attr_id.attr,
+ &simple_containerfs_attr_num_tasks.attr,
+ &simple_containerfs_attr_num_files.attr,
+ &simple_containerfs_attr_num_anon_pages.attr,
+ &simple_containerfs_attr_num_mapped_pages.attr,
+ &simple_containerfs_attr_num_file_pages.attr,
+ &simple_containerfs_attr_num_active_pages.attr,
+ &simple_containerfs_attr_page_limit.attr,
+ &simple_containerfs_attr_task_limit.attr,
+ &simple_containerfs_attr_page_limit_hits.attr,
+ &simple_containerfs_attr_task_limit_hits.attr,
+ &simple_containerfs_attr_freeing.attr,
+ &simple_containerfs_attr_addtask.attr,
+ &simple_containerfs_attr_rmtask.attr,
+ &simple_containerfs_attr_addfile.attr,
+ &simple_containerfs_attr_rmfile.attr,
+ NULL,
+};
+
+static inline struct simple_containerfs *to_simple_containerfs(struct config_item *item)
+{
+ return item ? container_of(item, struct simple_containerfs, item) : NULL;
+}
+
+/*
+ * simple_containerfs_attr_show operation is executed when ever there is a
+ * read operation on any of container's attribute.
+ */
+static ssize_t simple_containerfs_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ ssize_t tmp;
+ struct simple_containerfs *sc = to_simple_containerfs(item);
+ struct simple_containerfs_attr *ctfs_attr =
+ container_of(attr, struct simple_containerfs_attr, attr);
+
+ /* Attributes's index tells us what operation is requested. */
+ switch (ctfs_attr->idx) {
+ case CONFIGFS_CTN_ATTR_ID:
+ tmp = sc->ctn.id;
+ break;
+ case CONFIGFS_CTN_ATTR_NUM_TASKS:
+ tmp = (ssize_t)atomic_read(&sc->ctn.num_tasks);
+ break;
+ case CONFIGFS_CTN_ATTR_NUM_FILES:
+ tmp = (ssize_t)atomic_read(&sc->ctn.num_files);
+ break;
+ case CONFIGFS_CTN_ATTR_NUM_ANON_PAGES:
+ tmp = atomic_long_read(&sc->ctn.num_anon_pages);
+ break;
+ case CONFIGFS_CTN_ATTR_NUM_MAPPED_PAGES:
+ tmp = atomic_long_read(&sc->ctn.num_mapped_pages);
+ break;
+ case CONFIGFS_CTN_ATTR_NUM_FILE_PAGES:
+ tmp = atomic_long_read(&sc->ctn.num_file_pages);
+ break;
+ case CONFIGFS_CTN_ATTR_NUM_ACTIVE_PAGES:
+ tmp = atomic_long_read(&sc->ctn.num_active_pages);
+ break;
+ case CONFIGFS_CTN_ATTR_PAGE_LIMIT:
+ tmp = sc->ctn.page_limit;
+ break;
+ case CONFIGFS_CTN_ATTR_TASK_LIMIT:
+ tmp = sc->ctn.task_limit;
+ break;
+ case CONFIGFS_CTN_ATTR_PAGE_LIMIT_HITS:
+ tmp = atomic_long_read(&sc->ctn.page_limit_hits);
+ break;
+ case CONFIGFS_CTN_ATTR_TASK_LIMIT_HITS:
+ tmp = atomic_long_read(&sc->ctn.task_limit_hits);
+ break;
+ case CONFIGFS_CTN_ATTR_FREEING:
+ tmp = sc->ctn.freeing;
+ break;
+ default:
+ tmp = -1;
+ }
+
+ return sprintf(page, "%ld\n", tmp);
+
+}
+
+static ssize_t simple_containerfs_attr_store(struct config_item *item,
+ struct configfs_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct simple_containerfs *sc = to_simple_containerfs(item);
+ struct simple_containerfs_attr *ctfs_attr =
+ container_of(attr, struct simple_containerfs_attr, attr);
+ ssize_t tmp = 0;
+ char *p = (char *)buf;
+
+ /*
+ * For now it is only a simple operation. Expected input is
+ * integer for the attributes that are less than or equal to
+ * CONFIGFS_CTN_ATTR_RM_TASK defined in include/linux/container.h
+ * But update this code later as different types are expected.
+ */
+ if (ctfs_attr->idx <= CONFIGFS_CTN_ATTR_RM_TASK) {
+ tmp = simple_strtoul(p, &p, 10);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+ }
+
+ if (tmp > INT_MAX)
+ return -ERANGE;
+
+ switch (ctfs_attr->idx) {
+ case CONFIGFS_CTN_ATTR_PAGE_LIMIT:
+ tmp = set_container_page_limit(&sc->ctn, tmp);
+ break;
+ case CONFIGFS_CTN_ATTR_TASK_LIMIT:
+ tmp = set_container_task_limit(&sc->ctn, tmp);
+ break;
+ case CONFIGFS_CTN_ATTR_FREEING:
+ break;
+ case CONFIGFS_CTN_ATTR_ADD_TASK:
+ case CONFIGFS_CTN_ATTR_RM_TASK:
+ {
+ struct task_struct *t;
+
+ read_lock(&tasklist_lock);
+ t = find_task_by_pid(tmp);
+ if (t) {
+ get_task_struct(t);
+ read_unlock(&tasklist_lock);
+ if (ctfs_attr->idx == CONFIGFS_CTN_ATTR_ADD_TASK)
+ tmp = container_add_task(t, NULL, &sc->ctn);
+ else
+ container_remove_task(t, &sc->ctn);
+ put_task_struct(t);
+ }
+ else
+ read_unlock(&tasklist_lock);
+
...

Re: [Patch03/05]- Containers: Initialization and Configfs interface [message #6410 is a reply to message #6370] Fri, 15 September 2006 16:47 Go to previous messageGo to next message
Rohit Seth is currently offline  Rohit Seth
Messages: 101
Registered: August 2006
Senior Member
On Fri, 2006-09-15 at 18:30 +0200, Björn Steinbrink wrote:
> On 2006.09.14 18:41:26 -0700, Rohit Seth wrote:
> > +static int __init configfs_container_init(void)
> > +{
> > + int ret;
> > +
> > + config_group_init(&containerfs_group.cs_subsys.su_group) ;
> > + init_MUTEX(&containerfs_group.cs_subsys.su_sem);
> > + ret = configfs_register_subsystem(&containerfs_group.cs_subsys );
> > +
> > + if (ret)
> > + printk(KERN_ERR "Error %d while registering container subsystem\n", ret);
> > + else {
> > + container_wq = create_workqueue("Kcontainerd");
> > + if (container_wq == NULL) {
> > + ret = -ENOMEM;
> > + printk(KERN_ERR "Unable to create Container controllers");
>
> Shouldn't the subsystem be unregistered here?
>

Yes. Indeed. I'll fix it.

Thanks,
-rohit

> > + }
> > + }
> > + return ret;
> > +}
>
> Regards,
> Björn
Re: [Patch03/05]- Containers: Initialization and Configfs interface [message #6414 is a reply to message #6370] Fri, 15 September 2006 16:30 Go to previous messageGo to next message
B.Steinbrink is currently offline  B.Steinbrink
Messages: 2
Registered: September 2006
Junior Member
On 2006.09.14 18:41:26 -0700, Rohit Seth wrote:
> +static int __init configfs_container_init(void)
> +{
> + int ret;
> +
> + config_group_init(&containerfs_group.cs_subsys.su_group) ;
> + init_MUTEX(&containerfs_group.cs_subsys.su_sem);
> + ret = configfs_register_subsystem(&containerfs_group.cs_subsys );
> +
> + if (ret)
> + printk(KERN_ERR "Error %d while registering container subsystem\n", ret);
> + else {
> + container_wq = create_workqueue("Kcontainerd");
> + if (container_wq == NULL) {
> + ret = -ENOMEM;
> + printk(KERN_ERR "Unable to create Container controllers");

Shouldn't the subsystem be unregistered here?

> + }
> + }
> + return ret;
> +}

Regards,
Björn
Re: [Patch03/05]- Containers: Initialization and Configfs interface [message #6512 is a reply to message #6370] Tue, 19 September 2006 16:33 Go to previous message
Rohit Seth is currently offline  Rohit Seth
Messages: 101
Registered: August 2006
Senior Member
On Tue, 2006-09-19 at 11:38 -0400, Valdis.Kletnieks@vt.edu wrote:
> On Thu, 14 Sep 2006 18:41:26 PDT, Rohit Seth said:
>
> > --- linux-2.6.18-rc6-mm2.org/kernel/container_configfs.c 1969-12-31 16:00:00.000000000 -0800
> > +++ linux-2.6.18-rc6-mm2.ctn/kernel/container_configfs.c 2006-09-14 16:18:45.000000000 -0700
>
> > +static ssize_t simple_containerfs_attr_show(struct config_item *item,
> > + struct configfs_attribute *attr,
> > + char *page)
> ...
> > + switch (ctfs_attr->idx) {
> > + case CONFIGFS_CTN_ATTR_ID:
> > + tmp = sc->ctn.id;
> > + break;
> ...
> > + return sprintf(page, "%ld\n", tmp);
>
> What use is this value, given that we already have containers/user_friendly_name
> to use in the filesystem namespace? Or is this a mostly-debugging thing?

I think ids (numeric numbers) will be useful when printing the
information in /proc/<pid>/container User land tools don't necessarily
have to parse the (name) string in that case.

-rohit
Re: [Patch03/05]- Containers: Initialization and Configfs interface [message #6513 is a reply to message #6370] Tue, 19 September 2006 15:38 Go to previous message
Valdis.Kletnieks is currently offline  Valdis.Kletnieks
Messages: 5
Registered: September 2006
Junior Member
On Thu, 14 Sep 2006 18:41:26 PDT, Rohit Seth said:

> --- linux-2.6.18-rc6-mm2.org/kernel/container_configfs.c 1969-12-31 16:00:00.000000000 -0800
> +++ linux-2.6.18-rc6-mm2.ctn/kernel/container_configfs.c 2006-09-14 16:18:45.000000000 -0700

> +static ssize_t simple_containerfs_attr_show(struct config_item *item,
> + struct configfs_attribute *attr,
> + char *page)
...
> + switch (ctfs_attr->idx) {
> + case CONFIGFS_CTN_ATTR_ID:
> + tmp = sc->ctn.id;
> + break;
...
> + return sprintf(page, "%ld\n", tmp);

What use is this value, given that we already have containers/user_friendly_name
to use in the filesystem namespace? Or is this a mostly-debugging thing?
Previous Topic: [Patch 01/05]- Containers: Documentation on using containers
Next Topic: [patch03/05]: Containers(V2)- Container initialization and configfs interface
Goto Forum:
  


Current Time: Tue Sep 17 17:47:24 GMT 2024

Total time taken to generate the page: 0.05034 seconds