Module Name:    src
Committed By:   jruoho
Date:           Tue Mar 13 05:56:46 UTC 2012

Modified Files:
        src/tests/modules: t_modctl.c

Log Message:
A modctl(MODCTL_STAT, ...) always succeeds, even in non-modular kernels such
as Xen domUs. Thus, refactor the code to detect non-modular kernels; when the
other operations (MODCTL_LOAD or MODCTL_UNLOAD) fail specifically with ENOSYS,
this is taken as a hint about non-modularity and the test is skipped.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/tests/modules/t_modctl.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/modules/t_modctl.c
diff -u src/tests/modules/t_modctl.c:1.6 src/tests/modules/t_modctl.c:1.7
--- src/tests/modules/t_modctl.c:1.6	Sun Mar 11 19:33:17 2012
+++ src/tests/modules/t_modctl.c	Tue Mar 13 05:56:46 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: t_modctl.c,v 1.6 2012/03/11 19:33:17 jruoho Exp $	*/
+/*	$NetBSD: t_modctl.c,v 1.7 2012/03/13 05:56:46 jruoho Exp $	*/
 /*
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: t_modctl.c,v 1.6 2012/03/11 19:33:17 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: t_modctl.c,v 1.7 2012/03/13 05:56:46 jruoho Exp $");
 
 #include <sys/module.h>
 #include <sys/sysctl.h>
@@ -44,52 +44,32 @@ __KERNEL_RCSID(0, "$NetBSD: t_modctl.c,v
 
 #include <atf-c.h>
 
-static bool have_modular = false;
-
 enum presence_check { both_checks, stat_check, sysctl_check };
 
+static bool	skip_nonmodular(void);
+static bool	get_modstat_info(const char *, modstat_t *);
+static bool	get_sysctl(const char *, void *buf, const size_t);
+static bool	k_helper_is_present_stat(void);
+static bool	k_helper_is_present_sysctl(void);
+static bool	k_helper_is_present(enum presence_check);
+static int	load(prop_dictionary_t, bool, const char *, ...);
+static int	unload(const char *, bool);
+static void	unload_cleanup(const char *);
+
 /* --------------------------------------------------------------------- */
 /* Auxiliary functions                                                   */
 /* --------------------------------------------------------------------- */
 
 /*
- * Checks if the kernel has 'options MODULAR' built into it and returns
- * a boolean indicating this condition.  This function must be called
- * during the test program's initialization and the result be stored
- * globally for further (efficient) usage of require_modular().
- */
-static
-bool
-check_modular(void)
-{
-	bool res = false;
-	struct iovec iov;
-
-	iov.iov_base = NULL;
-	iov.iov_len = 0;
-
-	if (modctl(MODCTL_STAT, &iov) == 0)
-		res = true;
-
-	return res;
-}
-
-/*
- * Makes sure that the kernel has 'options MODULAR' built into it and
- * skips the test otherwise.  Cannot be called unless check_modular()
- * has been executed before.
+ * A function that is called if the kernel is detected to be non-MODULAR.
  */
-static
-void
-require_modular(void)
+static bool
+skip_nonmodular(void)
 {
-
-	if (!have_modular)
-		atf_tc_skip("Kernel does not have 'options MODULAR'.");
+	atf_tc_skip("Kernel does not have 'options MODULAR'.");
 }
 
