[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