Blame vdo/kernel/dump.c

Packit Service b3514a
/*
Packit Service b3514a
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service b3514a
 *
Packit Service b3514a
 * This program is free software; you can redistribute it and/or
Packit Service b3514a
 * modify it under the terms of the GNU General Public License
Packit Service b3514a
 * as published by the Free Software Foundation; either version 2
Packit Service b3514a
 * of the License, or (at your option) any later version.
Packit Service b3514a
 * 
Packit Service b3514a
 * This program is distributed in the hope that it will be useful,
Packit Service b3514a
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service b3514a
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service b3514a
 * GNU General Public License for more details.
Packit Service b3514a
 * 
Packit Service b3514a
 * You should have received a copy of the GNU General Public License
Packit Service b3514a
 * along with this program; if not, write to the Free Software
Packit Service b3514a
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service b3514a
 * 02110-1301, USA. 
Packit Service b3514a
 *
Packit Service b3514a
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/dump.c#2 $
Packit Service b3514a
 */
Packit Service b3514a
Packit Service b3514a
#include "dump.h"
Packit Service b3514a
Packit Service b3514a
#include <linux/module.h>
Packit Service b3514a
Packit Service b3514a
#include "memoryAlloc.h"
Packit Service b3514a
#include "typeDefs.h"
Packit Service b3514a
Packit Service b3514a
#include "constants.h"
Packit Service b3514a
#include "vdo.h"
Packit Service b3514a
Packit Service b3514a
#include "dedupeIndex.h"
Packit Service b3514a
#include "histogram.h"
Packit Service b3514a
#include "ioSubmitter.h"
Packit Service b3514a
#include "logger.h"
Packit Service b3514a
Packit Service b3514a
enum dumpOptions {
Packit Service b3514a
  // WorkQueues
Packit Service b3514a
  SHOW_ALBIREO_QUEUE,
Packit Service b3514a
  SHOW_BIO_ACK_QUEUE,
Packit Service b3514a
  SHOW_BIO_QUEUE,
Packit Service b3514a
  SHOW_CPU_QUEUES,
Packit Service b3514a
  SHOW_REQUEST_QUEUE,
Packit Service b3514a
  // MemoryPools
Packit Service b3514a
  SHOW_VIO_POOL,
Packit Service b3514a
  // Others
Packit Service b3514a
  SHOW_VDO_STATUS,
Packit Service b3514a
  // This one means an option overrides the "default" choices, instead
Packit Service b3514a
  // of altering them.
Packit Service b3514a
  SKIP_DEFAULT
Packit Service b3514a
};
Packit Service b3514a
Packit Service b3514a
enum dumpOptionFlags {
Packit Service b3514a
  // WorkQueues
Packit Service b3514a
  FLAG_SHOW_ALBIREO_QUEUE = (1 << SHOW_ALBIREO_QUEUE),
Packit Service b3514a
  FLAG_SHOW_BIO_ACK_QUEUE = (1 << SHOW_BIO_ACK_QUEUE),
Packit Service b3514a
  FLAG_SHOW_BIO_QUEUE     = (1 << SHOW_BIO_QUEUE),
Packit Service b3514a
  FLAG_SHOW_CPU_QUEUES    = (1 << SHOW_CPU_QUEUES),
Packit Service b3514a
  FLAG_SHOW_REQUEST_QUEUE = (1 << SHOW_REQUEST_QUEUE),
Packit Service b3514a
  // MemoryPools
Packit Service b3514a
  FLAG_SHOW_VIO_POOL      = (1 << SHOW_VIO_POOL),
Packit Service b3514a
  // Others
Packit Service b3514a
  FLAG_SHOW_VDO_STATUS    = (1 << SHOW_VDO_STATUS),
Packit Service b3514a
  // Special
Packit Service b3514a
  FLAG_SKIP_DEFAULT       = (1 << SKIP_DEFAULT)
Packit Service b3514a
  };
