[ovs-dev] [vlog v2 7/7] vlog: Make the vlog module catalog program-specific.

Ben Pfaff blp at nicira.com
Fri Jul 16 19:00:46 UTC 2010


Until now, the collection of vlog modules supported by a given OVS program
was not specific to that program.  That means that, for example, even
though ovs-dpctl does not have anything to do with jsonrpc, it still has
a vlog module for it.  This is confusing, at best.

This commit fixes the problem on some systems, in particular on ones that
use GCC and the GNU linker.  It uses the feature of the GNU linker
described in its manual as:

    If an orphaned section's name is representable as a C identifier then
    the linker will automatically see PROVIDE two symbols: __start_SECNAME
    and __end_SECNAME, where SECNAME is the name of the section.  These
    indicate the start address and end address of the orphaned section
    respectively.

Systems that don't support these features retain the earlier behavior.

This commit also fixes the annoyance that modifying lib/vlog-modules.def
causes all sources files that #include "vlog.h" to recompile.
---
 build-aux/check-vlog-modules |   66 +++++++++++++++++++
 configure.ac                 |    1 +
 extras/ezio/ovs-switchui.c   |    2 +-
 lib/automake.mk              |   32 ++--------
 lib/stream.c                 |    2 +-
 lib/stream.h                 |    2 +-
 lib/vlog.c                   |  142 ++++++++++++++++++++++-------------------
 lib/vlog.h                   |   76 ++++++++++++++--------
 m4/openvswitch.m4            |   75 ++++++++++++++++++++++
 tests/test-lockfile.c        |    3 +-
 tests/test-reconnect.c       |    3 +-
 tests/test-stp.c             |    2 +
 tests/test-vconn.c           |    4 +-
 utilities/nlmon.c            |    2 +-
 utilities/ovs-vsctl.c        |    9 ++-
 vswitchd/ovs-brcompatd.c     |    5 +-
 16 files changed, 292 insertions(+), 134 deletions(-)
 create mode 100755 build-aux/check-vlog-modules

diff --git a/build-aux/check-vlog-modules b/build-aux/check-vlog-modules
new file mode 100755
index 0000000..d40c048
--- /dev/null
+++ b/build-aux/check-vlog-modules
@@ -0,0 +1,66 @@
+#! /bin/sh
+
+if test "$1" = --help; then
+    cat <<EOF
+$0: cross-check declared and defined vlog modules
+usage: $0 [--help]
+
+Must be run from the top-level source directory.
+
+On systems that don't support user-defined section names, the 'vlog'
+logging subsystem requires the list of modules in lib/vlog-modules.def
+to match the set of vlog modules actually used by the source files.
+However, most Open vSwitch development happens on systems that do
+support user-defined section names and don't have this requirement.
+This utility runs automatically at build time to check this
+requirement "by hand", so that Open vSwitch developers don't
+accidentally break the build for others.
+EOF
+    exit 0
+elif test "$#" != 0; then
+    echo "no arguments accepted (use --help for help)"
+    exit 1
+elif test ! -e lib/vlog-modules.def; then
+    echo "must run from the top-level source directory (use --help for help)"
+    exit 1
+fi
+
+# We can only get a list of source files if this is a Git checkout.
+if test -e .git && (git --version) >/dev/null 2>&1; then
+    :
+else
+    exit 0
+fi
+
+# Get the list of modules declared in lib/vlog-modules.def.
+vlog_modules=`
+    sed -n 's/^VLOG_MODULE(\([_a-zA-Z0-9]\{1,\}\)).*$/\1/p' \
+    lib/vlog-modules.def \
+    | LC_ALL=C sort -u | xargs echo`
+
+# Get the list of modules defined in some source file.
+src_modules=`
+    git grep -h -E '^[ 	]*VLOG_DEFINE(_THIS)?_MODULE\([_a-zA-Z0-9]+\)[ 	]*$' \
+    | sed 's/.*(\([_a-zA-Z0-9]\{1,\}\)).*/\1/' \
+    | LC_ALL=C sort -u \
+    | xargs echo`
+
+rc=0
+
+for module in $vlog_modules; do
+    case " $src_modules " in
+        *" $module "*) ;;
+        *) echo "vlog module $module is declared in lib/vlog-modules.def but not defined by any source file";
+            rc=1 ;;
+    esac
+done
+
+for module in $src_modules; do
+    case " $vlog_modules " in
+        *" $module "*) ;;
+        *) echo "vlog module $module is defined in a source file but not declared in lib/vlog-modules.def";
+            rc=1 ;;
+    esac
+done
+
+exit $rc
diff --git a/configure.ac b/configure.ac
index aff53a1..fd3ce85 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,6 +65,7 @@ OVS_CHECK_MALLOC_HOOKS
 OVS_CHECK_VALGRIND
 OVS_CHECK_TTY_LOCK_DIR
 OVS_CHECK_SOCKET_LIBS
