[CRIU] [PATCH 1/5] crtools: preload libraries

Andrew Vagin avagin at parallels.com
Thu Dec 5 19:20:48 PST 2013


On Thu, Dec 05, 2013 at 10:28:36PM +0400, Pavel Emelyanov wrote:
> > @@ -271,6 +275,13 @@ int main(int argc, char *argv[])
> >  		case 54:
> >  			opts.check_ms_kernel = true;
> >  			break;
> > +		case 'L':
> > +			opts.libdir = strdup(optarg);
> > +			if (opts.libdir == NULL) {
> > +				pr_perror("Can't allocate memory");
> > +				return -1;
> > +			}
> > +			break;
> >  		case 'V':
> >  			pr_msg("Version: %s\n", CRIU_VERSION);
> >  			if (strcmp(CRIU_GITID, "0"))
> 
> Help text missing.
> 
> > diff --git a/include/cr_options.h b/include/cr_options.h
> > index b90b4e1..5a4676c 100644
> > --- a/include/cr_options.h
> > +++ b/include/cr_options.h
> > @@ -29,6 +29,7 @@ struct cr_options {
> >  	char			*pidfile;
> >  	struct list_head	veth_pairs;
> >  	struct list_head	scripts;
> > +	char			*libdir;
> >  	bool			use_page_server;
> >  	unsigned short		ps_port;
> >  	char			*addr;
> > diff --git a/include/criu-plugin.h b/include/criu-plugin.h
> > new file mode 100644
> > index 0000000..44abb2a
> > --- /dev/null
> > +++ b/include/criu-plugin.h
> > @@ -0,0 +1,26 @@
> > +/*
> > +    This file defines types and macros for CRIU plugins.
> > +    Copyright (C) 2013 Parallels, Inc
> > +
> > +    This program is free software; you can redistribute it and/or modify
> > +    it under the terms of the GNU General Public License as published by
> > +    the Free Software Foundation; either version 2 of the License, or
> > +    (at your option) any later version.
> > +
> > +    This program is distributed in the hope that it will be useful,
> > +    but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +    GNU General Public License for more details.
> > +
> > +    You should have received a copy of the GNU General Public License
> > +    along with this program; if not, write to the Free Software
> > +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> > + */
> > +
> > +#ifndef __CRIU_PLUGIN_H__
> > +#define __CRIU_PLUGIN_H__
> > +
> > +typedef int (cr_plugin_init_t)(void);
> > +typedef void (cr_plugin_fini_t)(void);
> > +
> > +#endif
> > diff --git a/include/plugin.h b/include/plugin.h
> > new file mode 100644
> > index 0000000..8653a5b
> > --- /dev/null
> > +++ b/include/plugin.h
> > @@ -0,0 +1,22 @@
> > +#ifndef __CR_PLUGIN_H__
> > +#define __CR_PLUGIN_H__
> > +
> > +#include "criu-plugin.h"
> > +
> > +struct cr_plugin_entry {
> > +	union {
> > +		cr_plugin_fini_t *cr_fini;
> > +	};
> > +
> > +	struct cr_plugin_entry *next;
> > +};
> > +
> > +struct cr_plugins {
> > +	struct cr_plugin_entry *cr_fini;
> > +};
> > +
> > +extern struct cr_plugins cr_plugins;
> 
> Why should this info be public?

criu-plugin.h is public, this one isn't.
> 
> > +
> > +void cr_lib_fini(void);
> > +int cr_lib_init(void);
> > +#endif
> > diff --git a/lib.c b/lib.c
> > new file mode 100644
> > index 0000000..387bb84
> > --- /dev/null
> > +++ b/lib.c
> > @@ -0,0 +1,123 @@
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <dirent.h>
> > +#include <errno.h>
> > +#include <stdio.h>
> > +#include <dlfcn.h>
> > +
> > +#include "cr_options.h"
> > +#include "plugin.h"
> > +#include "log.h"
> > +#include "xmalloc.h"
> > +
> > +struct cr_plugins cr_plugins;
> > +
> > +static int cr_lib_load(char *path)
> > +{
> > +	struct cr_plugin_entry *ce;
> > +	cr_plugin_init_t *f_init;
> > +	cr_plugin_fini_t *f_fini;
> > +	void *h;
> > +
> > +	h = dlopen(path, RTLD_LAZY);
> > +	if (h == NULL) {
> > +		pr_err("Unable to load %s: %s", path, dlerror());
> > +		return -1;
> > +	}
> > +
> > +	ce = NULL;
> > +	f_fini = dlsym(h, "cr_plugin_fini");
> > +	if (f_fini) {
> > +		ce = xmalloc(sizeof(struct cr_plugin_entry));
> > +		if (ce == NULL)
> > +			return -1;
> > +		ce->cr_fini = f_fini;
> 
> In patch #3 you use some fancy macro for this.

f_fini is a special case.
> 
> > +	}
> > +
> > +	f_init = dlsym(h, "cr_plugin_init");
> > +	if (f_init && f_init()) {
> > +		xfree(ce);
> > +		return -1;
> > +	}
> > +
> > +	if (ce) {
> > +		ce->next = cr_plugins.cr_fini;
> > +		cr_plugins.cr_fini = ce;
> > +	}

because it's added in the list here
> > +
> > +	return 0;
> > +}
> > +
> > +void cr_lib_fini(void)
> > +{
> > +	struct cr_plugin_entry *ce;
> > +
> > +	while (cr_plugins.cr_fini) {
> > +		ce = cr_plugins.cr_fini;
> > +		cr_plugins.cr_fini = cr_plugins.cr_fini->next;
> > +
> > +		ce->cr_fini();
> > +		xfree(ce);
> > +	}
> > +}
> > +
> > +int cr_lib_init(void)
> > +{
> > +	int exit_code = -1;
> > +	DIR *d;
> > +
> > +	memset(&cr_plugins, 0, sizeof(cr_plugins));
> > +
> > +	if (opts.libdir == NULL) {
> > +		char *path;
> > +
> > +		path = getenv("CRIU_LIBS_DIR");
> > +		if (path == NULL)
> 
> I think we should declare some default library for it.

I thought about this. I don't know which path can be default and we can
add the default path in any moment.


> 
> > +			return 0;
> > +
> > +		opts.libdir = strdup(path);
> 
> Why strdup?

becuase we need to copy the string, when we are parsing options,
so we are going to call free(opts.libdir)

> 
> > +		if (opts.libdir == NULL) {
> > +			pr_perror("Can't allocate memory");
> > +			return -1;
> > +		}
> > +	}
> > +
> > +	d = opendir(opts.libdir);
> > +	if (d == 0) {
> > +		pr_perror("Unable to open directory %s", opts.libdir);
> > +		return -1;
> > +	}
> > +
> > +	while (1) {
> > +		char path[PATH_MAX];
> > +		struct dirent *de;
> > +		int len;
> > +
> > +		errno = 0;
> > +		de = readdir(d);
> > +		if (de == NULL) {
> > +			if (errno == 0)
> > +				break;
> > +			pr_perror("Unable to read the libraries directory");
> > +			goto err;
> > +		}
> > +
> > +		len = strlen(de->d_name);
> > +
> > +		if (len < 3 || strncmp(de->d_name + len - 3, ".so", 3))
> > +			continue;
> > +
> > +		snprintf(path, sizeof(path), "%s/%s", opts.libdir, de->d_name);
> > +
> > +		if (cr_lib_load(path))
> > +			goto err;
> > +	}
> > +
> > +	exit_code = 0;
> > +err:
> > +	closedir(d);
> > +
> > +	cr_lib_fini();
> > +
> > +	return exit_code;
> > +}
> > 
> 
> 


More information about the CRIU mailing list