[openib-general] [PATCH] opensm: option to limit size of OpenSM log file

Sasha Khapyorsky sashak at voltaire.com
Tue Aug 22 14:18:55 PDT 2006


Hi Hal,

There is new option which specified max size of OpenSM log file. The
default is '0' (not-limited). Please note osm_log_init() has new
parameter now.

We already saw the problems with FS overflowing in real life - we may
want those related fixes in OFED too.

Sasha


opensm: option to limit size of OpenSM log file

New option '-L' will limit size of OpenSM log file. If specified the log
file will be truncated upon reaching this limit.

Signed-off-by: Sasha Khapyorsky <sashak at voltaire.com>
---

 osm/complib/cl_event_wheel.c    |    2 
 osm/include/opensm/osm_log.h    |   44 +----------
 osm/include/opensm/osm_subnet.h |    6 +
 osm/opensm/libopensm.map        |    1 
 osm/opensm/main.c               |   13 +++
 osm/opensm/osm_log.c            |  163 ++++++++++++++++++++++++++-------------
 osm/opensm/osm_opensm.c         |    3 -
 osm/opensm/osm_subnet.c         |    9 ++
 osm/osmtest/osmtest.c           |    2 
 9 files changed, 143 insertions(+), 100 deletions(-)

diff --git a/osm/complib/cl_event_wheel.c b/osm/complib/cl_event_wheel.c
index 46c1f8e..a215f40 100644
--- a/osm/complib/cl_event_wheel.c
+++ b/osm/complib/cl_event_wheel.c
@@ -610,7 +610,7 @@ main ()
   cl_event_wheel_construct( &event_wheel );
 
   /* init */
-  osm_log_init( &log, TRUE, 0xff, NULL, FALSE);
+  osm_log_init( &log, TRUE, 0xff, NULL, 0, FALSE);
   cl_event_wheel_init( &event_wheel, &log );
 
   /* Start Playing */
diff --git a/osm/include/opensm/osm_log.h b/osm/include/opensm/osm_log.h
index f5bffd1..5bfaef5 100644
--- a/osm/include/opensm/osm_log.h
+++ b/osm/include/opensm/osm_log.h
@@ -121,6 +121,8 @@ typedef struct _osm_log
 {
 	osm_log_level_t			level;
 	cl_spinlock_t			lock;
+	unsigned long			count;
+	unsigned long                   max_size;
 	boolean_t			flush;
 	FILE*				out_port;
 } osm_log_t;
