Motr  M0
traced.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 
24 #include <stdio.h> /* printf */
25 #include <err.h> /* err */
26 #include <errno.h> /* errno */
27 #include <string.h> /* strcpy, basename */
28 #include <sysexits.h> /* EX_* exit codes (EX_OSERR, EX_SOFTWARE) */
29 #include <sys/mman.h> /* mmap */
30 #include <sys/stat.h> /* open */
31 #include <signal.h> /* sigaction */
32 #include <fcntl.h> /* open */
33 #include <unistd.h> /* close, daemon, STDOUT_FILENO */
34 #include <syslog.h> /* openlog, vsyslog */
35 #include <stdarg.h> /* va_arg */
36 #include <linux/limits.h> /* PATH_MAX */
37 #include <sys/sendfile.h> /* sendfile */
38 #include <sys/utsname.h> /* uname */
39 
40 #include "motr/init.h" /* m0_init */
41 #include "lib/uuid.h" /* m0_node_uuid_string_set */
42 #include "lib/misc.h"
43 #include "lib/string.h" /* m0_strdup */
44 #include "lib/getopts.h" /* M0_GETOPTS */
45 #include "lib/thread.h" /* LAMBDA */
46 #include "lib/user_space/types.h" /* bool */
47 #include "lib/trace.h" /* M0_THREAD_INIT */
48 #include "lib/mutex.h" /* m0_mutex_lock */
49 #include "lib/cond.h" /* m0_cond_wait */
50 #include "lib/trace_internal.h"
51 #include "module/instance.h"
52 
53 
60 #define DEFAULT_IN_FILE_NAME "/sys/kernel/debug/motr/trace/buffer"
61 #define DEFAULT_OUT_FILE_NAME "/var/log/motr/m0trace.bin"
62 #define MOTR_KO_CORE_IN_FILE_NAME "/sys/kernel/debug/motr/core"
63 #define MOTR_KO_CORE_OUT_FILE_NAME "/var/log/motr/m0tr_ko.img"
64 
65 static const char *progname;
69 
70 static bool daemon_mode = false;
71 static bool pipe_mode = false;
72 static bool fsync_enabled = false;
73 static bool use_syslog = false;
74 static bool save_kore = true;
75 static int log_level = LOG_INFO;
76 static bool rotation_enabled = true;
77 static uint32_t log_rotation_dealy = 5; /* in seconds */
78 static uint32_t max_log_size = 1024; /* in MB */
79 static uint32_t keep_logs = 6; /* number of logs to keep */
80 
81 static struct m0_mutex write_data_mutex;
82 static struct m0_mutex rotator_mutex;
83 static struct m0_cond rotator_cond;
84 
85 struct rotator_ctx {
86  int log_fd;
88 };
89 
90 enum lr_action {
93 };
94 
96 static volatile bool stop_processing = false;
97 
98 enum {
99  MAX_LOG_NAMES = 1024,
100 };
101 /* array with the names of log files being rotated */
102 static char log_names[MAX_LOG_NAMES][PATH_MAX];
103 
104 
105 static void plog(int level, const char *format, ...)
106  __attribute__(( format(printf, 2, 3) ));
107 
108 #define log_err(fmt, ...) plog(LOG_ERR, fmt, ## __VA_ARGS__)
109 #define log_warn(fmt, ...) plog(LOG_WARNING, fmt, ## __VA_ARGS__)
110 #define log_info(fmt, ...) plog(LOG_INFO, fmt, ## __VA_ARGS__)
111 #define log_debug(fmt, ...) plog(LOG_DEBUG, fmt, ## __VA_ARGS__)
112 
113 
114 static void plog(int level, const char *format, ...)
115 {
116  static char buf[8 * 1024]; /* 8 KB */
117  va_list args;
118 
119  if (level > log_level)
120  return;
121 
122  va_start(args, format);
123 
124  if (use_syslog) {
125  vsyslog(level, format, args);
126  } else {
127  snprintf(buf, sizeof buf, "%s: %s", progname, format);
128  buf[sizeof buf - 1] = '\0';
129  vfprintf(stderr, buf, args);
130  }
131 
132  va_end(args);
133 }
134 
135 void sig_term_quit_int_handler(int signum, siginfo_t *siginfo, void *uctx)
136 {
137  log_debug("%s: signum %d\n", __func__, signum);
138  stop_processing = true;
139 }
140 
141 static const struct m0_trace_buf_header *read_trace_buf_header(int ifd)
142 {
143  const struct m0_trace_buf_header *tb_header;
144 
145  static char buf[M0_TRACE_BUF_HEADER_SIZE];
146  ssize_t n;
147 
148  n = read(ifd, buf, sizeof buf);
149  if (n != sizeof buf) {
150  log_err("failed to read trace header from '%s' file (got %zd"
151  " bytes instead of %zu bytes)\n",
152  input_file_name, n, sizeof buf);
153  return NULL;
154  }
155 
156  tb_header = (const struct m0_trace_buf_header *)buf;
157 
158  if (tb_header->tbh_magic != M0_TRACE_BUF_HEADER_MAGIC) {
159  log_err("invalid trace header MAGIC value\n");
160  return NULL;
161  }
162 
163  log_info("Trace buffer header: [%s]\n", input_file_name);
164  log_info(" header size: %u\n", tb_header->tbh_header_size);
165  log_info(" buffer size: %" PRIu64 "\n", tb_header->tbh_buf_size);
166  log_info(" buffer type: %s\n",
167  tb_header->tbh_buf_type == M0_TRACE_BUF_KERNEL ? "kernel" :
168  tb_header->tbh_buf_type == M0_TRACE_BUF_USER ? "user" :
169  "unknown"
170  );
171  log_info(" motr_version: %s\n", tb_header->tbh_motr_version);
172  log_info(" motr_git_describe: %s\n", tb_header->tbh_motr_git_describe);
173 
174  return tb_header;
175 }
176 
178  int *ofd, const char *ofname)
179 {
180  int fd;
181  ssize_t n;
182  int rc = 0;
183 
185  fd = *ofd;
186  n = write(fd, header, header->tbh_header_size);
187  if (n != header->tbh_header_size) {
188  log_err("failed to write trace header to output file '%s': %s\n",
189  ofname, strerror(errno));
190  rc = EX_IOERR;
191  goto out;
192  }
193 
194  if (fsync_enabled) {
195  rc = fsync(fd);
196  if (rc != 0)
197  log_err("fsync(2) failed on output file '%s': %s",
198  ofname, strerror(errno));
199  }
200 out:
202  return rc;
203 }
204 
205 
206 static int write_trace_data(int *fd_ptr, const void *buf, size_t size)
207 {
208  ssize_t n;
209  int fd;
210  int rc = 0;
211 
213  fd = *fd_ptr;
214  n = write(fd, buf, size);
215  if (n != size) {
216  log_err("failed to write trace data to output file"
217  " '%s': %s\n", output_file_name,
218  strerror(errno));
219  rc = EX_IOERR;
220  goto out;
221  }
222 
223  if (fsync_enabled) {
224  rc = fsync(fd);
225  if (rc != 0)
226  log_err("fsync(2) failed on output file '%s': %s",
227  output_file_name, strerror(errno));
228  }
229 out:
231  return rc;
232 }
233 
234 static const char *get_cur_pos(const struct m0_trace_buf_header *logheader,
235  const char *logbuf)
236 {
237  const char *curpos = logbuf + m0_atomic64_get(&logheader->tbh_cur_pos) %
238  logheader->tbh_buf_size;
239 
240  if (curpos >= logbuf + logheader->tbh_buf_size) {
241  log_err("invalid trace buffer pointer (out of range)\n");
242  return NULL;
243  }
244 
245  return curpos;
246 }
247 
248 static bool is_log_rotation_needed(int *fd_ptr)
249 {
250  static m0_time_t time_of_last_check;
251  m0_time_t time_diff;
252  struct stat log_stat;
253  int rc;
254 
255  if (!rotation_enabled || max_log_size == 0)
256  return false;
257 
258  if (time_of_last_check == 0)
259  time_of_last_check = m0_time_now();
260 
261  time_diff = m0_time_sub(m0_time_now(), time_of_last_check);
262 
263  if (m0_time_seconds(time_diff) > log_rotation_dealy) {
264  time_of_last_check = m0_time_now();
265 
267  rc = fstat(*fd_ptr, &log_stat);
269  if (rc != 0) {
270  log_err("failed to get stat info for '%s' file: %s\n",
271  output_file_name, strerror(errno));
272  return false;
273  }
274 
275  if (log_stat.st_size / 1024 / 1024 >= max_log_size) {
276  log_debug("log size is %.2fMB, log rotation is needed\n",
277  (float)log_stat.st_size / 1024 / 1024);
278  return true;
279  }
280  }
281 
282  return false;
283 }
284 
286 {
288  rotator_action = a;
291 }
292 
294 {
295  int ofd;
296  int rc;
297 
298  log_debug("rotating original log..\n");
299 
300  rc = rename(output_file_name, log_names[0]);
301  if (rc != 0) {
302  log_err("failed to rename log file '%s' => '%s': %s\n",
303  output_file_name, log_names[0], strerror(errno));
304  return rc;
305  }
306 
307  /* open new output file */
308  ofd = open(output_file_name, O_RDWR|O_CREAT|O_TRUNC,
309  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
310  if (ofd == -1) {
311  log_err("failed to open output file '%s': %s\n",
312  output_file_name, strerror(errno));
313  return EX_CANTCREAT;
314  }
315 
316  log_debug("new output log fd %d\n", ofd);
317 
318  rc = write_trace_header(rctx->log_header, &ofd, output_file_name);
319  if (rc != 0)
320  return rc;
321 
323  if (rctx->log_fd > 0)
324  close(rctx->log_fd);
325  rctx->log_fd = ofd;
327 
328  log_debug("original log has been rotated\n");
329  return rc;
330 }
331 
332 static void log_rotator_thread(struct rotator_ctx *rctx)
333 {
334  const char *last_log;
335  int i;
336  int rc;
337 
338  log_debug("log rotation thread started\n");
339 
340  while (true) {
341  /* waiting for some work */
343 
344  if (rotator_action == LR_STOP) {
346  break;
347  }
348 
350 
351  if (rotator_action == LR_STOP) {
353  break;
354  }
355 
357 
358  log_debug("perform logs rotation\n");
359 
360  /* drop oldest log file if it exists */
361  last_log = log_names[keep_logs - 1];
362  if (access(last_log, F_OK) == 0) {
363  rc = unlink(last_log);
364  if (rc != 0) {
365  log_err("failed to remove oldest log file '%s':"
366  " %s\n", last_log, strerror(errno));
367  continue;
368  }
369  }
370 
371  /* rotate log files with digit suffix */
372  for (i = keep_logs - 2; i >= 0; --i)
373  if (access(log_names[i], F_OK) == 0) {
374  rc = rename(log_names[i], log_names[i + 1]);
375  if (rc != 0) {
376  log_err("failed to rename log file"
377  " '%s' => '%s': %s\n",
378  log_names[i], log_names[i + 1],
379  strerror(errno));
380  break;
381  }
382  }
383 
385  }
386 
387  log_debug("log rotation thread stopped\n");
388 }
389 
390 static int process_trace_buffer(int *ofd_ptr,
391  const struct m0_trace_buf_header *logheader,
392  const char *logbuf)
393 {
394  int rc;
395  const char *curpos;
396  const char *oldpos;
397  const char *logbuf_end = logbuf + logheader->tbh_buf_size;
398  const m0_time_t idle_timeo = 100 * M0_TIME_ONE_MSEC;
399  m0_time_t timeo = idle_timeo;
400 
401  log_info("Fsync enabled: %s\n", fsync_enabled ? "yes" : "no");
402 
403  rc = write_trace_header(logheader, ofd_ptr, output_file_name);
404  if (rc != 0)
405  return rc;
406 
407  curpos = get_cur_pos(logheader, logbuf);
408  if (curpos == NULL)
409  return -EINVAL;
410 
411  if (!pipe_mode) {
412  /*
413  * write first chunk of trace data, we always start from the
414  * beginning of buffer till current position
415  */
416  rc = write_trace_data(ofd_ptr, logbuf, curpos - logbuf);
417  if (rc != 0)
418  return rc;
419  }
420 
421  oldpos = curpos;
422 
423  /* write rest of trace data as it appears in the buffer */
424  while (!stop_processing) {
425  curpos = get_cur_pos(logheader, logbuf);
426  if (curpos == NULL)
427  return -EINVAL;
428 
429  if (curpos == oldpos) {
430  timeo += M0_TIME_ONE_MSEC;
431  if (timeo > idle_timeo)
432  timeo = idle_timeo;
433 
434  rc = m0_nanosleep(timeo, NULL);
435  if (rc != 0) {
436  log_warn("trace data processing interrupted by"
437  " a signal, exiting\n");
438  return 0;
439  }
440 
441  continue;
442  }
443 
444  if (curpos > oldpos) {
445  rc = write_trace_data(ofd_ptr, oldpos, curpos - oldpos);
446  if (rc != 0)
447  return rc;
448  } else {
449  rc = write_trace_data(ofd_ptr, curpos, logbuf_end - curpos);
450  if (rc != 0)
451  return rc;
452  rc = write_trace_data(ofd_ptr, logbuf, curpos - logbuf);
453  if (rc != 0)
454  return rc;
455  }
456 
457  oldpos = curpos;
458  timeo /= 2;
459 
460  if (is_log_rotation_needed(ofd_ptr))
462  }
463 
464  return 0;
465 }
466 
467 static int init_log_names(void)
468 {
469  int i;
470 
471  if (keep_logs > MAX_LOG_NAMES) {
472  log_err("invalid valude for -k option, it should be <= %u\n",
473  MAX_LOG_NAMES);
474  return EX_USAGE;
475  }
476 
477  for (i = 0; i < keep_logs; ++i)
478  snprintf(log_names[i], sizeof log_names[i], "%s.%u",
479  output_file_name, i + 1);
480 
481  return 0;
482 }
483 
484 int save_kore_file(void)
485 {
486  int ifd;
487  int ofd;
488  int nr = 0;
489  int nw;
490  int rc = 0;
491 
492  static char buf[4 * 1024 * 1024]; /* 4MB */
493 
494  /* open input kore file */
495  ifd = open(MOTR_KO_CORE_IN_FILE_NAME, O_RDONLY);
496  if (ifd == -1) {
497  log_err("failed to open input file '%s': %s\n",
498  MOTR_KO_CORE_IN_FILE_NAME, strerror(errno));
499  return EX_NOINPUT;
500  }
501 
502  /* open output kore file */
503  ofd = open(output_kore_file_name, O_RDWR|O_CREAT|O_TRUNC,
504  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
505  if (ofd == -1) {
506  log_err("failed to open output file '%s': %s\n",
507  output_kore_file_name, strerror(errno));
508  return EX_CANTCREAT;
509  }
510 
511  while ((nr = read(ifd, buf, sizeof buf)) > 0) {
512  nw = write(ofd, buf, nr);
513  if (nw == -1) {
514  log_err("failed to write data to '%s' file: %s\n",
515  output_kore_file_name, strerror(errno));
516  rc = -errno;
517  goto close;
518  }
519  }
520 
521  if (nr == -1) {
522  log_err("failed to read data from '%s' file: %s\n",
523  MOTR_KO_CORE_IN_FILE_NAME, strerror(errno));
524  rc = -errno;
525  goto close;
526  }
527 close:
528  close(ifd);
529  close(ofd);
530 
531  if (rc == 0)
532  log_debug("m0tr.ko core image saved into '%s'\n",
534  return rc;
535 }
536 
537 int main(int argc, char *argv[])
538 {
539  int rc;
540  int ifd;
541  int ofd;
542 
543  static struct m0 instance = { 0 };
544  const struct m0_trace_buf_header *logheader;
545  void *logbuf;
546  struct m0_thread rotator_tid = { 0 };
547  struct rotator_ctx rotator_data = { 0 };
548  int32_t monitor_cycles = 0;
549 
550  struct sigaction old_sa;
551  struct sigaction sa = {
552  .sa_sigaction = sig_term_quit_int_handler,
553  .sa_flags = SA_SIGINFO,
554  };
555 
556  progname = basename(argv[0]);
557 
558  /* prevent creation of trace file for ourselves */
560 
561  /* we don't need a real node uuid, so we force a default one to be useed
562  * instead */
564 
565  rc = m0_init(&instance);
566  if (rc != 0) {
567  log_err("failed to initialize libmotr\n");
568  return EX_SOFTWARE;
569  }
570 
571  /* process CLI options */
572  rc = M0_GETOPTS(progname, argc, argv,
573  M0_HELPARG('h'),
574  M0_STRINGARG('i',
575  "input file name, if none is provided, then "
576  DEFAULT_IN_FILE_NAME " is used by default",
577  LAMBDA(void, (const char *str) {
578  input_file_name = m0_strdup(str);
579  })
580  ),
581  M0_STRINGARG('o',
582  "output file name, if none is provided, then "
583  DEFAULT_OUT_FILE_NAME " is used by default",
584  LAMBDA(void, (const char *str) {
586  })
587  ),
588  M0_STRINGARG('O',
589  "output file name for m0tr.ko core image, if none is provided"
590  ", then " MOTR_KO_CORE_OUT_FILE_NAME " is used by default;"
591  " it has effect only if -K option is also specified",
592  LAMBDA(void, (const char *str) {
594  })
595  ),
596  M0_FLAGARG('d',
597  "daemon mode - run in the background, implies -L (log errors"
598  " into syslog)",
599  &daemon_mode
600  ),
601  M0_VOIDARG('K',
602  "save m0tr.ko core image into a file, specified by -O option"
603  " (this option has no effect as it's 'on' by default, it has"
604  " been kept for backward compatibility, it's superseded by"
605  " '-S' option)",
606  LAMBDA(void, (void) { })
607  ),
608  M0_VOIDARG('S',
609  "discards action of '-K' option, i.e. don't save m0tr.ko"
610  " core image into a file",
611  LAMBDA(void, (void) {
612  save_kore = false;
613  })
614  ),
615  M0_NUMBERARG('l', "log level number (from syslog.h)",
616  LAMBDA(void, (int64_t lvl) {
617  log_level = lvl;
618  })
619  ),
620  M0_FLAGARG('L',
621  "log information into syslog instead of STDERR (by default"
622  " is off)",
623  &use_syslog
624  ),
625  M0_NUMBERARG('s',
626  "output trace file size in MB, when it's reached, log rotation"
627  " is performed; if set to 0 then rotation is disabled, default"
628  " is 1024MB",
629  LAMBDA(void, (int64_t size) {
630  max_log_size = size;
631  })
632  ),
633  M0_NUMBERARG('k',
634  "number of logs to keep in log rotation, default is 6",
635  LAMBDA(void, (int64_t k) {
636  keep_logs = k;
637  })
638  ),
639  M0_NUMBERARG('m',
640  "monitor trace buffer file creation each second during"
641  " specified period of time (in seconds)",
642  LAMBDA(void, (int64_t k) {
643  monitor_cycles = k;
644  })
645  ),
646  M0_VOIDARG('p',
647  "pipe mode - run in foreground, output to STDOUT and disable"
648  " log rotation",
649  LAMBDA(void, (void) {
650  pipe_mode = true;
651  fsync_enabled = false;
652  rotation_enabled = false;
653  daemon_mode = false;
654  save_kore = false;
655  output_file_name = "-";
656  })
657  ),
658  M0_FLAGARG('f', "do fsync after writing each chunk of trace data",
660  ),
661  );
662 
663  if (rc != 0)
664  return EX_USAGE;
665 
666  if (daemon_mode) {
667  /* configure syslog(3) */
668  openlog(progname, LOG_NOWAIT | LOG_CONS, LOG_DAEMON);
669  use_syslog = true;
670  /*
671  * become a daemon (fork background process,
672  * close STD{IN,OUT}, etc.)
673  */
674  rc = daemon(0, 0);
675  if (rc != 0)
676  err(EX_OSERR, "failed to switch to daemon mode");
677  }
678 
679  rc = sigaction(SIGTERM, &sa, &old_sa);
680  rc |= sigaction(SIGQUIT, &sa, NULL);
681  rc |= sigaction(SIGINT, &sa, NULL);
682  if (rc != 0) {
683  log_err("failed to set SIGTERM/SIGQUIT/SIGINT handler\n");
684  return EX_OSERR;
685  }
686 
687  if (rotation_enabled) {
688  rc = init_log_names();
689  if (rc != 0)
690  return rc;
691  }
692 
693  if (save_kore) {
694  rc = save_kore_file();
695  if (rc != 0)
696  return rc;
697  }
698 
699  while (monitor_cycles-- > 0) {
700  rc = access(input_file_name, F_OK);
701  if (rc == 0)
702  break;
703  sleep(1);
704  }
705 
706  /* open input file */
707  ifd = open(input_file_name, O_RDONLY);
708  if (ifd == -1) {
709  log_err("failed to open input file '%s': %s\n",
710  input_file_name, strerror(errno));
711  return EX_NOINPUT;
712  }
713 
714  /* open output file */
715  if (strcmp(output_file_name, "-") == 0) {
716  ofd = STDOUT_FILENO;
717  output_file_name = "*STDOUT*";
718  } else {
719  ofd = open(output_file_name, O_RDWR|O_CREAT|O_TRUNC,
720  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
721  if (ofd == -1) {
722  log_err("failed to open output file '%s': %s\n",
723  output_file_name, strerror(errno));
724  return EX_CANTCREAT;
725  }
726  }
727  log_debug("output log fd %d\n", ofd);
728 
729  logheader = read_trace_buf_header(ifd);
730  if (logheader == NULL)
731  return EX_DATAERR;
732 
733  logheader = mmap(NULL, logheader->tbh_header_size, PROT_READ,
734  MAP_SHARED, ifd, 0);
735  if (logheader == MAP_FAILED) {
736  log_err("failed to mmap trace buffer header from '%s': %s\n",
737  input_file_name, strerror(errno));
738  return EX_OSERR;
739  }
740 
741  logbuf = mmap(NULL, logheader->tbh_buf_size, PROT_READ, MAP_SHARED,
742  ifd, logheader->tbh_header_size);
743  if (logbuf == MAP_FAILED) {
744  log_err("failed to mmap trace buffer from '%s': %s\n",
745  input_file_name, strerror(errno));
746  return EX_OSERR;
747  }
748 
752 
753  rotator_data.log_fd = ofd;
754  rotator_data.log_header = logheader;
755 
756  if (rotation_enabled) {
757  /* start log rotation thread */
758  rc = M0_THREAD_INIT(&rotator_tid, struct rotator_ctx *, NULL,
759  &log_rotator_thread, &rotator_data,
760  "m0traced_logrt");
761  if (rc != 0) {
762  log_err("failed to start log rotation thread\n");
763  return EX_SOFTWARE;
764  }
765  }
766 
767  /* do main work */
768  rc = process_trace_buffer(&rotator_data.log_fd, logheader, logbuf);
769 
770  /* stop log rotation thread */
771  if (rotation_enabled) {
773  m0_thread_join(&rotator_tid);
774  m0_thread_fini(&rotator_tid);
775  }
776 
780 
781  m0_fini();
782  munmap(logbuf, logheader->tbh_buf_size);
783  munmap((void*)logheader, logheader->tbh_header_size);
784  close(ofd);
785  close(ifd);
786 
787  return rc;
788 }
789 
790 
794 /*
795  * Local variables:
796  * c-indentation-style: "K&R"
797  * c-basic-offset: 8
798  * tab-width: 8
799  * fill-column: 80
800  * scroll-step: 1
801  * End:
802  */
803 /*
804  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
805  */
static bool rotation_enabled
Definition: traced.c:76
#define M0_GETOPTS(progname, argc, argv,...)
Definition: getopts.h:169
Definition: cond.h:99
static size_t nr
Definition: dump.c:1505
int log_fd
Definition: traced.c:86
static uint32_t max_log_size
Definition: traced.c:78
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
#define m0_strdup(s)
Definition: string.h:43
static bool save_kore
Definition: traced.c:74
#define M0_FLAGARG(ch, desc, ptr)
Definition: getopts.h:232
M0_INTERNAL int struct dentry struct kstat * stat
Definition: dir.c:1433
#define MOTR_KO_CORE_IN_FILE_NAME
Definition: traced.c:62
#define NULL
Definition: misc.h:38
static int process_trace_buffer(int *ofd_ptr, const struct m0_trace_buf_header *logheader, const char *logbuf)
Definition: traced.c:390
void m0_fini(void)
Definition: init.c:318
int m0_thread_join(struct m0_thread *q)
Definition: kthread.c:169
#define MOTR_KO_CORE_OUT_FILE_NAME
Definition: traced.c:63
static bool daemon_mode
Definition: traced.c:70
#define log_debug(fmt,...)
Definition: traced.c:111
uint64_t m0_time_t
Definition: time.h:37
struct m0_atomic64 tbh_cur_pos
Definition: trace.h:385
enum m0_trace_level level
Definition: trace.c:111
static const char * output_file_name
Definition: traced.c:67
uint64_t tbh_buf_size
Definition: trace.h:376
static struct m0_mutex write_data_mutex
Definition: traced.c:81
#define DEFAULT_IN_FILE_NAME
Definition: traced.c:60
static void wake_up_rotator_thread(enum lr_action a)
Definition: traced.c:285
enum m0_md_lustre_logrec_type __attribute__
Definition: balloc.c:2745
#define M0_THREAD_INIT(thread, TYPE, init, func, arg, namefmt,...)
Definition: thread.h:139
char tbh_motr_version[16]
Definition: trace.h:394
int m0_init(struct m0 *instance)
Definition: init.c:310
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
Definition: ub.c:49
void sig_term_quit_int_handler(int signum, siginfo_t *siginfo, void *uctx)
Definition: traced.c:135
M0_INTERNAL void m0_cond_init(struct m0_cond *cond, struct m0_mutex *mutex)
Definition: cond.c:40
#define M0_VOIDARG(ch, desc, func)
Definition: getopts.h:177
Definition: sock.c:887
static uint32_t keep_logs
Definition: traced.c:79
#define M0_NUMBERARG(ch, desc, func)
Definition: getopts.h:187
static bool pipe_mode
Definition: traced.c:71
struct m0_reqh_context rctx
#define M0_STRINGARG(ch, desc, func)
Definition: getopts.h:207
int i
Definition: dir.c:1033
#define PRIu64
Definition: types.h:58
def args
Definition: addb2db.py:716
#define LAMBDA(T,...)
Definition: thread.h:153
static int init_log_names(void)
Definition: traced.c:467
lr_action
Definition: traced.c:90
static enum lr_action rotator_action
Definition: traced.c:95
M0_INTERNAL void m0_cond_fini(struct m0_cond *cond)
Definition: cond.c:46
static const char * output_kore_file_name
Definition: traced.c:68
char tbh_motr_git_describe[64]
Definition: trace.h:396
m0_time_t m0_time_now(void)
Definition: time.c:134
void m0_node_uuid_string_set(const char *uuid)
Definition: uuuid.c:64
static void log_rotator_thread(struct rotator_ctx *rctx)
Definition: traced.c:332
static volatile bool stop_processing
Definition: traced.c:96
void m0_thread_fini(struct m0_thread *q)
Definition: thread.c:92
M0_INTERNAL void m0_cond_signal(struct m0_cond *cond)
Definition: cond.c:94
Definition: instance.h:80
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
static const char * progname
Definition: traced.c:65
static const struct m0_trace_buf_header * read_trace_buf_header(int ifd)
Definition: traced.c:141
uint64_t tbh_magic
Definition: trace.h:363
static struct m0_cond rotator_cond
Definition: traced.c:83
#define DEFAULT_OUT_FILE_NAME
Definition: traced.c:61
uint64_t m0_time_seconds(const m0_time_t time)
Definition: time.c:83
#define log_info(fmt,...)
Definition: traced.c:110
static void plog(int level, const char *format,...) __attribute__((format(printf
Definition: traced.c:114
static int64_t m0_atomic64_get(const struct m0_atomic64 *a)
format
Definition: hist.py:128
M0_INTERNAL void m0_cond_wait(struct m0_cond *cond)
Definition: cond.c:52
uint64_t n
Definition: fops.h:107
static int write_trace_header(const struct m0_trace_buf_header *header, int *ofd, const char *ofname)
Definition: traced.c:177
uint32_t tbh_header_size
Definition: trace.h:372
#define log_warn(fmt,...)
Definition: traced.c:109
const struct m0_trace_buf_header * log_header
Definition: traced.c:87
int save_kore_file(void)
Definition: traced.c:484
m0_time_t m0_time_sub(const m0_time_t t1, const m0_time_t t2)
Definition: time.c:65
static char log_names[MAX_LOG_NAMES][PATH_MAX]
Definition: traced.c:102
static bool is_log_rotation_needed(int *fd_ptr)
Definition: traced.c:248
#define M0_HELPARG(ch)
Definition: getopts.h:242
m0_bcount_t size
Definition: di.c:39
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
static uint32_t log_rotation_dealy
Definition: traced.c:77
static struct m0 instance
Definition: main.c:78
static int rotate_original_log(struct rotator_ctx *rctx)
Definition: traced.c:293
static struct m0_mutex rotator_mutex
Definition: traced.c:82
struct m0t1fs_filedata * fd
Definition: dir.c:1030
static bool use_syslog
Definition: traced.c:73
static bool fsync_enabled
Definition: traced.c:72
Definition: traced.c:92
#define out(...)
Definition: gen.c:41
static const char * get_cur_pos(const struct m0_trace_buf_header *logheader, const char *logbuf)
Definition: traced.c:234
static int log_level
Definition: traced.c:75
Definition: mutex.h:47
#define log_err(fmt,...)
Definition: traced.c:108
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL void m0_trace_set_mmapped_buffer(bool val)
Definition: utrace.c:156
uint16_t tbh_buf_type
Definition: trace.h:378
int main(int argc, char *argv[])
Definition: traced.c:537
static const char * input_file_name
Definition: traced.c:66
static int write_trace_data(int *fd_ptr, const void *buf, size_t size)
Definition: traced.c:206
int m0_nanosleep(const m0_time_t req, m0_time_t *rem)
Definition: ktime.c:73