[Libct] [PATCH v2 1/6] VZ containers: Initial groundwork
Andrew Vagin
avagin at parallels.com
Wed Nov 12 13:42:56 PST 2014
On Wed, Nov 12, 2014 at 03:52:15PM +0300, Alexander Burluka wrote:
> Modified Makefile, make it recognize PCS server
> Surrounded uncompilable parts with VZ macros
> Added necessary files for further work
> Added some already-implemented and easy functions to vz container_ops
> ---
> Makefile | 15 +++
> src/Makefile | 1 +
> src/ct.c | 39 +++++++--
> src/include/ct.h | 12 +++
> src/include/session.h | 1 +
> src/include/util.h | 3 +
> src/include/vz.h | 11 +++
> src/namespaces.c | 4 +
> src/session.c | 44 +++++++++-
> src/util.c | 55 ++++++++++++
> src/vz.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++
> 11 files changed, 400 insertions(+), 11 deletions(-)
> create mode 100644 src/include/vz.h
> create mode 100644 src/vz.c
>
> diff --git a/Makefile b/Makefile
> index b8bbd80..61795b1 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -52,9 +52,17 @@ ifneq ($(ARCH),x86)
> $(error "The architecture $(ARCH) isn't supported"))
> endif
>
> +ifneq ("$(wildcard /proc/vz)","")
> + VZ := 1
> +endif
> +
> +
> cflags-y += -iquote src/include
> cflags-y += -fno-strict-aliasing
> cflags-y += -I/usr/include
> +ifeq ($(VZ),1)
> + cflags-y += -I/usr/src/kernels/$(shell uname -r)/include/
> +endif
> export cflags-y
>
> VERSION_MAJOR := 0
> @@ -72,6 +80,9 @@ LIBS := -lrt
>
> DEFINES += -D_FILE_OFFSET_BITS=64
> DEFINES += -D_GNU_SOURCE
> +ifeq ($(VZ),1)
> + DEFINES += -D_VZ
> +endif
>
> WARNINGS := -Wall -Wno-unused-result
>
> @@ -88,6 +99,10 @@ endif
>
> CFLAGS += $(WARNINGS) $(DEFINES)
>
> +ifneq ("$(wildcard /proc/vz)","")
> + CFLAGS += -D VZ
What is a difference between VZ and _VZ? Why do we need them both?
> +endif
> +
> export E Q CC ECHO MAKE CFLAGS LIBS ARCH DEFINES MAKEFLAGS
> export SH RM OBJCOPY LDARCH LD CP MKDIR CD LN
> export ESED SED CAT
> diff --git a/src/Makefile b/src/Makefile
> index 050ef95..6ef8016 100644
> --- a/src/Makefile
> +++ b/src/Makefile
> @@ -16,6 +16,7 @@ obj-y += util.o
> obj-y += devnodes.o
> obj-y += route.o
> obj-y += process.o
> +obj-y += vz.o
>
> cflags-y += -fPIC -Wa,--noexecstack -fno-stack-protector
> cflags-so += -rdynamic
> diff --git a/src/ct.c b/src/ct.c
> index b3a13ff..284b51e 100644
> --- a/src/ct.c
> +++ b/src/ct.c
> @@ -28,6 +28,7 @@
> #include "net.h"
> #include "ct.h"
> #include "fs.h"
> +#include "vz.h"
>
> static enum ct_state local_get_state(ct_handler_t h)
> {
> @@ -399,13 +400,6 @@ err_cg:
> return ret;
> }
>
> -struct execv_args {
> - char *path;
> - char **argv;
> - char **env;
> - int *fds;
> -};
> -
> static int ct_execv(void *a)
> {
> struct execv_args *ea = a;
> @@ -644,7 +638,7 @@ static int local_add_map(struct list_head *list, unsigned int first,
> return 0;
> }
>
> -static int local_add_uid_map(ct_handler_t h, unsigned int first,
> +int local_add_uid_map(ct_handler_t h, unsigned int first,
> unsigned int lower_first, unsigned int count)
userns isn't supported by rhel kernels, so the vz driver doesn't need
this functions.
> {
> struct container *ct = cth2ct(h);
> @@ -652,7 +646,7 @@ static int local_add_uid_map(ct_handler_t h, unsigned int first,
> return local_add_map(&ct->uid_map, first, lower_first, count);
> }
>
> -static int local_add_gid_map(ct_handler_t h, unsigned int first,
> +int local_add_gid_map(ct_handler_t h, unsigned int first,
> unsigned int lower_first, unsigned int count)
> {
> struct container *ct = cth2ct(h);
> @@ -714,3 +708,30 @@ ct_handler_t ct_create(char *name)
>
> return NULL;
> }
> +
> +ct_handler_t vz_ct_create(char *name)
> +{
> + struct container *ct;
> +
> + ct = xzalloc(sizeof(*ct));
> + if (ct) {
> + ct_handler_init(&ct->h);
> + ct->h.ops = get_vz_ct_ops();
> + ct->state = CT_STOPPED;
> + ct->name = xstrdup(name);
> + ct->tty_fd = -1;
> + INIT_LIST_HEAD(&ct->cgroups);
> + INIT_LIST_HEAD(&ct->cg_configs);
> + INIT_LIST_HEAD(&ct->ct_nets);
> + INIT_LIST_HEAD(&ct->ct_net_routes);
> + INIT_LIST_HEAD(&ct->fs_mnts);
> + INIT_LIST_HEAD(&ct->fs_devnodes);
> + INIT_LIST_HEAD(&ct->uid_map);
> + INIT_LIST_HEAD(&ct->gid_map);
> +
> + return &ct->h;
> + }
> +
> + return NULL;
> +
> +}
> diff --git a/src/include/ct.h b/src/include/ct.h
> index ebce788..c3a760f 100644
> --- a/src/include/ct.h
> +++ b/src/include/ct.h
> @@ -48,6 +48,7 @@ struct ct_handler {
> };
>
> ct_handler_t ct_create(char *name);
> +ct_handler_t vz_ct_create(char *name);
>
> #define CT_AUTO_PROC 0x1
> #define CT_KILLABLE 0x2
> @@ -117,6 +118,10 @@ static inline struct container *cth2ct(struct ct_handler *h)
> }
>
> extern char *local_ct_name(ct_handler_t h);
> +extern int local_add_uid_map(ct_handler_t h, unsigned int first,
> + unsigned int lower_first, unsigned int count);
> +extern int local_add_gid_map(ct_handler_t h, unsigned int first,
> + unsigned int lower_first, unsigned int count);
>
> static inline bool fs_private(struct container *ct)
> {
> @@ -125,4 +130,11 @@ static inline bool fs_private(struct container *ct)
>
> extern void ct_handler_init(ct_handler_t h);
>
> +struct execv_args {
> + char *path;
> + char **argv;
> + char **env;
> + int *fds;
> +};
> +
> #endif /* __LIBCT_CT_H__ */
> diff --git a/src/include/session.h b/src/include/session.h
> index 7a67e8d..45a7595 100644
> --- a/src/include/session.h
> +++ b/src/include/session.h
> @@ -10,6 +10,7 @@ enum {
> BACKEND_NONE,
> BACKEND_LOCAL,
> BACKEND_UNIX,
> + BACKEND_VZ,
> };
>
> struct backend_ops {
> diff --git a/src/include/util.h b/src/include/util.h
> index 8937a13..7227255 100644
> --- a/src/include/util.h
> +++ b/src/include/util.h
> @@ -13,5 +13,8 @@
>
> extern int do_mount(char *src, char *dst, int flags, char *fstype, char *data);
> extern int set_string(char **dest, char *src);
> +extern int parse_int(const char *str, int *val);
> +extern int parse_uint(const char *str, unsigned int *val);
> +extern int stat_file(const char *file);
>
> #endif /* __LIBCT_UTIL_H__ */
> diff --git a/src/include/vz.h b/src/include/vz.h
> new file mode 100644
> index 0000000..f4c2f34
> --- /dev/null
> +++ b/src/include/vz.h
> @@ -0,0 +1,11 @@
> +#ifndef __LIBCT_VZ_H__
> +#define __LIBCT_VZ_H__
> +
> +struct container_ops;
> +
> +const struct container_ops *get_vz_ct_ops(void);
> +int vzctl_open(void);
> +void vzctl_close(void);
> +int get_vzctlfd(void);
> +
> +#endif
> diff --git a/src/namespaces.c b/src/namespaces.c
> index f3a1b74..035ad99 100644
> --- a/src/namespaces.c
> +++ b/src/namespaces.c
> @@ -57,7 +57,9 @@ int switch_ns(int pid, struct ns_desc *nd, int *rst)
> goto err_rst;
> }
>
> +#ifndef VZ
> ret = setns(nsfd, nd->cflag);
I don't like this hack. Pls, remove it.
> +#endif
> if (ret < 0)
> goto err_set;
>
> @@ -75,6 +77,8 @@ err_ns:
>
> void restore_ns(int rst, struct ns_desc *nd)
> {
> +#ifndef VZ
> setns(rst, nd->cflag);
> +#endif
> close(rst);
> }
> diff --git a/src/session.c b/src/session.c
> index 6e32a4d..26af8cc 100644
> --- a/src/session.c
> +++ b/src/session.c
> @@ -8,6 +8,7 @@
> #include "libct.h"
> #include "async.h"
> #include "ct.h"
> +#include "vz.h"
>
> static void close_local_session(libct_session_t s)
> {
> @@ -22,8 +23,8 @@ static ct_handler_t create_local_ct(libct_session_t s, char *name)
> ct = ct_create(name);
> if (!ct)
> return libct_err_to_handle(-1);
> - else
> - return ct;
> +
> + return ct;
> }
>
> static ct_process_desc_t local_process_create_desc(libct_session_t s)
> @@ -62,6 +63,41 @@ static const struct backend_ops local_session_ops = {
> .update_ct_state = update_local_ct_state,
> };
>
> +
> +static void close_vz_session(libct_session_t s)
> +{
> + struct local_session *l = s2ls(s);
> + xfree(l);
> + vzctl_close();
> +}
> +
> +static ct_handler_t create_vz_ct(libct_session_t s, char *name)
> +{
> + ct_handler_t ct = NULL;
> + if (vzctl_open() == -1)
> + return libct_err_to_handle(-1);
> +
> + ct = vz_ct_create(name);
> + if (!ct)
> + return libct_err_to_handle(-1);
> +
> + return ct;
> +}
> +
> +static void update_vz_ct_state(libct_session_t s, pid_t pid)
> +{
> + /* TODO: implement afterwards */
> +}
> +
> +
> +static const struct backend_ops vz_session_ops = {
> + .type = BACKEND_VZ,
> + .create_ct = create_vz_ct,
> + .create_process_desc = local_process_create_desc,
> + .close = close_vz_session,
> + .update_ct_state = update_vz_ct_state,
> +};
> +
> libct_session_t libct_session_open_local(void)
> {
> struct local_session *s;
> @@ -73,7 +109,11 @@ libct_session_t libct_session_open_local(void)
> if (s) {
> INIT_LIST_HEAD(&s->s.s_cts);
> INIT_LIST_HEAD(&s->s.async_list);
> +#ifndef VZ
> s->s.ops = &local_session_ops;
> +#else
> + s->s.ops = &vz_session_ops;
> +#endif
> return &s->s;
> }
>
> diff --git a/src/util.c b/src/util.c
> index 62dfbaf..d303815 100644
> --- a/src/util.c
> +++ b/src/util.c
> @@ -6,6 +6,9 @@
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> +#include <limits.h>
> +#include <ctype.h>
> +#include <sys/param.h>
>
> #include "uapi/libct.h"
> #include "xmalloc.h"
> @@ -113,3 +116,55 @@ int set_string(char **dest, char *src)
> return 0;
> }
>
> +int parse_uint(const char *str, unsigned int *val)
> +{
> + char *tail;
> + long int n;
> +
> + if (*str == '\0')
> + return -1;
> +
> + errno = 0;
> + n = strtoul(str, &tail, 10);
> + if (*tail != '\0' || n >= UINT_MAX)
> + return -1;
> + *val = (unsigned int)n;
> +
> + return 0;
> +}
> +
> +int parse_int(const char *str, int *val)
> +{
> + char *tail;
> + long int n;
> +
> + if (*str == '\0')
> + return -1;
> +
> + errno = 0;
> + n = strtol(str, &tail, 10);
> + if (*tail != '\0' || errno == ERANGE || n > INT_MAX)
> + return -1;
> + *val = (int)n;
> +
> + return 0;
> +}
> +
> +/*
> + 1 - exist
> + 0 - doesn't exist
> + -1 - error
> +*/
> +int stat_file(const char *file)
Why we can't use access()?
More information about the Libct
mailing list