[lxc-devel] [PATCH] introduce lxcapi_add_device_node and lxcapi_remove_device_node to API

S.Çağlar Onur caglar at 10ur.org
Mon Nov 11 06:07:05 UTC 2013


Adding block/char devices to running container is a common operation so provide a common
implementation for users to consume.

Signed-off-by: S.Çağlar Onur <caglar at 10ur.org>
---
 src/lxc/lxccontainer.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/lxccontainer.h |   9 +++++
 2 files changed, 109 insertions(+)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index ede0113..58eebb0 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -2912,6 +2912,104 @@ static bool lxcapi_may_control(struct lxc_container *c)
 	return lxc_try_cmd(c->name, c->config_path) == 0;
 }
 
+static bool lxcapi_add_device_node(struct lxc_container *c, char *path)
+{
+	int ret, size = 32;
+	struct stat st;
+	char *value = alloca(size);
+	char dest_path[MAXPATHLEN];
+
+	/* make sure container is running */
+	if (!c->is_running(c)) {
+		ERROR("container is not running");
+		return false;
+	}
+
+	/* make sure that we can access given path */
+	if(access(path, F_OK) < 0 || lstat(path, &st) < 0)
+		return false;
+
+	/* continue if path is character device or block device */
+	if S_ISCHR(st.st_mode)
+		ret = snprintf(value, size, "c %d:%d rwm", major(st.st_rdev), minor(st.st_rdev));
+	else if S_ISBLK(st.st_mode)
+		ret = snprintf(value, size, "b %d:%d rwm", major(st.st_rdev), minor(st.st_rdev));
+	else
+		return false;
+
+	/* check snprintf return code */
+	if (ret < 0 || ret >= size)
+		return false;
+
+	/* prepare dest_path */
+	ret = snprintf(dest_path, MAXPATHLEN, "/proc/%d/root%s", c->init_pid(c), path);
+	if (ret < 0 || ret >= MAXPATHLEN)
+		return false;
+
+	/* remove dest_path if exists in the container */
+	if(access(dest_path, F_OK) == 0)
+		unlink(dest_path);
+
+	/* create the device node */
+	if (mknod(dest_path, st.st_mode, st.st_rdev) < 0)
+		return false;
+
+	/* add to device list */
+	if (!c->set_cgroup_item(c, "devices.allow", value)) {
+		ERROR("set_cgroup_item failed");
+		return false;
+	}
+
+	return true;
+}
+
+static bool lxcapi_remove_device_node(struct lxc_container *c, char *path)
+{
+	int ret, size = 32;
+	struct stat st;
+	char *value = alloca(size);
+	char dest_path[MAXPATHLEN];
+
+	/* make sure container is running */
+	if (!c->is_running(c)) {
+		ERROR("container is not running");
+		return false;
+	}
+
+	/* prepare dest_path */
+	ret = snprintf(dest_path, MAXPATHLEN, "/proc/%d/root%s", c->init_pid(c), path);
+	if (ret < 0 || ret >= MAXPATHLEN)
+		return false;
+
+	/* make sure that we can access dest_path */
+	if(access(dest_path, F_OK) < 0 || lstat(dest_path, &st) < 0)
+		return false;
+
+	/* continue if path is character device or block device */
+	if S_ISCHR(st.st_mode)
+		ret = snprintf(value, size, "c %d:%d rwm", major(st.st_rdev), minor(st.st_rdev));
+	else if S_ISBLK(st.st_mode)
+		ret = snprintf(value, size, "b %d:%d rwm", major(st.st_rdev), minor(st.st_rdev));
+	else
+		return false;
+
+	/* check snprintf return code */
+	if (ret < 0 || ret >= size)
+		return false;
+
+	/* remove dest_path if exists in the container */
+	if(access(dest_path, F_OK) == 0)
+		unlink(dest_path);
+
+	/* remove from device list */
+	if (!c->set_cgroup_item(c, "devices.deny", value)) {
+		ERROR("set_cgroup_item failed");
+		return false;
+	}
+
+	return true;
+}
+
 static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
 {
 	va_list ap;
@@ -3033,6 +3131,8 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
 	c->snapshot_restore = lxcapi_snapshot_restore;
 	c->snapshot_destroy = lxcapi_snapshot_destroy;
 	c->may_control = lxcapi_may_control;
+	c->add_device_node = lxcapi_add_device_node;
+	c->remove_device_node = lxcapi_remove_device_node;
 
 	/* we'll allow the caller to update these later */
 	if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 486035a..a94de9a 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -236,6 +236,15 @@ struct lxc_container {
 	 * and the caller may not access it.  Return true otherwise.
 	 */
 	bool (*may_control)(struct lxc_container *c);
+
+	/*
+	 * Returns true if given device succesfully added to container
+	 */
+	bool (*add_device_node)(struct lxc_container *c, char *path);
+	/*
+	 * Returns true if given device succesfully removed from container
+	 */
+	bool (*remove_device_node)(struct lxc_container *c, char *path);
 };
 
 struct lxc_snapshot {
-- 
1.8.3.2





More information about the lxc-devel mailing list