+OVS_CHECK_LINKER_SECTIONS
 
 AC_CHECK_FUNCS([strsignal])
 
diff --git a/extras/ezio/ovs-switchui.c b/extras/ezio/ovs-switchui.c
index 092eb1e..6f433a3 100644
--- a/extras/ezio/ovs-switchui.c
+++ b/extras/ezio/ovs-switchui.c
@@ -149,7 +149,7 @@ main(int argc, char *argv[])
     set_program_name(argv[0]);
     parse_options(argc, argv);
     signal(SIGPIPE, SIG_IGN);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_EMER);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_EMER);
     init_reboot_notifier();
 
     argc -= optind;
diff --git a/lib/automake.mk b/lib/automake.mk
index 046e9ab..3bf9da1 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -263,30 +263,8 @@ lib/coverage-counters.c: $(COVERAGE_FILES) lib/coverage-scan.pl
 	mv $@.tmp $@
 EXTRA_DIST += lib/coverage-scan.pl
 
-
-# Make sure that every vlog module listed in vlog-modules.def is
-# actually used somewhere.
-ALL_LOCAL += check-for-unused-vlog-modules
-check-for-unused-vlog-modules:
-	if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1; then    \
-	  cd $(srcdir);							      \
-	  decl_vlog=`sed -n 's/^VLOG_MODULE(\([_a-z0-9]\{1,\}\)).*$$/\1/p'    \
-	             lib/vlog-modules.def |				      \
-                     LC_ALL=C sort -u |					      \
-                     xargs echo`;					      \
-	  used_vlog=`git grep VLOG_DEFINE_THIS_MODULE |                       \
-	             sed -n 's/.*VLOG_DEFINE_THIS_MODULE(\([a-z_0-9]\{1,\}\)).*/\1/p' |	      \
-	             LC_ALL=C sort -u |					      \
-                     xargs echo`;					      \
-	  rc=0;								      \
-	  for decl in $$decl_vlog; do					      \
-            case " $$used_vlog " in					      \
-	      *" $$decl "*) ;;						      \
-	      *) echo "vlog module $$decl is declared in lib/vlog-modules.def \
-but not used by any source file";					      \
-                 rc=1 ;;						      \
-            esac							      \
-          done;								      \
-	  exit $$rc;							      \
-	fi
-.PHONY: check-for-unused-vlog-modules
+ALL_LOCAL += check-vlog-modules
+check-vlog-modules:
+	cd $(srcdir) && build-aux/check-vlog-modules
+.PHONY: check-vlog-modules
+EXTRA_DIST += build-aux/check-vlog-modules
diff --git a/lib/stream.c b/lib/stream.c
index 4d894e7..43c95b6 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -769,7 +769,7 @@ stream_content_type_to_string(enum stream_content_type type)
 void
 stream_report_content(const void *data, size_t size,
                       enum stream_content_type expected_type,
-                      enum vlog_module module, const char *stream_name)
+                      struct vlog_module *module, const char *stream_name)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
     enum stream_content_type actual_type;
diff --git a/lib/stream.h b/lib/stream.h
index 256667e..5c536c6 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -84,6 +84,6 @@ enum stream_content_type {
 };
 
 void stream_report_content(const void *, size_t, enum stream_content_type,
-                           enum vlog_module, const char *stream_name);
+                           struct vlog_module *, const char *stream_name);
 
 #endif /* stream.h */
diff --git a/lib/vlog.c b/lib/vlog.c
index 3887129..1c6d25b 100644
--- a/lib/vlog.c
+++ b/lib/vlog.c
@@ -49,12 +49,24 @@ static int syslog_levels[VLL_N_LEVELS] = {
 #undef VLOG_LEVEL
 };
 