-static
-bool
+static bool
 get_modstat_info(const char *name, modstat_t *msdest)
 {
 	bool found;
@@ -100,7 +80,14 @@ get_modstat_info(const char *name, modst
 	for (len = 4096; ;) {
 		iov.iov_base = malloc(len);
 		iov.iov_len = len;
+
+		errno = 0;
+
 		if (modctl(MODCTL_STAT, &iov) != 0) {
+
+			if (errno == ENOSYS)
+				skip_nonmodular();
+
 			int err = errno;
 			fprintf(stderr, "modctl(MODCTL_STAT) failed: %s\n",
 			    strerror(err));
@@ -131,8 +118,7 @@ get_modstat_info(const char *name, modst
 /*
  * Queries a sysctl property.
  */
-static
-bool
+static bool
 get_sysctl(const char *name, void *buf, const size_t len)
 {
 	size_t len2 = len;
@@ -151,8 +137,7 @@ get_sysctl(const char *name, void *buf, 
  * successfully.  This implementation uses modctl(2)'s MODCTL_STAT
  * subcommand to do the check.
  */
-static
-bool
+static bool
 k_helper_is_present_stat(void)
 {
 
@@ -164,8 +149,7 @@ k_helper_is_present_stat(void)
  * successfully.  This implementation uses the module's sysctl
  * installed node to do the check.
  */
-static
-bool
+static bool
 k_helper_is_present_sysctl(void)
 {
 	size_t present;
@@ -179,8 +163,7 @@ k_helper_is_present_sysctl(void)
  * successfully.  The 'how' parameter specifies the implementation to
  * use to do the check.
  */
-static
-bool
+static bool
 k_helper_is_present(enum presence_check how)
 {
 	bool found;
@@ -212,8 +195,7 @@ k_helper_is_present(enum presence_check 
  * occurs when loading the module, an error message is printed and the
  * test case is aborted.
  */
-static
-int
+static int
 load(prop_dictionary_t props, bool fatal, const char *fmt, ...)
 {
 	int err;
@@ -241,8 +223,13 @@ load(prop_dictionary_t props, bool fatal
 	ml.ml_propslen = strlen(propsstr);
 
 	printf("Loading module %s\n", filename);
-	err = 0;
+	errno = err = 0;
+
 	if (modctl(MODCTL_LOAD, &ml) == -1) {
+
+		if (errno == ENOSYS)
+			skip_nonmodular();
+
 		err = errno;
 		fprintf(stderr, "modctl(MODCTL_LOAD, %s), failed: %s\n",
 		    filename, strerror(err));
@@ -259,15 +246,19 @@ load(prop_dictionary_t props, bool fatal
  * Unloads the specified module.  If silent is true, nothing will be
  * printed and no errors will be raised if the unload was unsuccessful.
  */
-static
-int
+static int
 unload(const char *name, bool fatal)
 {
 	int err;
 
 	printf("Unloading module %s\n", name);
-	err = 0;
+	errno = err = 0;
+
 	if (modctl(MODCTL_UNLOAD, __UNCONST(name)) == -1) {
+
+		if (errno == ENOSYS)
+			skip_nonmodular();
+
 		err = errno;
 		fprintf(stderr, "modctl(MODCTL_UNLOAD, %s) failed: %s\n",
 		    name, strerror(err));
@@ -281,8 +272,7 @@ unload(const char *name, bool fatal)
  * A silent version of unload, to be called as part of the cleanup
  * process only.
  */
-static
-void
+static void
 unload_cleanup(const char *name)
 {
 
@@ -304,8 +294,6 @@ ATF_TC_BODY(cmd_load, tc)
 	char longname[MAXPATHLEN];
 	size_t i;
 
-	require_modular();
-
 	ATF_CHECK(load(NULL, false, "") == ENOENT);
 	ATF_CHECK(load(NULL, false, "non-existent.o") == ENOENT);
 
@@ -336,8 +324,6 @@ ATF_TC_BODY(cmd_load_props, tc)
 {
 	prop_dictionary_t props;
 
-	require_modular();
-
 	printf("Loading module without properties\n");
 	props = prop_dictionary_create();
 	load(props, true, "%s/k_helper/k_helper.kmod",
@@ -408,8 +394,6 @@ ATF_TC_BODY(cmd_load_recurse, tc)
 	prop_dictionary_t props;
 	char filename[MAXPATHLEN];
 
-	require_modular();
-
 	printf("Loading module with request to load another module\n");
 	props = prop_dictionary_create();
 	snprintf(filename, sizeof(filename), "%s/k_helper2/k_helper2.kmod",
@@ -444,8 +428,6 @@ ATF_TC_HEAD(cmd_stat, tc)
 }
 ATF_TC_BODY(cmd_stat, tc)
 {
-	require_modular();
-
 	ATF_CHECK(!k_helper_is_present(both_checks));
 
 	load(NULL, true, "%s/k_helper/k_helper.kmod",
@@ -476,8 +458,6 @@ ATF_TC_HEAD(cmd_unload, tc)
 }
 ATF_TC_BODY(cmd_unload, tc)
 {
-	require_modular();
-
 	load(NULL, true, "%s/k_helper/k_helper.kmod",
 	    atf_tc_get_config_var(tc, "srcdir"));
 
@@ -501,7 +481,6 @@ ATF_TC_CLEANUP(cmd_unload, tc)
 
 ATF_TP_ADD_TCS(tp)
 {
-	have_modular = check_modular();
 
 	ATF_TP_ADD_TC(tp, cmd_load);
 	ATF_TP_ADD_TC(tp, cmd_load_props);

Reply via email to