@@ -211,50 +213,14 @@ osm_log_destroy(
 *
 * SYNOPSIS
 */
-static inline ib_api_status_t
+ib_api_status_t
 osm_log_init(
   IN osm_log_t* const p_log,
   IN const boolean_t flush,
   IN const uint8_t log_flags,
   IN const char *log_file,
-  IN const boolean_t accum_log_file )
-{
-  p_log->level = log_flags;
-  p_log->flush = flush;
-
-  if (log_file == NULL || !strcmp(log_file, "-") ||
-      !strcmp(log_file, "stdout"))
-  {
-    p_log->out_port = stdout;
-  }
-  else if (!strcmp(log_file, "stderr"))
-  {
-    p_log->out_port = stderr;
-  }
-  else
-  {
-    if (accum_log_file)
-      p_log->out_port = fopen(log_file, "a+");
-    else
-      p_log->out_port = fopen(log_file, "w+");
-
-    if (!p_log->out_port)
-    {
-      if (accum_log_file)
-        printf("Cannot open %s for appending. Permission denied\n", log_file);
-      else
-        printf("Cannot open %s for writing. Permission denied\n", log_file);
-
-      return(IB_UNKNOWN_ERROR);
-    }
-  }
-  openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
-
-  if (cl_spinlock_init( &p_log->lock ) == CL_SUCCESS) 
-    return IB_SUCCESS;
-  else
-    return IB_ERROR;
-}
+  IN const unsigned long max_size,
+  IN const boolean_t accum_log_file );
 /*
 * PARAMETERS
 *	p_log
diff --git a/osm/include/opensm/osm_subnet.h b/osm/include/opensm/osm_subnet.h
index b45e5b6..650391b 100644
--- a/osm/include/opensm/osm_subnet.h
+++ b/osm/include/opensm/osm_subnet.h
@@ -261,6 +261,7 @@ typedef struct _osm_subn_opt
   uint8_t                  log_flags;
   char *                   dump_files_dir;
   char *                   log_file;
+  unsigned long            log_max_size;
   char *                   partition_config_file;
   boolean_t                no_partition_enforcement;
   boolean_t                no_qos;
@@ -388,6 +389,11 @@ typedef struct _osm_subn_opt
 *	log_file
 *		Name of the log file (or NULL) for stdout.
 *
+*	log_limit
+*		This option defines maximal log file size in MB. When
+*		specified the log file will be truncated upon reaching
+*		this limit.
+*
 *	accum_log_file
 *		If TRUE (default) - the log file will be accumulated.
 *		If FALSE - the log file will be erased before starting current opensm run.
diff --git a/osm/opensm/libopensm.map b/osm/opensm/libopensm.map
index 2b45b5d..c5bc0ab 100644
--- a/osm/opensm/libopensm.map
+++ b/osm/opensm/libopensm.map
@@ -2,6 +2,7 @@ OPENSM_1.1 {
 	global:
 		osm_log;
 		osm_is_debug;
+		osm_log_init;
 		osm_mad_pool_construct;
 		osm_mad_pool_destroy;
 		osm_mad_pool_init;
diff --git a/osm/opensm/main.c b/osm/opensm/main.c
index b429626..d5d8211 100644
--- a/osm/opensm/main.c
+++ b/osm/opensm/main.c
@@ -228,6 +228,11 @@ show_usage(void)
           "          This option defines the log to be the given file.\n"
           "          By default the log goes to /var/log/osm.log.\n"
           "          For the log to go to standard output use -f stdout.\n\n");
+  printf( "-L <size in MB>\n"
+          "--log_limit <size in MB>\n"
+          "          This option defines maximal log file size in MB. When\n"
+          "          specified the log file will be truncated upon reaching\n"
+          "          this limit.\n\n");
   printf( "-e\n"
           "--erase_log_file\n"
           "          This option will cause deletion of the log file\n"
@@ -527,7 +532,7 @@ #endif
   boolean_t             cache_options = FALSE;
   char                 *ignore_guids_file_name = NULL;
   uint32_t              val;
-  const char * const    short_option = "i:f:ed:g:l:s:t:a:R:U:P:NQvVhorcyx";
+  const char * const    short_option = "i:f:ed:g:l:L:s:t:a:R:U:P:NQvVhorcyx";
 
   /*
     In the array below, the 2nd parameter specified the number
@@ -547,6 +552,7 @@ #endif
       {  "verbose",       0, NULL, 'v'},
       {  "D",             1, NULL, 'D'},
       {  "log_file",      1, NULL, 'f'},
+      {  "log_limit",     1, NULL, 'L'},
       {  "erase_log_file",0, NULL, 'e'},
       {  "Pconfig",       1, NULL, 'P'},
       {  "no_part_enforce",0,NULL, 'N'},
@@ -731,6 +737,11 @@ #endif
       opt.log_file = optarg;
       break;
 
+    case 'L':
+      opt.log_max_size = strtoul(optarg, NULL, 0) * (1024*1024);
+      printf(" Log file max size is %lu bytes\n", opt.log_max_size);
+      break;
+
     case 'e':
       opt.accum_log_file = FALSE;
       printf(" Creating new log file\n");
diff --git a/osm/opensm/osm_log.c b/osm/opensm/osm_log.c
index 6efbc5a..eba3cb6 100644
--- a/osm/opensm/osm_log.c
+++ b/osm/opensm/osm_log.c
@@ -83,6 +83,18 @@ #endif /* ndef WIN32 */
 
 static int log_exit_count = 0;
 