-/* Name for each logging module */
-static const char *module_names[VLM_N_MODULES] = { 
-#define VLOG_MODULE(NAME) #NAME,
+/* The log modules. */
+#if USE_LINKER_SECTIONS
+extern struct vlog_module *__start_vlog_modules[];
+extern struct vlog_module *__stop_vlog_modules[];
+#define vlog_modules __start_vlog_modules
+#define n_vlog_modules (__stop_vlog_modules - __start_vlog_modules)
+#else
+#define VLOG_MODULE VLOG_DEFINE_MODULE__
+#include "vlog-modules.def"
+#undef VLOG_MODULE
+
+struct vlog_module *vlog_modules[] = {
+#define VLOG_MODULE(NAME) &VLM_##NAME,
 #include "vlog-modules.def"
 #undef VLOG_MODULE
 };
+#define n_vlog_modules ARRAY_SIZE(vlog_modules)
+#endif
 
 /* Information about each facility. */
 struct facility {
@@ -68,21 +80,6 @@ static struct facility facilities[VLF_N_FACILITIES] = {
 #undef VLOG_FACILITY
 };
 
-/* Current log levels. */
-static int levels[VLM_N_MODULES][VLF_N_FACILITIES] = {
-#define VLOG_MODULE(NAME) { VLL_INFO, VLL_INFO, VLL_INFO },
-#include "vlog-modules.def"
-#undef VLOG_MODULE
-};
-
-/* For fast checking whether we're logging anything for a given module and
- * level.*/
-enum vlog_level min_vlog_levels[VLM_N_MODULES] = {
-#define VLOG_MODULE(NAME) VLL_INFO,
-#include "vlog-modules.def"
-#undef VLOG_MODULE
-};
-
 /* Time at which vlog was initialized, in milliseconds. */
 static long long int boot_time;
 
@@ -93,7 +90,7 @@ static FILE *log_file;
 /* vlog initialized? */
 static bool vlog_inited;
 
-static void format_log_message(enum vlog_module, enum vlog_level,
+static void format_log_message(const struct vlog_module *, enum vlog_level,
                                enum vlog_facility, unsigned int msg_num,
                                const char *message, va_list, struct ds *)
     PRINTF_FORMAT(5, 0);
@@ -154,64 +151,76 @@ vlog_get_facility_val(const char *name)
 }
 
 /* Returns the name for logging module 'module'. */
-const char *vlog_get_module_name(enum vlog_module module) 
+const char *
+vlog_get_module_name(const struct vlog_module *module)
 {
-    assert(module < VLM_N_MODULES);
-    return module_names[module];
+    return module->name;
 }
 
-/* Returns the logging module named 'name', or VLM_N_MODULES if 'name' is not
- * the name of a logging module. */
-enum vlog_module
-vlog_get_module_val(const char *name) 
+/* Returns the logging module named 'name', or NULL if 'name' is not the name
+ * of a logging module. */
+struct vlog_module *
+vlog_module_from_name(const char *name)
 {
-    return search_name_array(name, module_names, ARRAY_SIZE(module_names));
+    struct vlog_module **mp;
+
+    for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
+        if (!strcasecmp(name, (*mp)->name)) {
+            return *mp;
+        }
+    }
+    return NULL;
 }
 
 /* Returns the current logging level for the given 'module' and 'facility'. */
 enum vlog_level
-vlog_get_level(enum vlog_module module, enum vlog_facility facility) 
+vlog_get_level(const struct vlog_module *module, enum vlog_facility facility) 
 {
-    assert(module < VLM_N_MODULES);
     assert(facility < VLF_N_FACILITIES);
-    return levels[module][facility];
+    return module->levels[facility];
 }
 
 static void
-update_min_level(enum vlog_module module)
+update_min_level(struct vlog_module *module)
 {
-    enum vlog_level min_level = VLL_EMER;
     enum vlog_facility facility;
 
+    module->min_level = VLL_EMER;
     for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
         if (log_file || facility != VLF_FILE) {
-            min_level = MAX(min_level, levels[module][facility]); 
+            enum vlog_level level = module->levels[facility];
+            if (level < module->min_level) {
+                module->min_level = level;
+            }
         }
     }
-    min_vlog_levels[module] = min_level;
 }
 
 static void
