|
Packit Service |
75d76b |
/*
|
|
Packit Service |
75d76b |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
75d76b |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
75d76b |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
75d76b |
* of the License, or (at your option) any later version.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
75d76b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
75d76b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
75d76b |
* GNU General Public License for more details.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
75d76b |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
75d76b |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
75d76b |
* 02110-1301, USA.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/trace.h#1 $
|
|
Packit Service |
75d76b |
*/
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#ifndef TRACE_H
|
|
Packit Service |
75d76b |
#define TRACE_H
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#ifndef __KERNEL__
|
|
Packit Service |
75d76b |
#include "cpu.h"
|
|
Packit Service |
75d76b |
#endif
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "threads.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*
|
|
Packit Service |
75d76b |
* We need these records to be glued together with no intervening
|
|
Packit Service |
75d76b |
* bytes. That makes it rather sensitive to how the compiler,
|
|
Packit Service |
75d76b |
* assembler, and linker may add padding. Force extra alignment to
|
|
Packit Service |
75d76b |
* make it more reliable.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* Trace point descriptor language:
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* The descriptor string provided at a trace point can have one or
|
|
Packit Service |
75d76b |
* more components, separated by ";". The first (or only) component is
|
|
Packit Service |
75d76b |
* a string to be formatted and shown in the flowchart graph. The
|
|
Packit Service |
75d76b |
* remaining components must be of the form "var=string", and assign
|
|
Packit Service |
75d76b |
* string values to "variables" that last through the processing of
|
|
Packit Service |
75d76b |
* the remainder of the current trace being read.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* The string displayed has variable substitutions done for any
|
|
Packit Service |
75d76b |
* occurrences of "$var" in the string.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* So, the descriptor sequence:
|
|
Packit Service |
75d76b |
* kvdoWriteVIO;io=writeData;j=normal
|
|
Packit Service |
75d76b |
* submitBio($io)
|
|
Packit Service |
75d76b |
* writeJournalBlock($j)
|
|
Packit Service |
75d76b |
* would cause the graph generator to show the strings:
|
|
Packit Service |
75d76b |
* kvdoWriteVIO
|
|
Packit Service |
75d76b |
* submitBio(writeData)
|
|
Packit Service |
75d76b |
* writeJournalBlock(normal)
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* Substitutions are done in the variable assignment strings when
|
|
Packit Service |
75d76b |
* they're processed, so "foo=x($bar)" sets "foo" using the current
|
|
Packit Service |
75d76b |
* value of "bar"; it doesn't cause "bar" to be looked up when "$foo"
|
|
Packit Service |
75d76b |
* is seen later.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* The variable named "F" is automatically updated with the name of
|
|
Packit Service |
75d76b |
* the function associated with the descriptor, so you don't have to
|
|
Packit Service |
75d76b |
* explicitly repeat the name of the function if you just want to
|
|
Packit Service |
75d76b |
* augment it with more information. This may be desirable if a trace
|
|
Packit Service |
75d76b |
* point is expected to be reached more than once at different stages
|
|
Packit Service |
75d76b |
* of processing, or in a static function with a generic-sounding name
|
|
Packit Service |
75d76b |
* that needs disambiguation for graphing.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* If no descriptor string is provided, the
|
|
Packit Service |
75d76b |
* function:lineNumber:threadName string reported via systemtap will
|
|
Packit Service |
75d76b |
* be used in the graph.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* Current variable names used:
|
|
Packit Service |
75d76b |
* cb=(various) random info to log when enqueueing VIO callback
|
|
Packit Service |
75d76b |
* dup=post,update deduplication operation
|
|
Packit Service |
75d76b |
* io=(various) kind of I/O and data it's being done on
|
|
Packit Service |
75d76b |
* j=normal,dedupe kind of journal update being done
|
|
Packit Service |
75d76b |
* js=mapWrite,writeZero,unmap which step of journaling we're doing
|
|
Packit Service |
75d76b |
*/
|
|
Packit Service |
75d76b |
typedef const struct __attribute__((aligned(16))) traceLocationRecord {
|
|
Packit Service |
75d76b |
const char *function;
|
|
Packit Service |
75d76b |
int line;
|
|
Packit Service |
75d76b |
const char *description;
|
|
Packit Service |
75d76b |
} TraceLocationRecord;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*
|
|
Packit Service |
75d76b |
* With well under 100 locations defined at the moment, even with no
|
|
Packit Service |
75d76b |
* idea where &baseTraceLocation will fall relative to the others, we
|
|
Packit Service |
75d76b |
* only need to support a range of -100..+100.
|
|
Packit Service |
75d76b |
*/
|
|
Packit Service |
75d76b |
typedef int32_t TraceLocationNumber;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/* The type to pass around */
|
|
Packit Service |
75d76b |
typedef TraceLocationRecord *TraceLocation;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*
|
|
Packit Service |
75d76b |
* N.B.: This code uses GCC extensions to create static, initialized
|
|
Packit Service |
75d76b |
* objects inline, describing the current function and line number.
|
|
Packit Service |
75d76b |
* The objects are collected into a table we can index with small
|
|
Packit Service |
75d76b |
* signed integers relative to &baseTraceLocation.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* We need baseTraceLocation because there's no standard way to get
|
|
Packit Service |
75d76b |
* the address of the start of this array we're defining. And because
|
|
Packit Service |
75d76b |
* we're not playing any (additional) special linker tricks to ensure
|
|
Packit Service |
75d76b |
* ordering of the object files, the offsets may be signed, and we
|
|
Packit Service |
75d76b |
* don't know the range beyond the fact that we don't have hundreds of
|
|
Packit Service |
75d76b |
* these records lying around.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* By specifying a name that starts with neither .data nor .rodata, we
|
|
Packit Service |
75d76b |
* leave it to the toolchain to pick a location for us, based on
|
|
Packit Service |
75d76b |
* things like whether the section needs write access, which it does
|
|
Packit Service |
75d76b |
* for a PIC library but not for a kernel module.
|
|
Packit Service |
75d76b |
*/
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#define TRACE_LOCATION_SECTION \
|
|
Packit Service |
75d76b |
__attribute__((section(".kvdo_trace_locations")))
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
extern TRACE_LOCATION_SECTION TraceLocationRecord baseTraceLocation[];
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#define TRACE_JOIN2(a,b) a##b
|
|
Packit Service |
75d76b |
#define TRACE_JOIN(a,b) TRACE_JOIN2(a,b)
|
|
Packit Service |
75d76b |
#define THIS_LOCATION(DESCRIPTION) \
|
|
Packit Service |
75d76b |
__extension__ \
|
|
Packit Service |
75d76b |
({ \
|
|
Packit Service |
75d76b |
static TRACE_LOCATION_SECTION \
|
|
Packit Service |
75d76b |
TraceLocationRecord TRACE_JOIN(loc,__LINE__) = { \
|
|
Packit Service |
75d76b |
.function = __func__, \
|
|
Packit Service |
75d76b |
.line = __LINE__, \
|
|
Packit Service |
75d76b |
.description = DESCRIPTION, \
|
|
Packit Service |
75d76b |
}; \
|
|
Packit Service |
75d76b |
&TRACE_JOIN(loc,__LINE__); \
|
|
Packit Service |
75d76b |
})
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
typedef struct traceRecord {
|
|
Packit Service |
75d76b |
uint64_t when; // counted in usec
|
|
Packit Service |
75d76b |
pid_t tid;
|
|
Packit Service |
75d76b |
TraceLocationNumber location;
|
|
Packit Service |
75d76b |
} TraceRecord;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
enum { NUM_TRACE_RECORDS = 71 };
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
typedef struct trace {
|
|
Packit Service |
75d76b |
unsigned int used;
|
|
Packit Service |
75d76b |
TraceRecord records[NUM_TRACE_RECORDS];
|
|
Packit Service |
75d76b |
} Trace;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Store a new record in the trace data.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param trace The trace data to be updated
|
|
Packit Service |
75d76b |
* @param location The source-location descriptor to be recorded
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
void addTraceRecord(Trace *trace, TraceLocation location);
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Format trace data into a string for logging.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param [in] trace The trace data to be logged
|
|
Packit Service |
75d76b |
* @param [in] buffer The buffer in which to store the string
|
|
Packit Service |
75d76b |
* @param [in] bufferLength Length of the buffer
|
|
Packit Service |
75d76b |
* @param [out] msgLen Length of the formatted string
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
void formatTrace(Trace *trace,
|
|
Packit Service |
75d76b |
char *buffer,
|
|
Packit Service |
75d76b |
size_t bufferLength,
|
|
Packit Service |
75d76b |
size_t *msgLen);
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#endif /* TRACE_H */
|