diff options
-rw-r--r-- | libglusterfs/src/globals.c | 2 | ||||
-rw-r--r-- | libglusterfs/src/logging.c | 173 | ||||
-rw-r--r-- | libglusterfs/src/logging.h | 39 | ||||
-rw-r--r-- | libglusterfs/src/mem-pool.c | 23 | ||||
-rw-r--r-- | libglusterfs/src/mem-pool.h | 64 |
5 files changed, 235 insertions, 66 deletions
diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c index 3121a1f1415..9e9870e0bf0 100644 --- a/libglusterfs/src/globals.c +++ b/libglusterfs/src/globals.c @@ -349,6 +349,8 @@ glusterfs_globals_init () gf_op_list_init (); + gf_log_globals_init (); + ret = glusterfs_ctx_init (); if (ret) goto out; diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c index ed024840aa4..4c6bc2ed73e 100644 --- a/libglusterfs/src/logging.c +++ b/libglusterfs/src/logging.c @@ -48,8 +48,8 @@ static pthread_mutex_t logfile_mutex; static char *filename = NULL; static uint8_t logrotate = 0; static FILE *logfile = NULL; -static gf_loglevel_t loglevel = GF_LOG_MAX; -static int gf_log_syslog = 0; +static gf_loglevel_t loglevel = GF_LOG_INFO; +static int gf_log_syslog = 1; char gf_log_xl_log_set; gf_loglevel_t gf_log_loglevel; /* extern'd */ @@ -115,6 +115,18 @@ gf_log_fini (void) } +void +gf_log_globals_init (void) +{ + pthread_mutex_init (&logfile_mutex, NULL); + +#ifdef GF_LINUX_HOST_OS + /* For the 'syslog' output. one can grep 'GlusterFS' in syslog + for serious logs */ + openlog ("GlusterFS", LOG_PID, LOG_DAEMON); +#endif +} + int gf_log_init (const char *file) { @@ -123,8 +135,6 @@ gf_log_init (const char *file) return -1; } - pthread_mutex_init (&logfile_mutex, NULL); - filename = gf_strdup (file); if (!filename) { fprintf (stderr, "gf_log_init: strdup error\n"); @@ -140,12 +150,6 @@ gf_log_init (const char *file) return -1; } -#ifdef GF_LINUX_HOST_OS - /* For the 'syslog' output. one can grep 'GlusterFS' in syslog - for serious logs */ - openlog ("GlusterFS", LOG_PID, LOG_DAEMON); -#endif - gf_log_logfile = logfile; return 0; @@ -170,8 +174,6 @@ struct _log_msg { }; - - void gf_log_lock (void) { @@ -193,6 +195,123 @@ gf_log_cleanup (void) } int +_gf_log_nomem (const char *domain, const char *file, + const char *function, int line, gf_loglevel_t level, + size_t size) +{ + const char *basename = NULL; + struct tm *tm = NULL; + xlator_t *this = NULL; + struct timeval tv = {0,}; + int ret = 0; + gf_loglevel_t xlator_loglevel = 0; + char msg[8092]; + char timestr[256]; + char callstr[4096]; + + this = THIS; + + xlator_loglevel = this->loglevel; + if (xlator_loglevel == 0) + xlator_loglevel = loglevel; + + if (level > xlator_loglevel) + goto out; + + static char *level_strings[] = {"", /* NONE */ + "M", /* EMERGENCY */ + "A", /* ALERT */ + "C", /* CRITICAL */ + "E", /* ERROR */ + "W", /* WARNING */ + "N", /* NOTICE */ + "I", /* INFO/NORMAL */ + "D", /* DEBUG */ + "T", /* TRACE */ + ""}; + + if (!domain || !file || !function) { + fprintf (stderr, + "logging: %s:%s():%d: invalid argument\n", + __FILE__, __PRETTY_FUNCTION__, __LINE__); + return -1; + } + +#if HAVE_BACKTRACE + /* Print 'calling function' */ + do { + void *array[5]; + char **callingfn = NULL; + size_t bt_size = 0; + + bt_size = backtrace (array, 5); + if (bt_size) + callingfn = backtrace_symbols (&array[2], bt_size-2); + if (!callingfn) + break; + + if (bt_size == 5) + snprintf (callstr, 4096, "(-->%s (-->%s (-->%s)))", + callingfn[2], callingfn[1], callingfn[0]); + if (bt_size == 4) + snprintf (callstr, 4096, "(-->%s (-->%s))", + callingfn[1], callingfn[0]); + if (bt_size == 3) + snprintf (callstr, 4096, "(-->%s)", callingfn[0]); + + free (callingfn); + } while (0); +#endif /* HAVE_BACKTRACE */ + + ret = gettimeofday (&tv, NULL); + if (-1 == ret) + goto out; + + tm = localtime (&tv.tv_sec); + + pthread_mutex_lock (&logfile_mutex); + { + strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm); + snprintf (timestr + strlen (timestr), 256 - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + + basename = strrchr (file, '/'); + if (basename) + basename++; + else + basename = file; + + ret = sprintf (msg, "[%s] %s [%s:%d:%s] %s %s: no memory " + "available for size (%"GF_PRI_SIZET")", + timestr, level_strings[level], + basename, line, function, callstr, + domain, size); + if (-1 == ret) { + goto unlock; + } + + if (logfile) { + fprintf (logfile, "%s\n", msg); + fflush (logfile); + } else { + fprintf (stderr, "%s\n", msg); + } + +#ifdef GF_LINUX_HOST_OS + /* We want only serious log in 'syslog', not our debug + and trace logs */ + if (gf_log_syslog && level && (level <= GF_LOG_ERROR)) + syslog ((level-1), "%s\n", msg); +#endif + } + +unlock: + pthread_mutex_unlock (&logfile_mutex); +out: + return ret; + } + +int _gf_log_callingfn (const char *domain, const char *file, const char *function, int line, gf_loglevel_t level, const char *fmt, ...) { @@ -210,9 +329,6 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function, gf_loglevel_t xlator_loglevel = 0; va_list ap; - if (!logfile) - return -1; - this = THIS; xlator_loglevel = this->loglevel; @@ -308,13 +424,17 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function, strcpy (msg, str1); strcpy (msg + len, str2); - fprintf (logfile, "%s\n", msg); - fflush (logfile); + if (logfile) { + fprintf (logfile, "%s\n", msg); + fflush (logfile); + } else { + fprintf (stderr, "%s\n", msg); + } #ifdef GF_LINUX_HOST_OS /* We want only serious log in 'syslog', not our debug and trace logs */ - if (gf_log_syslog && level && (level <= GF_LOG_ERROR)) + if (gf_log_syslog && level && (level <= GF_LOG_CRITICAL)) syslog ((level-1), "%s\n", msg); #endif } @@ -355,9 +475,6 @@ _gf_log (const char *domain, const char *file, const char *function, int line, xlator_t *this = NULL; gf_loglevel_t xlator_loglevel = 0; - if (!logfile) - return -1; - this = THIS; xlator_loglevel = this->loglevel; @@ -398,7 +515,9 @@ _gf_log (const char *domain, const char *file, const char *function, int line, goto log; } - fclose (logfile); + if (logfile) + fclose (logfile); + gf_log_logfile = logfile = new_logfile; } @@ -444,13 +563,17 @@ log: strcpy (msg, str1); strcpy (msg + len, str2); - fprintf (logfile, "%s\n", msg); - fflush (logfile); + if (logfile) { + fprintf (logfile, "%s\n", msg); + fflush (logfile); + } else { + fprintf (stderr, "%s\n", msg); + } #ifdef GF_LINUX_HOST_OS /* We want only serious log in 'syslog', not our debug and trace logs */ - if (gf_log_syslog && level && (level <= GF_LOG_ERROR)) + if (gf_log_syslog && level && (level <= GF_LOG_CRITICAL)) syslog ((level-1), "%s\n", msg); #endif } diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h index aa6e00edb70..0664b2efae0 100644 --- a/libglusterfs/src/logging.h +++ b/libglusterfs/src/logging.h @@ -69,8 +69,6 @@ typedef enum { GF_LOG_TRACE, /* full trace of operation */ } gf_loglevel_t; -#define GF_LOG_MAX GF_LOG_DEBUG - extern gf_loglevel_t gf_log_loglevel; extern char gf_log_xl_log_set; @@ -94,27 +92,38 @@ extern char gf_log_xl_log_set; levl, ##fmt); \ } while (0) + +/* No malloc or calloc should be called in this function */ +#define gf_log_nomem(dom, levl, size) do { \ + if ((levl > gf_log_loglevel) && !gf_log_xl_log_set) \ + break; \ + _gf_log_nomem (dom, __FILE__, __FUNCTION__, __LINE__, \ + levl, size); \ + } while (0) + + /* Log once in GF_UNIVERSAL_ANSWER times */ #define GF_LOG_OCCASIONALLY(var, args...) if (!(var++%GF_UNIVERSAL_ANSWER)) { \ gf_log (args); \ } -void -gf_log_logrotate (int signum); +void gf_log_logrotate (int signum); +void gf_log_globals_init (void); int gf_log_init (const char *filename); void gf_log_cleanup (void); -int -_gf_log (const char *domain, const char *file, const char *function, - int32_t line, gf_loglevel_t level, const char *fmt, ...); -int -_gf_log_callingfn (const char *domain, const char *file, const char *function, - int32_t line, gf_loglevel_t level, const char *fmt, ...); +int _gf_log (const char *domain, const char *file, const char *function, + int32_t line, gf_loglevel_t level, const char *fmt, ...); +int _gf_log_callingfn (const char *domain, const char *file, const char *function, + int32_t line, gf_loglevel_t level, const char *fmt, ...); + +int _gf_log_nomem (const char *domain, const char *file, + const char *function, int line, gf_loglevel_t level, + size_t size); -int -gf_log_from_client (const char *msg, char *identifier); +int gf_log_from_client (const char *msg, char *identifier); void gf_log_lock (void); void gf_log_unlock (void); @@ -135,9 +144,7 @@ void gf_log_set_xl_loglevel (void *xl, gf_loglevel_t level); #define GF_ERROR(xl, format, args...) \ gf_log ((xl)->name, GF_LOG_ERROR, format, ##args) -int -gf_cmd_log (const char *domain, const char *fmt, ...); +int gf_cmd_log (const char *domain, const char *fmt, ...); -int -gf_cmd_log_init (const char *filename); +int gf_cmd_log_init (const char *filename); #endif /* __LOGGING_H__ */ diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c index 9acebad4153..0d555020bbe 100644 --- a/libglusterfs/src/mem-pool.c +++ b/libglusterfs/src/mem-pool.c @@ -141,9 +141,10 @@ __gf_calloc (size_t nmemb, size_t size, uint32_t type) ptr = calloc (1, tot_size); - if (!ptr) + if (!ptr) { + gf_log_nomem ("", GF_LOG_ALERT, tot_size); return NULL; - + } gf_mem_set_acct_info (xl, &ptr, req_size, type); return (void *)ptr; @@ -164,9 +165,10 @@ __gf_malloc (size_t size, uint32_t type) tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE; ptr = malloc (tot_size); - if (!ptr) + if (!ptr) { + gf_log_nomem ("", GF_LOG_ALERT, tot_size); return NULL; - + } gf_mem_set_acct_info (xl, &ptr, size, type); return (void *)ptr; @@ -181,7 +183,7 @@ __gf_realloc (void *ptr, size_t size) uint32_t type = 0; if (!gf_mem_acct_enable) - return realloc (ptr, size); + return REALLOC (ptr, size); tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE; @@ -196,8 +198,10 @@ __gf_realloc (void *ptr, size_t size) type = *(uint32_t *)orig_ptr; ptr = realloc (orig_ptr, tot_size); - if (!ptr) + if (!ptr) { + gf_log_nomem ("", GF_LOG_ALERT, tot_size); return NULL; + } gf_mem_set_acct_info (xl, (char **)&ptr, size, type); @@ -221,12 +225,7 @@ gf_vasprintf (char **string_ptr, const char *format, va_list arg) size++; str = GF_MALLOC (size, gf_common_mt_asprintf); if (str == NULL) { - /* - * Strictly speaking, GNU asprintf doesn't do this, - * but the caller isn't checking the return value. - */ - gf_log ("libglusterfs", GF_LOG_CRITICAL, - "failed to allocate memory"); + /* log is done in GF_MALLOC itself */ return -1; } rv = vsnprintf (str, size, format, arg_save); diff --git a/libglusterfs/src/mem-pool.h b/libglusterfs/src/mem-pool.h index 0cda62fb85b..85ceeb87e06 100644 --- a/libglusterfs/src/mem-pool.h +++ b/libglusterfs/src/mem-pool.h @@ -22,6 +22,7 @@ #include "list.h" #include "locking.h" +#include "logging.h" #include "mem-types.h" #include <stdlib.h> #include <inttypes.h> @@ -29,15 +30,6 @@ #include <stdarg.h> -#define MALLOC(size) malloc(size) -#define CALLOC(cnt,size) calloc(cnt,size) - -#define FREE(ptr) \ - if (ptr != NULL) { \ - free ((void *)ptr); \ - ptr = (void *)0xeeeeeeee; \ - } - struct mem_acct { uint32_t num_types; struct mem_acct_rec *rec; @@ -67,16 +59,62 @@ gf_vasprintf (char **string_ptr, const char *format, va_list arg); int gf_asprintf (char **string_ptr, const char *format, ...); +void +__gf_free (void *ptr); + + +static inline +void* __gf_default_malloc (size_t size) +{ + void *ptr = NULL; + + ptr = malloc (size); + if (!ptr) + gf_log_nomem ("", GF_LOG_ALERT, size); + + return ptr; +} + +static inline +void* __gf_default_calloc (int cnt, size_t size) +{ + void *ptr = NULL; + + ptr = calloc (cnt, size); + if (!ptr) + gf_log_nomem ("", GF_LOG_ALERT, (cnt * size)); + + return ptr; +} + +static inline +void* __gf_default_realloc (void *oldptr, size_t size) +{ + void *ptr = NULL; + + ptr = realloc (oldptr, size); + if (!ptr) + gf_log_nomem ("", GF_LOG_ALERT, size); + + return ptr; +} + +#define MALLOC(size) __gf_default_malloc(size) +#define CALLOC(cnt,size) __gf_default_calloc(cnt,size) +#define REALLOC(ptr,size) __gf_default_realloc(ptr,size) + +#define FREE(ptr) \ + if (ptr != NULL) { \ + free ((void *)ptr); \ + ptr = (void *)0xeeeeeeee; \ + } + #define GF_CALLOC(nmemb, size, type) __gf_calloc (nmemb, size, type) #define GF_MALLOC(size, type) __gf_malloc (size, type) #define GF_REALLOC(ptr, size) __gf_realloc (ptr, size) -void -__gf_free (void *ptr); - - #define GF_FREE(free_ptr) __gf_free (free_ptr); static inline |