-set_facility_level(enum vlog_facility facility, enum vlog_module module,
+set_facility_level(enum vlog_facility facility, struct vlog_module *module,
                    enum vlog_level level)
 {
     assert(facility >= 0 && facility < VLF_N_FACILITIES);
     assert(level < VLL_N_LEVELS);
 
-    if (module == VLM_ANY_MODULE) {
-        for (module = 0; module < VLM_N_MODULES; module++) {
-            levels[module][facility] = level;
-            update_min_level(module);
+    if (!module) {
+        struct vlog_module **mp;
+
+        for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
+            (*mp)->levels[facility] = level;
+            update_min_level(*mp);
         }
     } else {
-        levels[module][facility] = level;
+        module->levels[facility] = level;
         update_min_level(module);
     }
 }
 
-/* Sets the logging level for the given 'module' and 'facility' to 'level'. */
+/* Sets the logging level for the given 'module' and 'facility' to 'level'.  A
+ * null 'module' or a 'facility' of VLF_ANY_FACILITY is treated as a wildcard
+ * across all modules or facilities, respectively. */
 void
-vlog_set_levels(enum vlog_module module, enum vlog_facility facility,
+vlog_set_levels(struct vlog_module *module, enum vlog_facility facility,
                 enum vlog_level level) 
 {
     assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
@@ -267,7 +276,7 @@ int
 vlog_set_log_file(const char *file_name)
 {
     char *old_log_file_name;
-    enum vlog_module module;
+    struct vlog_module **mp;
     int error;
 
     /* Close old log file. */
@@ -289,8 +298,8 @@ vlog_set_log_file(const char *file_name)
     /* Open new log file and update min_levels[] to reflect whether we actually
      * have a log_file. */
     log_file = fopen(log_file_name, "a");
-    for (module = 0; module < VLM_N_MODULES; module++) {
-        update_min_level(module);
+    for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
+        update_min_level(*mp);
     }
 
     /* Log success or failure. */
@@ -331,7 +340,7 @@ vlog_set_levels_from_string(const char *s_)
 
     for (module = strtok_r(s, ": \t", &save_ptr); module != NULL;
          module = strtok_r(NULL, ": \t", &save_ptr)) {
-        enum vlog_module e_module;
+        struct vlog_module *e_module;
         enum vlog_facility e_facility;
 
         facility = strtok_r(NULL, ":", &save_ptr);
@@ -355,10 +364,10 @@ vlog_set_levels_from_string(const char *s_)
             enum vlog_level e_level;
 
             if (!strcmp(module, "ANY")) {
-                e_module = VLM_ANY_MODULE;
+                e_module = NULL;
             } else {
-                e_module = vlog_get_module_val(module);
-                if (e_module >= VLM_N_MODULES) {
+                e_module = vlog_module_from_name(module);
+                if (!e_module) {
                     char *msg = xasprintf("unknown module \"%s\"", module);
                     free(s);
                     return msg;
@@ -391,7 +400,7 @@ vlog_set_verbosity(const char *arg)
             ovs_fatal(0, "processing \"%s\": %s", arg, msg);
         }
     } else {
-        vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
+        vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
     }
 }
 
@@ -473,17 +482,17 @@ char *
 vlog_get_levels(void)
 {
     struct ds s = DS_EMPTY_INITIALIZER;
-    enum vlog_module module;
+    struct vlog_module **mp;
 
     ds_put_format(&s, "                 console    syslog    file\n");
     ds_put_format(&s, "                 -------    ------    ------\n");
 
-    for (module = 0; module < VLM_N_MODULES; module++) {
+    for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
         ds_put_format(&s, "%-16s  %4s       %4s       %4s\n",
-           vlog_get_module_name(module),
-           vlog_get_level_name(vlog_get_level(module, VLF_CONSOLE)),
-           vlog_get_level_name(vlog_get_level(module, VLF_SYSLOG)),
-           vlog_get_level_name(vlog_get_level(module, VLF_FILE)));
+           vlog_get_module_name(*mp),
+           vlog_get_level_name(vlog_get_level(*mp, VLF_CONSOLE)),
+           vlog_get_level_name(vlog_get_level(*mp, VLF_SYSLOG)),
+           vlog_get_level_name(vlog_get_level(*mp, VLF_FILE)));
     }
 
     return ds_cstr(&s);
@@ -493,9 +502,9 @@ vlog_get_levels(void)
  * would cause some log output, false if that module and level are completely
  * disabled. */
 bool
-vlog_is_enabled(enum vlog_module module, enum vlog_level level)
+vlog_is_enabled(const struct vlog_module *module, enum vlog_level level)
 {
-    return min_vlog_levels[module] >= level;
+    return module->min_level >= level;
 }
 
 static const char *
@@ -514,7 +523,7 @@ fetch_braces(const char *p, const char *def, char *out, size_t out_size)
 }
 
 static void
-format_log_message(enum vlog_module module, enum vlog_level level,
+format_log_message(const struct vlog_module *module, enum vlog_level level,
                    enum vlog_facility facility, unsigned int msg_num,
                    const char *message, va_list args_, struct ds *s)
 {
@@ -609,12 +618,12 @@ format_log_message(enum vlog_module module, enum vlog_level level,
  *
  * Guaranteed to preserve errno. */
 void
-vlog_valist(enum vlog_module module, enum vlog_level level,
+vlog_valist(const struct vlog_module *module, enum vlog_level level,
             const char *message, va_list args)
 {
-    bool log_to_console = levels[module][VLF_CONSOLE] >= level;
-    bool log_to_syslog = levels[module][VLF_SYSLOG] >= level;
-    bool log_to_file = levels[module][VLF_FILE] >= level && log_file;
+    bool log_to_console = module->levels[VLF_CONSOLE] >= level;
+    bool log_to_syslog = module->levels[VLF_SYSLOG] >= level;
+    bool log_to_file = module->levels[VLF_FILE] >= level && log_file;
     if (log_to_console || log_to_syslog || log_to_file) {
         int save_errno = errno;
         static unsigned int msg_num;
@@ -660,7 +669,8 @@ vlog_valist(enum vlog_module module, enum vlog_level level,
 }
 
 void
-vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
+vlog(const struct vlog_module *module, enum vlog_level level,
+     const char *message, ...)
 {
     va_list args;
 
@@ -670,7 +680,7 @@ vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
 }
 
 bool
-vlog_should_drop(enum vlog_module module, enum vlog_level level,
+vlog_should_drop(const struct vlog_module *module, enum vlog_level level,
                  struct vlog_rate_limit *rl)
 {
     if (!vlog_is_enabled(module, level)) {
@@ -710,7 +720,7 @@ vlog_should_drop(enum vlog_module module, enum vlog_level level,
 }
 
 void
-vlog_rate_limit(enum vlog_module module, enum vlog_level level,
+vlog_rate_limit(const struct vlog_module *module, enum vlog_level level,
                 struct vlog_rate_limit *rl, const char *message, ...)
 {
     if (!vlog_should_drop(module, level, rl)) {
diff --git a/lib/vlog.h b/lib/vlog.h
index 53e8f39..7a55dea 100644
--- a/lib/vlog.h
+++ b/lib/vlog.h
@@ -60,16 +60,25 @@ enum vlog_facility {
 const char *vlog_get_facility_name(enum vlog_facility);
 enum vlog_facility vlog_get_facility_val(const char *name);
 
-/* VLM_ constant for each vlog module. */
-enum vlog_module {
-#define VLOG_MODULE(NAME) VLM_##NAME,
-#include "vlog-modules.def"
-    VLM_N_MODULES,
-    VLM_ANY_MODULE = -1
+/* A log module. */
+struct vlog_module {
+    const char *name;             /* User-visible name. */
+    int levels[VLF_N_FACILITIES]; /* Minimum log level for each facility. */
+    int min_level;                /* Minimum log level for any facility. */
 };
 
-const char *vlog_get_module_name(enum vlog_module);
-enum vlog_module vlog_get_module_val(const char *name);
+/* Creates and initializes a global instance of a module named MODULE. */
+#if USE_LINKER_SECTIONS
+#define VLOG_DEFINE_MODULE(MODULE)                                      \
+        VLOG_DEFINE_MODULE__(MODULE)                                    \
+        struct vlog_module *vlog_module_ptr_##MODULE                    \
+            __attribute__((section("vlog_modules"))) = &VLM_##MODULE;
+#else
+#define VLOG_DEFINE_MODULE(MODULE) extern struct vlog_module VLM_##MODULE;
+#endif
+
+const char *vlog_get_module_name(const struct vlog_module *);
+struct vlog_module *vlog_module_from_name(const char *name);
 
 /* Rate-limiter for log messages. */
 struct vlog_rate_limit {
@@ -103,12 +112,13 @@ struct vlog_rate_limit {
         }
 
 /* Configuring how each module logs messages. */
-enum vlog_level vlog_get_level(enum vlog_module, enum vlog_facility);
-void vlog_set_levels(enum vlog_module, enum vlog_facility, enum vlog_level);
+enum vlog_level vlog_get_level(const struct vlog_module *, enum vlog_facility);
+void vlog_set_levels(struct vlog_module *,
+                     enum vlog_facility, enum vlog_level);
 char *vlog_set_levels_from_string(const char *);
 char *vlog_get_levels(void);
-bool vlog_is_enabled(enum vlog_module, enum vlog_level);
-bool vlog_should_drop(enum vlog_module, enum vlog_level,
+bool vlog_is_enabled(const struct vlog_module *, enum vlog_level);
+bool vlog_should_drop(const struct vlog_module *, enum vlog_level,
                       struct vlog_rate_limit *);
 void vlog_set_verbosity(const char *arg);
 
@@ -121,19 +131,25 @@ int vlog_reopen_log_file(void);
 /* Function for actual logging. */
 void vlog_init(void);
 void vlog_exit(void);
-void vlog(enum vlog_module, enum vlog_level, const char *format, ...)
+void vlog(const struct vlog_module *, enum vlog_level, const char *format, ...)
     __attribute__((format(printf, 3, 4)));
-void vlog_valist(enum vlog_module, enum vlog_level, const char *, va_list)
+void vlog_valist(const struct vlog_module *, enum vlog_level,
+                 const char *, va_list)
     __attribute__((format(printf, 3, 0)));
-void vlog_rate_limit(enum vlog_module, enum vlog_level,
+void vlog_rate_limit(const struct vlog_module *, enum vlog_level,
                      struct vlog_rate_limit *, const char *, ...)
     __attribute__((format(printf, 4, 5)));
 
-/* Defines THIS_MODULE as MODULE, for use with the convenience macros below. */
-#define VLOG_DEFINE_THIS_MODULE(MODULE) enum { THIS_MODULE = VLM_##MODULE };
+/* Creates and initializes a global instance of a module named MODULE, and
+ * defines a static variable named THIS_MODULE that points to it, for use with
+ * the convenience macros below. */
+#define VLOG_DEFINE_THIS_MODULE(MODULE)                                 \
+        VLOG_DEFINE_MODULE(MODULE)                                      \
+        static struct vlog_module *const THIS_MODULE = &VLM_##MODULE;
 
-/* Convenience macros.  These assume that THIS_MODULE is defined as the current
- * module, as set up by e.g. the VLOG_DEFINE_MODULE macro above.
+/* Convenience macros.  These assume that THIS_MODULE points to a "struct
+ * vlog_module" for the current module, as set up by e.g. the
+ * VLOG_DEFINE_MODULE macro above.
  *
  * Guaranteed to preserve errno.
  */
@@ -180,20 +196,26 @@ void vlog_rate_limit(enum vlog_module, enum vlog_level,
 void vlog_usage(void);
 
 /* Implementation details. */
-#define VLOG(LEVEL, ...)                                \
-    do {                                                \
-        if (min_vlog_levels[THIS_MODULE] >= LEVEL) {    \
-            vlog(THIS_MODULE, LEVEL, __VA_ARGS__);      \
-        }                                               \
+#define VLOG(LEVEL, ...)                            \
+    do {                                            \
+        if (THIS_MODULE->min_level >= LEVEL) {      \
+            vlog(THIS_MODULE, LEVEL, __VA_ARGS__);  \
+        }                                           \
     } while (0)
 #define VLOG_RL(RL, LEVEL, ...)                                     \
     do {                                                            \
-        if (min_vlog_levels[THIS_MODULE] >= LEVEL) {                \
+        if (THIS_MODULE->min_level >= LEVEL) {                      \
             vlog_rate_limit(THIS_MODULE, LEVEL, RL, __VA_ARGS__);   \
         }                                                           \
     } while (0)
-extern enum vlog_level min_vlog_levels[VLM_N_MODULES];
- 
+#define VLOG_DEFINE_MODULE__(MODULE)                                    \
+        struct vlog_module VLM_##MODULE =                               \
+        {                                                               \
+            #MODULE,                                      /* name */    \
+            { [ 0 ... VLF_N_FACILITIES - 1] = VLL_INFO }, /* levels */  \
+            VLL_INFO,                                     /* min_level */ \
+        };
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4
index 0b22f64..6fb8609 100644
--- a/m4/openvswitch.m4
+++ b/m4/openvswitch.m4
@@ -347,3 +347,78 @@ AC_DEFUN([OVS_CHECK_OVSDBMONITOR],
    AC_MSG_CHECKING([whether to build ovsdbmonitor])
    AC_MSG_RESULT([$BUILD_OVSDBMONITOR])
    AM_CONDITIONAL([BUILD_OVSDBMONITOR], [test $BUILD_OVSDBMONITOR = yes])])
+
+# OVS_LINK2_IFELSE(SOURCE1, SOURCE2, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+# -------------------------------------------------------------
+# Based on AC_LINK_IFELSE, but tries to link both SOURCE1 and SOURCE2
+# into a program.
+#
+# This macro is borrowed from acinclude.m4 in GNU PSPP, which has the
+# following license:
+#
+#     Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+#     This file is free software; the Free Software Foundation
+#     gives unlimited permission to copy and/or distribute it,
+#     with or without modifications, as long as this notice is preserved.
+#
+m4_define([OVS_LINK2_IFELSE],
+[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl
+mv conftest.$ac_ext conftest1.$ac_ext
+m4_ifvaln([$2], [AC_LANG_CONFTEST([$2])])dnl
+mv conftest.$ac_ext conftest2.$ac_ext
+rm -f conftest1.$ac_objext conftest2.$ac_objext conftest$ac_exeext
+ovs_link2='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest1.$ac_ext conftest2.$ac_ext $LIBS >&5'
+AS_IF([_AC_DO_STDERR($ovs_link2) && {
+	 test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 AS_TEST_X([conftest$ac_exeext])
+       }],
+      [$3],
+      [echo "$as_me: failed source file 1 of 2 was:" >&5
+sed 's/^/| /' conftest1.$ac_ext >&5
+echo "$as_me: failed source file 2 of 2 was:" >&5
+sed 's/^/| /' conftest2.$ac_ext >&5
+	$4])
+dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization)
+dnl information created by the PGI compiler (conftest_ipa8_conftest.oo),
+dnl as it would interfere with the next link command.
+rm -rf conftest.dSYM conftest1.dSYM conftest2.dSYM
+rm -f core conftest.err conftest1.err conftest2.err
+rm -f conftest1.$ac_objext conftest2.$ac_objext conftest*_ipa8_conftest*.oo
+rm -f conftest$ac_exeext
+rm -f m4_ifval([$1], [conftest1.$ac_ext]) m4_ifval([$2], [conftest1.$ac_ext])[]dnl
+])# OVS_LINK2_IFELSE
+
+dnl Defines USE_LINKER_SECTIONS to 1 if the compiler supports putting
+dnl variables in sections with user-defined names and the linker
+dnl automatically defines __start_SECNAME and __stop_SECNAME symbols
+dnl that designate the start and end of the sections.
+AC_DEFUN([OVS_CHECK_LINKER_SECTIONS],
+  [AC_CACHE_CHECK(
+    [for user-defined linker section support],
+    [ovs_cv_use_linker_sections],
+    [OVS_LINK2_IFELSE(
+      [AC_LANG_SOURCE(
+        [int a __attribute__((__section__("mysection"))) = 1;
+         int b __attribute__((__section__("mysection"))) = 2;
+         int c __attribute__((__section__("mysection"))) = 3;])],
+      [AC_LANG_PROGRAM(
+        [#include <stdio.h>
+         extern int __start_mysection;
+         extern int __stop_mysection;],
+        [int n_ints = &__stop_mysection - &__start_mysection;
+         int *i;
+         for (i = &__start_mysection; i < &__start_mysection + n_ints; i++) {
+             printf("%d\n", *i);
+         }])],
+      [ovs_cv_use_linker_sections=yes],
+      [ovs_cv_use_linker_sections=no])])
+   if test $ovs_cv_use_linker_sections = yes; then
+     AC_DEFINE([USE_LINKER_SECTIONS], [1],
+               [Define to 1 if the compiler support putting variables
+                into sections with user-defined names and the linker
+                automatically defines __start_SECNAME and __stop_SECNAME
+                symbols that designate the start and end of the section.])
+   fi])
diff --git a/tests/test-lockfile.c b/tests/test-lockfile.c
index f18e24e..0feb270 100644
--- a/tests/test-lockfile.c
+++ b/tests/test-lockfile.c
@@ -238,10 +238,11 @@ static const struct test tests[] = {
 int
 main(int argc, char *argv[])
 {
+    extern struct vlog_module VLM_lockfile;
     size_t i;
 
     set_program_name(argv[0]);
-    vlog_set_levels(VLM_lockfile, VLF_ANY_FACILITY, VLL_ERR);
+    vlog_set_levels(&VLM_lockfile, VLF_ANY_FACILITY, VLL_ERR);
 
     if (argc != 2) {
         ovs_fatal(0, "exactly one argument required; use \"%s help\" for help",
diff --git a/tests/test-reconnect.c b/tests/test-reconnect.c
index 2bb59d5..0f49d7f 100644
--- a/tests/test-reconnect.c
+++ b/tests/test-reconnect.c
@@ -40,12 +40,13 @@ static void diff_stats(const struct reconnect_stats *old,
 int
 main(void)
 {
+    extern struct vlog_module VLM_reconnect;
     struct reconnect_stats prev;
     unsigned int old_max_tries;
     int old_time;
     char line[128];
 
-    vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_EMER);
+    vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_EMER);
 
     now = 1000;
     reconnect = reconnect_create(now);
diff --git a/tests/test-stp.c b/tests/test-stp.c
index eab13d6..83d571d 100644
--- a/tests/test-stp.c
+++ b/tests/test-stp.c
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <config.h>
+
 #include "stp.h"
 #include <assert.h>
 #include <ctype.h>
diff --git a/tests/test-vconn.c b/tests/test-vconn.c
index 32228f8..12b69ca 100644
--- a/tests/test-vconn.c
+++ b/tests/test-vconn.c
@@ -401,8 +401,8 @@ int
 main(int argc, char *argv[])
 {
     set_program_name(argv[0]);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_EMER);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_DBG);
+    vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_EMER);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_DBG);
     signal(SIGPIPE, SIG_IGN);
 
     time_alarm(10);
diff --git a/utilities/nlmon.c b/utilities/nlmon.c
index 699df13..672fae4 100644
--- a/utilities/nlmon.c
+++ b/utilities/nlmon.c
@@ -42,7 +42,7 @@ main(int argc OVS_UNUSED, char *argv[])
     int error;
 
     set_program_name(argv[0]);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
+    vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
 
     error = nl_sock_create(NETLINK_ROUTE, RTNLGRP_LINK, 0, 0, &sock);
     if (error) {
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index 7ae4f2d..69ce481 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -118,6 +118,7 @@ static void set_column(const struct vsctl_table_class *,
 int
 main(int argc, char *argv[])
 {
+    extern struct vlog_module VLM_reconnect;
     struct ovsdb_idl *idl;
     struct vsctl_command *commands;
     size_t n_commands;
@@ -125,8 +126,8 @@ main(int argc, char *argv[])
 
     set_program_name(argv[0]);
     signal(SIGPIPE, SIG_IGN);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
-    vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
+    vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
     ovsrec_init();
 
     /* Log our arguments.  This is often valuable for debugging systems. */
@@ -201,7 +202,7 @@ parse_options(int argc, char *argv[])
             break;
 
         case OPT_NO_SYSLOG:
-            vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
+            vlog_set_levels(&VLM_vsctl, VLF_SYSLOG, VLL_WARN);
             break;
 
         case OPT_NO_WAIT:
@@ -383,7 +384,7 @@ vsctl_fatal(const char *format, ...)
     message = xvasprintf(format, args);
     va_end(args);
 
-    vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
+    vlog_set_levels(&VLM_vsctl, VLF_CONSOLE, VLL_EMER);
     VLOG_ERR("%s", message);
     ovs_error(0, "%s", message);
     vsctl_exit(EXIT_FAILURE);
diff --git a/vswitchd/ovs-brcompatd.c b/vswitchd/ovs-brcompatd.c
index 5e59373..0b5ebb9 100644
--- a/vswitchd/ovs-brcompatd.c
+++ b/vswitchd/ovs-brcompatd.c
@@ -1287,6 +1287,7 @@ rtnl_recv_update(struct ovsdb_idl *idl,
 int
 main(int argc, char *argv[])
 {
+    extern struct vlog_module VLM_reconnect;
     struct unixctl_server *unixctl;
     const char *remote;
     struct ovsdb_idl *idl;
@@ -1294,8 +1295,8 @@ main(int argc, char *argv[])
 
     proctitle_init(argc, argv);
     set_program_name(argv[0]);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
-    vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
+    vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
 
     remote = parse_options(argc, argv);
     signal(SIGPIPE, SIG_IGN);
-- 
1.7.1





More information about the dev mailing list