
On Wed, Jan 29, 2014 at 07:52:43PM -0500, John Ferlan wrote:
diff --git a/src/util/virkmod.c b/src/util/virkmod.c new file mode 100644 index 0000000..b8de8ea --- /dev/null +++ b/src/util/virkmod.c @@ -0,0 +1,138 @@ +/* + * virkmod.c: helper APIs for managing kernel modules + * + * Copyright (C) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <config.h> +#include "virkmod.h" +#include "vircommand.h" + +static int +doModprobe(const char *opts, const char *module, char **outbuf, char **errbuf) +{ + int ret = -1; + virCommandPtr cmd = NULL; + + cmd = virCommandNew(MODPROBE); + if (opts) + virCommandAddArg(cmd, opts); + if (module) + virCommandAddArg(cmd, module); + if (outbuf) + virCommandSetOutputBuffer(cmd, outbuf); + if (errbuf) + virCommandSetErrorBuffer(cmd, errbuf); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virCommandFree(cmd); + return ret; +} + +/** + * virModprobeConfig: + * + * Get the current kernel module configuration + * + * Returns NULL on failure or a pointer to the output which + * must be VIR_FREE()'d by the caller + */ +char * +virModprobeConfig(void) +{ + char *outbuf = NULL; + + if (doModprobe("-c", NULL, &outbuf, NULL) < 0) + return NULL; + + return outbuf; +} + + +/** + * virModprobeLoad: + * @module: Name of the module to load regardless of being on blacklist + * + * Attempts to load a kernel module + * + * returns NULL in case of success and the error buffer output from the + * virCommandRun() on failure. The returned buffer must be VIR_FREE() + * by the caller + */ +char * +virModprobeLoad(const char *module) +{ + char *errbuf = NULL; + + if (doModprobe(NULL, module, NULL, &errbuf) < 0) + return errbuf; + + VIR_FREE(errbuf); + return NULL; +} + + +/** + * virModprobeUseBlacklist: + * @module: Name of the module to load applying blacklist lookup + * + * Like ModprobeLoad, except adhere to the blacklist if present + * + * returns NULL in case of success and the error buffer output from the + * virCommandRun() on failure. The returned buffer must be VIR_FREE() + * by the caller + */ +char * +virModprobeUseBlacklist(const char *module) +{ + char *errbuf = NULL; + + if (doModprobe("-b", module, NULL, &errbuf) < 0) + return errbuf; + + VIR_FREE(errbuf); + return NULL; +}
I think we could probably just have a 'bool useBlacklist' parameter for the virModeprobeLoad method - we'll likely want all callers to use the blacklist anyway, so not much need to have separate methods for each usage.
+ + +/** + * virModprobeUnload: + * @module: Name of the module to unload + * + * Remove or unload a module + * + * returns NULL in case of success and the error buffer output from the + * virCommandRun() on failure. The returned buffer must be VIR_FREE() + * by the caller + */ +char * +virModprobeUnload(const char *module) +{ + char *errbuf = NULL; + + if (doModprobe("-r", module, NULL, &errbuf) < 0) + return errbuf; + + VIR_FREE(errbuf); + return NULL; +}
Oh actually this reminds me of a recent firewalld bug. Basically 'modprobe -r' has utterly broken semantics - it will recursively unload any modules that were dependancies of the one you're removing even if things still require them ! eg it'll see the 'bridge' module has refcount of 0 and remove it, even if you have bridges created on the host :-( 'rmmod modname' is what you actually want to use.
+#ifndef __VIR_KMOD_H__ +# define __VIR_KMOD_H__ + +# include "internal.h" +# include "viralloc.h"
Put the viralloc.h in the .c file, since the header doesn't do need any memory allocation APIs.
+ +char *virModprobeConfig(void); +char *virModprobeLoad(const char *) + ATTRIBUTE_NONNULL(1); +char *virModprobeUseBlacklist(const char *); + ATTRIBUTE_NONNULL(1) +char *virModprobeUnload(const char *) + ATTRIBUTE_NONNULL(1); +#endif /* __VIR_KMOD_H__ */
Nitpick on naming - general goal is to have function names match the filename. eg so we should use virKModLoad / virKModUnload Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|