Blame source/vdo/kernel/dump.c

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