+static void truncate_log_file(osm_log_t* const p_log)
+{
+	int fd = fileno(p_log->out_port);
+	if (ftruncate(fd, 0) < 0)
+		fprintf(stderr, "truncate_log_file: cannot truncate: %s\n",
+			strerror(errno));
+	if (lseek(fd, 0, SEEK_SET) < 0)
+		fprintf(stderr, "truncate_log_file: cannot rewind: %s\n",
+			strerror(errno));
+	p_log->count = 0;
+}
+
 void
 osm_log(
   IN osm_log_t* const p_log,
@@ -110,84 +122,67 @@ #else
 #endif /* WIN32 */
 
   /* If this is a call to syslog - always print it */
-  if ( verbosity & OSM_LOG_SYS )
+  if ( verbosity & (OSM_LOG_SYS|p_log->level))
   {
-    /* this is a call to the syslog */
     va_start( args, p_str );
     vsprintf( buffer, p_str, args );
     va_end(args);
-    cl_log_event("OpenSM", LOG_INFO, buffer , NULL, 0);
 
-    /* SYSLOG should go to stdout too */
-    if (p_log->out_port != stdout)
-    {
-      printf("%s\n", buffer);
-      fflush( stdout );
-    }
+    /* this is a call to the syslog */
+    if (verbosity & OSM_LOG_SYS) {
+      cl_log_event("OpenSM", LOG_INFO, buffer , NULL, 0);
 
-    /* send it also to the log file */
-#ifdef WIN32
-    GetLocalTime(&st);
-    fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
-                     st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
-                     pid, buffer);
-#else
-    fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s\n",
-             (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"),
-             result.tm_mday, result.tm_hour,
-             result.tm_min, result.tm_sec,
-             usecs, pid, buffer);
-    fflush( p_log->out_port );
-#endif    
-  }
+      /* SYSLOG should go to stdout too */
+      if (p_log->out_port != stdout)
+      {
+        printf("%s\n", buffer);
+        fflush( stdout );
+      }
+    }
 
-  /* SYS messages go to the log anyways */
-  if (p_log->level & verbosity)
-  {
-    
-    va_start( args, p_str );
-    vsprintf( buffer, p_str, args );
-    va_end(args);
-    
     /* regular log to default out_port */
     cl_spinlock_acquire( &p_log->lock );
+
+    if (p_log->max_size && p_log->count > p_log->max_size) {
+      /* truncate here */
+      fprintf(stderr, "osm_log: log file exceeds the limit %lu. Truncating.\n",
+              p_log->max_size);
+      truncate_log_file(p_log);
+    }
+
 #ifdef WIN32
     GetLocalTime(&st);
  _retry:
-    ret = fprintf(   p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
+    ret = fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
                      st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
                      pid, buffer);
-    
 #else
     pid = pthread_self();
-    tim = time(NULL);
  _retry:
-    ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s",
-                   ((result.tm_mon < 12) && (result.tm_mon >= 0) ? 
-                    month_str[result.tm_mon] : "???"),
-                   result.tm_mday, result.tm_hour,
-                   result.tm_min, result.tm_sec,
-                   usecs, pid, buffer);
-#endif /*  WIN32 */
-
-    if (ret >= 0)
-      log_exit_count = 0;
-    else if (errno == ENOSPC && log_exit_count < 3) {
-      int fd = fileno(p_log->out_port);
+    ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s\n",
+             (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"),
+             result.tm_mday, result.tm_hour,
+             result.tm_min, result.tm_sec,
+             usecs, pid, buffer);
+#endif
+ 
+    /*  flush log */
+    if (ret > 0 && (p_log->flush || (verbosity & OSM_LOG_ERROR)) &&
+        fflush( p_log->out_port ) < 0)
+      ret = -1;
+
+    if (ret < 0 && errno == ENOSPC && log_exit_count < 3) {
       fprintf(stderr, "osm_log write failed: %s. Truncating log file.\n",
               strerror(errno));
-      ftruncate(fd, 0);
-      lseek(fd, 0, SEEK_SET);
+      truncate_log_file(p_log);
       log_exit_count++;
       goto _retry;
     }
-    
-    /*
-      Flush log on errors too.
-    */
-    if( p_log->flush || (verbosity & OSM_LOG_ERROR) )
-      fflush( p_log->out_port );
-    
+    else {
+      log_exit_count = 0;
+      p_log->count += ret;
+    }
+
     cl_spinlock_release( &p_log->lock );
   }
 }
@@ -221,3 +216,59 @@ #else
   return FALSE;
 #endif /* defined( _DEBUG_ ) */
 }