Packit Service b3514a
Packit Service b3514a
enum {
Packit Service b3514a
  FLAGS_ALL_POOLS    = (FLAG_SHOW_VIO_POOL),
Packit Service b3514a
  FLAGS_ALL_QUEUES   = (FLAG_SHOW_REQUEST_QUEUE
Packit Service b3514a
                        | FLAG_SHOW_ALBIREO_QUEUE
Packit Service b3514a
                        | FLAG_SHOW_BIO_ACK_QUEUE
Packit Service b3514a
                        | FLAG_SHOW_BIO_QUEUE
Packit Service b3514a
                        | FLAG_SHOW_CPU_QUEUES),
Packit Service b3514a
  FLAGS_ALL_THREADS  = (FLAGS_ALL_QUEUES),
Packit Service b3514a
  DEFAULT_DUMP_FLAGS = (FLAGS_ALL_THREADS | FLAG_SHOW_VDO_STATUS)
Packit Service b3514a
};
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
static inline bool isArgString(const char *arg, const char *thisOption)
Packit Service b3514a
{
Packit Service b3514a
  // device-mapper convention seems to be case-independent options
Packit Service b3514a
  return strncasecmp(arg, thisOption, strlen(thisOption)) == 0;
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
static void doDump(KernelLayer  *layer,
Packit Service b3514a
                   unsigned int  dumpOptionsRequested,
Packit Service b3514a
                   const char   *why)
Packit Service b3514a
{
Packit Service b3514a
  logInfo("%s dump triggered via %s", THIS_MODULE->name, why);
Packit Service b3514a
  // XXX Add in number of outstanding requests being processed by vdo
Packit Service b3514a
  uint32_t active, maximum;
Packit Service b3514a
  getLimiterValuesAtomically(&layer->requestLimiter, &active, &maximum);
Packit Service b3514a
  int64_t outstanding = atomic64_read(&layer->biosSubmitted)
Packit Service b3514a
                        - atomic64_read(&layer->biosCompleted);
Packit Service b3514a
  logInfo("%" PRIu32 " device requests outstanding (max %" PRIu32 "), "
Packit Service b3514a
          "%" PRId64 " bio requests outstanding, poolName '%s'",
Packit Service b3514a
          active, maximum, outstanding, layer->deviceConfig->poolName);
Packit Service b3514a
  if ((dumpOptionsRequested & FLAG_SHOW_REQUEST_QUEUE) != 0) {
Packit Service b3514a
    dumpKVDOWorkQueue(&layer->kvdo);
Packit Service b3514a
  }
Packit Service b3514a
  if ((dumpOptionsRequested & FLAG_SHOW_BIO_QUEUE) != 0) {
Packit Service b3514a
    dumpBioWorkQueue(layer->ioSubmitter);
Packit Service b3514a
  }
Packit Service b3514a
  if (useBioAckQueue(layer)
Packit Service b3514a
      && ((dumpOptionsRequested & FLAG_SHOW_BIO_ACK_QUEUE) != 0)) {
Packit Service b3514a
    dumpWorkQueue(layer->bioAckQueue);
Packit Service b3514a
  }
Packit Service b3514a
  if ((dumpOptionsRequested & FLAG_SHOW_CPU_QUEUES) != 0) {
Packit Service b3514a
    dumpWorkQueue(layer->cpuQueue);
Packit Service b3514a
  }
Packit Service b3514a
  dumpDedupeIndex(layer->dedupeIndex,
Packit Service b3514a
                  (dumpOptionsRequested & FLAG_SHOW_ALBIREO_QUEUE) != 0);
Packit Service b3514a
  dumpBufferPool(layer->dataKVIOPool,
Packit Service b3514a
                 (dumpOptionsRequested & FLAG_SHOW_VIO_POOL) != 0);
Packit Service b3514a
  if ((dumpOptionsRequested & FLAG_SHOW_VDO_STATUS) != 0) {
Packit Service b3514a
    // Options should become more fine-grained when we have more to
Packit Service b3514a
    // display here.
Packit Service b3514a
    dumpKVDOStatus(&layer->kvdo);
Packit Service b3514a
  }
Packit Service b3514a
  reportMemoryUsage();
Packit Service b3514a
  logInfo("end of %s dump", THIS_MODULE->name);
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
static int parseDumpOptions(unsigned int  argc,
Packit Service b3514a
                            char * const *argv,
Packit Service b3514a
                            unsigned int *dumpOptionsRequestedPtr)
Packit Service b3514a
{
Packit Service b3514a
  unsigned int dumpOptionsRequested = 0;
Packit Service b3514a
Packit Service b3514a
  static const struct {
Packit Service b3514a
    const char   *name;
Packit Service b3514a
    unsigned int  flags;
Packit Service b3514a
  } optionNames[] = {
Packit Service b3514a
    // Should "albireo" mean sending queue + receiving thread + outstanding?
Packit Service b3514a
    { "dedupe",      FLAG_SKIP_DEFAULT | FLAG_SHOW_ALBIREO_QUEUE },
Packit Service b3514a
    { "dedupeq",     FLAG_SKIP_DEFAULT | FLAG_SHOW_ALBIREO_QUEUE },
Packit Service b3514a
    { "kvdodedupeq", FLAG_SKIP_DEFAULT | FLAG_SHOW_ALBIREO_QUEUE },
Packit Service b3514a
    { "bioack",      FLAG_SKIP_DEFAULT | FLAG_SHOW_BIO_ACK_QUEUE },
Packit Service b3514a
    { "kvdobioackq", FLAG_SKIP_DEFAULT | FLAG_SHOW_BIO_ACK_QUEUE },
Packit Service b3514a
    { "bioackq",     FLAG_SKIP_DEFAULT | FLAG_SHOW_BIO_ACK_QUEUE },
Packit Service b3514a
    { "bio",         FLAG_SKIP_DEFAULT | FLAG_SHOW_BIO_QUEUE },
Packit Service b3514a
    { "kvdobioq",    FLAG_SKIP_DEFAULT | FLAG_SHOW_BIO_QUEUE },
Packit Service b3514a
    { "bioq",        FLAG_SKIP_DEFAULT | FLAG_SHOW_BIO_QUEUE },
Packit Service b3514a
    { "cpu",         FLAG_SKIP_DEFAULT | FLAG_SHOW_CPU_QUEUES },
Packit Service b3514a
    { "kvdocpuq",    FLAG_SKIP_DEFAULT | FLAG_SHOW_CPU_QUEUES },
Packit Service b3514a
    { "cpuq",        FLAG_SKIP_DEFAULT | FLAG_SHOW_CPU_QUEUES },
Packit Service b3514a
    { "request",     FLAG_SKIP_DEFAULT | FLAG_SHOW_REQUEST_QUEUE },
Packit Service b3514a
    { "kvdoreqq",    FLAG_SKIP_DEFAULT | FLAG_SHOW_REQUEST_QUEUE },
Packit Service b3514a
    { "reqq",        FLAG_SKIP_DEFAULT | FLAG_SHOW_REQUEST_QUEUE },
Packit Service b3514a
    { "viopool",     FLAG_SKIP_DEFAULT | FLAG_SHOW_VIO_POOL },
Packit Service b3514a
    { "vdo",         FLAG_SKIP_DEFAULT | FLAG_SHOW_VDO_STATUS },
Packit Service b3514a
Packit Service b3514a
    { "pools",   FLAG_SKIP_DEFAULT | FLAGS_ALL_POOLS },
Packit Service b3514a
    { "queues",  FLAG_SKIP_DEFAULT | FLAGS_ALL_QUEUES },
Packit Service b3514a
    { "threads", FLAG_SKIP_DEFAULT | FLAGS_ALL_THREADS },
Packit Service b3514a
    { "default", FLAG_SKIP_DEFAULT | DEFAULT_DUMP_FLAGS },
Packit Service b3514a
    { "all",      ~0 },
Packit Service b3514a
  };
Packit Service b3514a
Packit Service b3514a
  bool optionsOkay = true;
Packit Service b3514a
  for (int i = 1; i < argc; i++) {
Packit Service b3514a
    int j;
Packit Service b3514a
    for (j = 0; j < COUNT_OF(optionNames); j++) {
Packit Service b3514a
      if (isArgString(argv[i], optionNames[j].name)) {
Packit Service b3514a
        dumpOptionsRequested |= optionNames[j].flags;
Packit Service b3514a
        break;
Packit Service b3514a
      }
Packit Service b3514a
    }
Packit Service b3514a
    if (j == COUNT_OF(optionNames)) {
Packit Service b3514a
      logWarning("dump option name '%s' unknown", argv[i]);
Packit Service b3514a
      optionsOkay = false;
Packit Service b3514a
    }
Packit Service b3514a
  }
Packit Service b3514a
  if (!optionsOkay) {
Packit Service b3514a
    return -EINVAL;
Packit Service b3514a
  }
Packit Service b3514a
  if ((dumpOptionsRequested & FLAG_SKIP_DEFAULT) == 0) {
Packit Service b3514a
    dumpOptionsRequested |= DEFAULT_DUMP_FLAGS;
Packit Service b3514a
  }
Packit Service b3514a
  *dumpOptionsRequestedPtr = dumpOptionsRequested;
Packit Service b3514a
  return 0;
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
int vdoDump(KernelLayer  *layer,
Packit Service b3514a
            unsigned int  argc,
Packit Service b3514a
            char * const *argv,
Packit Service b3514a
            const char   *why)
Packit Service b3514a
{
Packit Service b3514a
  unsigned int dumpOptionsRequested = 0;
Packit Service b3514a
  int result = parseDumpOptions(argc, argv, &dumpOptionsRequested);
Packit Service b3514a
  if (result != 0) {
Packit Service b3514a
    return result;
Packit Service b3514a
  }
Packit Service b3514a
  doDump(layer, dumpOptionsRequested, why);
Packit Service b3514a
  return 0;
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
void vdoDumpAll(KernelLayer *layer, const char *why)
Packit Service b3514a
{
Packit Service b3514a
  doDump(layer, ~0, why);
Packit Service b3514a
}