[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