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 <cag...@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


------------------------------------------------------------------------------
November Webinars for C, C++, Fortran Developers
Accelerate application performance with scalable programming models. Explore
techniques for threading, error checking, porting, and tuning. Get the most 
from the latest Intel processors and coprocessors. See abstracts and register
http://pubads.g.doubleclick.net/gampad/clk?id=60136231&iu=/4140/ostg.clktrk
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to