[lxc-devel] [PATCH] introduce lxcapi_add_device_node and lxcapi_remove_device_node to API (v2)
S.Çağlar Onur
caglar at 10ur.org
Wed Nov 13 03:47:06 UTC 2013
Adding block/char devices to running container is a common operation so
provide a common implementation for users to consume.
changes since v2;
* removed duplicated code
Signed-off-by: S.Çağlar Onur <caglar at 10ur.org>
---
src/lxc/lxccontainer.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/lxc/lxccontainer.h | 9 ++++++
2 files changed, 93 insertions(+)
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 05ca643..c21bc96 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -62,6 +62,8 @@
#endif
#endif
+#define MAX_BUFFER 4096
+
lxc_log_define(lxc_container, lxc);
static bool file_exists(char *f)
@@ -2920,6 +2922,86 @@ static bool lxcapi_may_control(struct lxc_container *c)
return lxc_try_cmd(c->name, c->config_path) == 0;
}
+static bool add_remove_device_node(struct lxc_container *c, char *src_path, bool add)
+{
+ int ret;
+ struct stat st;
+ char value[MAX_BUFFER];
+ 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), src_path);
+ if (ret < 0 || ret >= MAXPATHLEN)
+ return false;
+
+ if (add) {
+ /* make sure that we can access src_path */
+ if(access(src_path, F_OK) < 0 || stat(src_path, &st) < 0)
+ return false;
+ } else {
+ /* make sure that we can access dest_path */
+ if(access(dest_path, F_OK) < 0 || stat(dest_path, &st) < 0)
+ return false;
+ }
+
+ /* continue if path is character device or block device */
+ if S_ISCHR(st.st_mode)
+ ret = snprintf(value, MAX_BUFFER, "c %d:%d rwm", major(st.st_rdev), minor(st.st_rdev));
+ else if S_ISBLK(st.st_mode)
+ ret = snprintf(value, MAX_BUFFER, "b %d:%d rwm", major(st.st_rdev), minor(st.st_rdev));
+ else
+ return false;
+
+ /* check snprintf return code */
+ if (ret < 0 || ret >= MAX_BUFFER)
+ return false;
+
+ /* remove dest_path if it exists */
+ if(access(dest_path, F_OK) == 0) {
+ if (unlink(dest_path) < 0) {
+ ERROR("unlink failed");
+ return false;
+ }
+ }
+
+ if (add) {
+ /* create the device node */
+ if (mknod(dest_path, st.st_mode, st.st_rdev) < 0) {
+ ERROR("mknod failed");
+ return false;
+ }
+
+ /* add to device list */
+ if (!c->set_cgroup_item(c, "devices.allow", value)) {
+ ERROR("set_cgroup_item failed while adding the device node");
+ return false;
+ }
+ } else {
+ /* remove from device list */
+ if (!c->set_cgroup_item(c, "devices.deny", value)) {
+ ERROR("set_cgroup_item failed while removing the device node");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool lxcapi_add_device_node(struct lxc_container *c, char *path)
+{
+ return add_remove_device_node(c, path, true);
+}
+
+static bool lxcapi_remove_device_node(struct lxc_container *c, char *path)
+{
+ return add_remove_device_node(c, path, false);
+}
+
static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
{
va_list ap;
@@ -3041,6 +3123,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