+
+ib_api_status_t
+osm_log_init(
+  IN osm_log_t* const p_log,
+  IN const boolean_t flush,
+  IN const uint8_t log_flags,
+  IN const char *log_file,
+  IN const unsigned long max_size,
+  IN const boolean_t accum_log_file )
+{
+  struct stat st;
+
+  p_log->level = log_flags;
+  p_log->flush = flush;
+  p_log->count = 0;
+  p_log->max_size = 0;
+
+  if (log_file == NULL || !strcmp(log_file, "-") ||
+      !strcmp(log_file, "stdout"))
+  {
+    p_log->out_port = stdout;
+  }
+  else if (!strcmp(log_file, "stderr"))
+  {
+    p_log->out_port = stderr;
+  }
+  else
+  {
+    if (accum_log_file)
+      p_log->out_port = fopen(log_file, "a+");
+    else
+      p_log->out_port = fopen(log_file, "w+");
+
+    if (!p_log->out_port)
+    {
+      if (accum_log_file)
+        printf("Cannot open %s for appending. Permission denied\n", log_file);
+      else
+        printf("Cannot open %s for writing. Permission denied\n", log_file);
+
+      return(IB_UNKNOWN_ERROR);
+    }
+
+    if (fstat(fileno(p_log->out_port), &st) == 0)
+      p_log->count = st.st_size;
+
+    p_log->max_size = max_size;
+  }
+
+  openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
+
+  if (cl_spinlock_init( &p_log->lock ) == CL_SUCCESS) 
+    return IB_SUCCESS;
+  else
+    return IB_ERROR;
+}
diff --git a/osm/opensm/osm_opensm.c b/osm/opensm/osm_opensm.c
index 6704e98..0b39d13 100644
--- a/osm/opensm/osm_opensm.c
+++ b/osm/opensm/osm_opensm.c
@@ -181,7 +181,8 @@ osm_opensm_init(
    osm_opensm_construct( p_osm );
 
    status = osm_log_init( &p_osm->log, p_opt->force_log_flush,
-                          p_opt->log_flags, p_opt->log_file, p_opt->accum_log_file );
+                          p_opt->log_flags, p_opt->log_file,
+                          p_opt->log_max_size, p_opt->accum_log_file );
    if( status != IB_SUCCESS )
       return ( status );
 
diff --git a/osm/opensm/osm_subnet.c b/osm/opensm/osm_subnet.c
index bb5067a..395d71b 100644
--- a/osm/opensm/osm_subnet.c
+++ b/osm/opensm/osm_subnet.c
@@ -477,6 +477,7 @@ osm_subn_set_default_opt(
     p_opt->dump_files_dir = OSM_DEFAULT_TMP_DIR;
 
   p_opt->log_file = OSM_DEFAULT_LOG_FILE;
+  p_opt->log_max_size = 0;
   p_opt->partition_config_file = OSM_DEFAULT_PARTITION_CONFIG_FILE;
   p_opt->no_partition_enforcement = FALSE;
   p_opt->no_qos = FALSE;
@@ -923,6 +924,10 @@ osm_subn_parse_conf_file(
       __osm_subn_opts_unpack_charp(
         "log_file", p_key, p_val, &p_opts->log_file);
 
+      __osm_subn_opts_unpack_uint32(
+        "log_max_size",
+        p_key, p_val, (uint32_t *)&p_opts->log_max_size);
+      
       __osm_subn_opts_unpack_charp(
         "partition_config_file",
 	p_key, p_val, &p_opts->partition_config_file);
@@ -1173,7 +1178,8 @@ osm_subn_write_conf_file(
     "# Force flush of the log file after each log message\n"
     "force_log_flush %s\n\n"
     "# Log file to be used\n"
-    "log_file %s\n\n" 
+    "log_file %s\n\n"
+    "log_max_size %lu\n\n"
     "accum_log_file %s\n\n"
     "# The directory to hold the file OpenSM dumps\n"
     "dump_files_dir %s\n\n"
@@ -1186,6 +1192,7 @@ osm_subn_write_conf_file(
     p_opts->log_flags,
     p_opts->force_log_flush ? "TRUE" : "FALSE",
     p_opts->log_file,
+    p_opts->log_max_size,
     p_opts->accum_log_file ? "TRUE" : "FALSE",
     p_opts->dump_files_dir,
     p_opts->no_multicast_option ? "TRUE" : "FALSE",
diff --git a/osm/osmtest/osmtest.c b/osm/osmtest/osmtest.c
index f0f29d3..4f41e38 100644
--- a/osm/osmtest/osmtest.c
+++ b/osm/osmtest/osmtest.c
@@ -521,7 +521,7 @@ osmtest_init( IN osmtest_t * const p_osm
   osmtest_construct( p_osmt );
 
   status = osm_log_init( &p_osmt->log, p_opt->force_log_flush,
-                         0x0001, p_opt->log_file, TRUE );
+                         0x0001, p_opt->log_file, 0, TRUE );
   if( status != IB_SUCCESS )
     return ( status );
 




More information about the general mailing list