[lxc-devel] [RFC 1/2] lxc-start: added --start-frozen

Wolfgang Bumiller w.bumiller at proxmox.com
Thu Jan 14 13:30:19 UTC 2016


Add the possibility to start a container in a frozen state.

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 doc/lxc-start.sgml.in  | 12 ++++++++++++
 src/lxc/arguments.h    |  3 +++
 src/lxc/conf.h         |  1 +
 src/lxc/lxc_start.c    |  7 +++++++
 src/lxc/lxccontainer.c | 16 ++++++++++++++++
 src/lxc/lxccontainer.h | 10 ++++++++++
 src/lxc/start.c        | 17 +++++++++++++++++
 7 files changed, 66 insertions(+)

diff --git a/doc/lxc-start.sgml.in b/doc/lxc-start.sgml.in
index 1770ac2..46bfcc7 100644
--- a/doc/lxc-start.sgml.in
+++ b/doc/lxc-start.sgml.in
@@ -59,6 +59,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       <arg choice="opt">-s KEY=VAL</arg>
       <arg choice="opt">-C</arg>
       <arg choice="opt">--share-[net|ipc|uts] <replaceable>name|pid</replaceable></arg>
+      <arg choice="opt">--start-frozen</arg>
       <arg choice="opt">command</arg>
     </cmdsynopsis>
   </refsynopsisdiv>
@@ -245,6 +246,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 	</listitem>
       </varlistentry>
 
+      <varlistentry>
+	<term>
+	  <option>--start-frozen</option>
+	</term>
+	<listitem>
+	  <para>
+	    Freeze the container before starting its init process.
+	  </para>
+	</listitem>
+      </varlistentry>
+
     </variablelist>
 
   </refsect1>
diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h
index 38cb0da..79a4758 100644
--- a/src/lxc/arguments.h
+++ b/src/lxc/arguments.h
@@ -81,6 +81,9 @@ struct lxc_arguments {
 	/* close fds from parent? */
 	int close_all_fds;
 
+	/* freeze before starting init */
+	int start_frozen;
+
 	/* lxc-create */
 	char *bdevtype, *configfile, *template;
 	char *fstype;
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index b0274ec..5c84f5f 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -312,6 +312,7 @@ struct lxc_conf {
 	struct lxc_rootfs rootfs;
 	char *ttydir;
 	int close_all_fds;
+	int start_frozen;
 	struct lxc_list hooks[NUM_LXC_HOOKS];
 
 	char *lsm_aa_profile;
diff --git a/src/lxc/lxc_start.c b/src/lxc/lxc_start.c
index 6b942ac..73e27e3 100644
--- a/src/lxc/lxc_start.c
+++ b/src/lxc/lxc_start.c
@@ -53,6 +53,7 @@
 #define OPT_SHARE_NET OPT_USAGE+1
 #define OPT_SHARE_IPC OPT_USAGE+2
 #define OPT_SHARE_UTS OPT_USAGE+3
+#define OPT_START_FROZEN OPT_USAGE+4
 
 lxc_log_define(lxc_start_ui, lxc);
 
@@ -154,6 +155,7 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
 	case OPT_SHARE_NET: args->share_ns[LXC_NS_NET] = arg; break;
 	case OPT_SHARE_IPC: args->share_ns[LXC_NS_IPC] = arg; break;
 	case OPT_SHARE_UTS: args->share_ns[LXC_NS_UTS] = arg; break;
+	case OPT_START_FROZEN: args->start_frozen = 1; break;
 	}
 	return 0;
 }
@@ -170,6 +172,7 @@ static const struct option my_longopts[] = {
 	{"share-net", required_argument, 0, OPT_SHARE_NET},
 	{"share-ipc", required_argument, 0, OPT_SHARE_IPC},
 	{"share-uts", required_argument, 0, OPT_SHARE_UTS},
+	{"start-frozen", no_argument, 0, OPT_START_FROZEN},
 	LXC_COMMON_OPTIONS
 };
 
@@ -193,6 +196,7 @@ Options :\n\
                          Note: --daemon implies --close-all-fds\n\
   -s, --define KEY=VAL   Assign VAL to configuration variable KEY\n\
       --share-[net|ipc|uts]=NAME Share a namespace with another container or pid\n\
+      --start-frozen     Freeze the container before starting its init\n\
 ",
 	.options   = my_longopts,
 	.parser    = my_parser,
@@ -335,6 +339,9 @@ int main(int argc, char *argv[])
 	if (my_args.close_all_fds)
 		c->want_close_all_fds(c, true);
 
+	if (my_args.start_frozen)
+		c->set_start_frozen(c, true);
+
 	if (args == default_args)
 		err = c->start(c, 0, NULL) ? 0 : 1;
 	else
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 802a930..166f507 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -590,6 +590,21 @@ static bool do_lxcapi_want_close_all_fds(struct lxc_container *c, bool state)
 
 WRAP_API_1(bool, lxcapi_want_close_all_fds, bool)
 
+static bool do_lxcapi_set_start_frozen(struct lxc_container *c, bool state)
+{
+	if (!c || !c->lxc_conf)
+		return false;
+	if (container_mem_lock(c)) {
+		ERROR("Error getting mem lock");
+		return false;
+	}
+	c->lxc_conf->start_frozen = state;
+	container_mem_unlock(c);
+	return true;
+}
+
+WRAP_API_1(bool, lxcapi_set_start_frozen, bool)
+
 static bool do_lxcapi_wait(struct lxc_container *c, const char *state, int timeout)
 {
 	int ret;
@@ -4074,6 +4089,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
 	c->load_config = lxcapi_load_config;
 	c->want_daemonize = lxcapi_want_daemonize;
 	c->want_close_all_fds = lxcapi_want_close_all_fds;
+	c->set_start_frozen = lxcapi_set_start_frozen;
 	c->start = lxcapi_start;
 	c->startl = lxcapi_startl;
 	c->stop = lxcapi_stop;
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 6d155a1..454f029 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -245,6 +245,16 @@ struct lxc_container {
 	bool (*want_close_all_fds)(struct lxc_container *c, bool state);
 
 	/*!
+	 * \brief Specify whether the container wishes start in a frozen state.
+	 *
+	 * \param c Container.
+	 * \param state Value for the start_frozen bit (0 or 1).
+	 *
+	 * \return \c true on success, else \c false.
+	 */
+	bool (*set_start_frozen)(struct lxc_container *c, bool state);
+
+	/*!
 	 * \brief Return current config file name.
 	 *
 	 * \param c Container.
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 79dbe33..84a05f9 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1343,6 +1343,23 @@ static int start(struct lxc_handler *handler, void* data)
 {
 	struct start_args *arg = data;
 
+	if (handler->conf->start_frozen) {
+		char *cgfile = NULL;
+		NOTICE("freezing '%s'", arg->argv[0]);
+		/* Let the monitor know we reached this point. */
+		lxc_sync_fini_child(handler);
+		if (asprintf(&cgfile, "/sys/fs/cgroup/freezer/lxc/%s/freezer.state", handler->name) == -1) {
+			ERROR("failed to allocate memory trying to freezed container '%s'", handler->name);
+			return -1;
+		}
+		if (lxc_write_to_file(cgfile, "FROZEN", sizeof("FROZEN")-1, false) == -1) {
+			ERROR("error freezing container '%s' at startup", handler->name);
+			free(cgfile);
+			return -1;
+		}
+		free(cgfile);
+	}
+
 	NOTICE("exec'ing '%s'", arg->argv[0]);
 
 	execvp(arg->argv[0], arg->argv);
-- 
2.1.4




More information about the lxc-devel mailing list