|
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/kernel/ktrace.c#2 $
|
|
Packit Service |
75d76b |
*/
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "ktrace.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "memoryAlloc.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "dataVIO.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "kvio.h"
|
|
Packit Service |
75d76b |
#include "logger.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
enum {
|
|
Packit Service |
75d76b |
// How much data from a trace can we log in one call without messing
|
|
Packit Service |
75d76b |
// up the log or losing data?
|
|
Packit Service |
75d76b |
TRACE_LOG_MAX = 820,
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
// What fraction (1 out of TRACE_SAMPLE_INTERVAL VIOs) to trace
|
|
Packit Service |
75d76b |
TRACE_SAMPLE_INTERVAL = 3,
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
bool traceRecording = false;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
static struct {
|
|
Packit Service |
75d76b |
char buffer[2000];
|
|
Packit Service |
75d76b |
unsigned int counter;
|
|
Packit Service |
75d76b |
struct mutex lock;
|
|
Packit Service |
75d76b |
} traceLoggingState;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Initialize a SampleCounter structure with the given sampling interval.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param counter The counter to initialize
|
|
Packit Service |
75d76b |
* @param interval The desired sampling interval
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
static void initializeSampleCounter(SampleCounter *counter,
|
|
Packit Service |
75d76b |
unsigned int interval)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
spin_lock_init(&counter->lock);
|
|
Packit Service |
75d76b |
counter->tick = 0;
|
|
Packit Service |
75d76b |
counter->interval = interval;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*************************************************************************/
|
|
Packit Service |
75d76b |
bool sampleThisOne(SampleCounter *counter)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
bool wantTracing = false;
|
|
Packit Service |
75d76b |
spin_lock(&counter->lock);
|
|
Packit Service |
75d76b |
counter->tick++;
|
|
Packit Service |
75d76b |
if (counter->tick >= counter->interval) {
|
|
Packit Service |
75d76b |
counter->tick = 0;
|
|
Packit Service |
75d76b |
wantTracing = true;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
spin_unlock(&counter->lock);
|
|
Packit Service |
75d76b |
return wantTracing;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*************************************************************************/
|
|
Packit Service |
75d76b |
static void freeTraceDataBuffer(void *poolData, void *data)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
Trace *trace = (Trace *) data;
|
|
Packit Service |
75d76b |
FREE(trace);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*************************************************************************/
|
|
Packit Service |
75d76b |
static int allocTraceDataBuffer(void *poolData, void **dataPtr)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
Trace *trace;
|
|
Packit Service |
75d76b |
int result = ALLOCATE(1, Trace, __func__, &trace);
|
|
Packit Service |
75d76b |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
75d76b |
logError("trace data allocation failure %d", result);
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
*dataPtr = trace;
|
|
Packit Service |
75d76b |
return VDO_SUCCESS;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*************************************************************************/
|
|
Packit Service |
75d76b |
int allocTraceFromPool(KernelLayer *layer, Trace **tracePointer)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
int result = allocBufferFromPool(layer->traceBufferPool,
|
|
Packit Service |
75d76b |
(void **) tracePointer);
|
|
Packit Service |
75d76b |
if (result == VDO_SUCCESS) {
|
|
Packit Service |
75d76b |
(*tracePointer)->used = 0;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*************************************************************************/
|
|
Packit Service |
75d76b |
void freeTraceToPool(KernelLayer *layer, Trace *trace)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
freeBufferToPool(layer->traceBufferPool, trace);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*************************************************************************/
|
|
Packit Service |
75d76b |
int traceKernelLayerInit(KernelLayer *layer)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
layer->vioTraceRecording = traceRecording;
|
|
Packit Service |
75d76b |
initializeSampleCounter(&layer->traceSampleCounter, TRACE_SAMPLE_INTERVAL);
|
|
Packit Service |
75d76b |
unsigned int traceRecordsNeeded = 0;
|
|
Packit Service |
75d76b |
if (layer->vioTraceRecording) {
|
|
Packit Service |
75d76b |
traceRecordsNeeded += layer->requestLimiter.limit;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
if (traceRecordsNeeded > 0) {
|
|
Packit Service |
75d76b |
return makeBufferPool("KVDO Trace Data Pool", traceRecordsNeeded,
|
|
Packit Service |
75d76b |
allocTraceDataBuffer, freeTraceDataBuffer, NULL,
|
|
Packit Service |
75d76b |
layer, &layer->traceBufferPool);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
return VDO_SUCCESS;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*************************************************************************/
|
|
Packit Service |
75d76b |
void initializeTraceLoggingOnce(void)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
mutex_init(&traceLoggingState.lock);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/*************************************************************************/
|
|
Packit Service |
75d76b |
void logKvioTrace(KVIO *kvio)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
KernelLayer *layer = kvio->layer;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
mutex_lock(&traceLoggingState.lock);
|
|
Packit Service |
75d76b |
traceLoggingState.counter++;
|
|
Packit Service |
75d76b |
// Log about 0.1% to avoid spewing data faster than syslog can keep up
|
|
Packit Service |
75d76b |
// (on certain of Permabit's test machines).
|
|
Packit Service |
75d76b |
// Yes, the 37 is arbitrary and meaningless.
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
if (layer->traceLogging && ((traceLoggingState.counter % 1024) == 37)) {
|
|
Packit Service |
75d76b |
kvioAddTraceRecord(kvio, THIS_LOCATION(NULL));
|
|
Packit Service |
75d76b |
size_t traceLen = 0;
|
|
Packit Service |
75d76b |
formatTrace(kvio->vio->trace, traceLoggingState.buffer,
|
|
Packit Service |
75d76b |
sizeof(traceLoggingState.buffer), &traceLen);
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
if (isMetadata(kvio)) {
|
|
Packit Service |
75d76b |
logInfo("finishing kvio %s meta @%" PRIptr " %s",
|
|
Packit Service |
75d76b |
(isWriteVIO(kvio->vio) ? "read" : "write"),
|
|
Packit Service |
75d76b |
kvio, traceLoggingState.buffer);
|
|
Packit Service |
75d76b |
} else if (isCompressedWriter(kvio)) {
|
|
Packit Service |
75d76b |
logInfo("finishing kvio write comp @%" PRIptr " %s",
|
|
Packit Service |
75d76b |
kvio, traceLoggingState.buffer);
|
|
Packit Service |
75d76b |
} else {
|
|
Packit Service |
75d76b |
const char *dupeLabel = "";
|
|
Packit Service |
75d76b |
if (isWriteVIO(kvio->vio)) {
|
|
Packit Service |
75d76b |
DataVIO *dataVIO = vioAsDataVIO(kvio->vio);
|
|
Packit Service |
75d76b |
if (isTrimDataVIO(dataVIO)) {
|
|
Packit Service |
75d76b |
dupeLabel = "trim ";
|
|
Packit Service |
75d76b |
} else if (dataVIO->isZeroBlock) {
|
|
Packit Service |
75d76b |
dupeLabel = "zero ";
|
|
Packit Service |
75d76b |
} else if (dataVIO->isDuplicate) {
|
|
Packit Service |
75d76b |
dupeLabel = "dupe ";
|
|
Packit Service |
75d76b |
} else {
|
|
Packit Service |
75d76b |
dupeLabel = "new ";
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
logInfo("finishing kvio %s data %s@%" PRIptr " %.*s",
|
|
Packit Service |
75d76b |
(isWriteVIO(kvio->vio) ? "read" : "write"),
|
|
Packit Service |
75d76b |
dupeLabel, kvio, TRACE_LOG_MAX, traceLoggingState.buffer);
|
|
Packit Service |
75d76b |
char *buf = traceLoggingState.buffer;
|
|
Packit Service |
75d76b |
while (traceLen > TRACE_LOG_MAX) {
|
|
Packit Service |
75d76b |
traceLen -= TRACE_LOG_MAX;
|
|
Packit Service |
75d76b |
buf += TRACE_LOG_MAX;
|
|
Packit Service |
75d76b |
logInfo("more kvio %" PRIptr " path: %.*s", kvio, TRACE_LOG_MAX, buf);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
mutex_unlock(&traceLoggingState.lock);
|
|
Packit Service |
75d76b |
}
|