[lxc-devel] [PATCH] introduce lxcapi_add_device_node and lxcapi_remove_device_node to API
Serge Hallyn
serge.hallyn at ubuntu.com
Wed Nov 13 14:33:31 UTC 2013
Quoting S.Çağlar Onur (caglar at 10ur.org):
> 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>
Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
> ---
> 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 at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel
More information about the lxc-devel
mailing list