Blame source/vdo/kernel/kernelVDO.c

Packit Service d40955
/*
Packit Service d40955
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service d40955
 *
Packit Service d40955
 * This program is free software; you can redistribute it and/or
Packit Service d40955
 * modify it under the terms of the GNU General Public License
Packit Service d40955
 * as published by the Free Software Foundation; either version 2
Packit Service d40955
 * of the License, or (at your option) any later version.
Packit Service d40955
 * 
Packit Service d40955
 * This program is distributed in the hope that it will be useful,
Packit Service d40955
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service d40955
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service d40955
 * GNU General Public License for more details.
Packit Service d40955
 * 
Packit Service d40955
 * You should have received a copy of the GNU General Public License
Packit Service d40955
 * along with this program; if not, write to the Free Software
Packit Service d40955
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service d40955
 * 02110-1301, USA. 
Packit Service d40955
 *
Packit Service d40955
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/kernelVDO.c#7 $
Packit Service d40955
 */
Packit Service d40955
Packit Service d40955
#include "kernelVDOInternals.h"
Packit Service d40955
Packit Service d40955
#include <linux/delay.h>
Packit Service d40955
Packit Service d40955
#include "memoryAlloc.h"
Packit Service d40955
Packit Service d40955
#include "statistics.h"
Packit Service d40955
#include "threadConfig.h"
Packit Service d40955
#include "vdo.h"
Packit Service d40955
#include "vdoDebug.h"
Packit Service d40955
#include "vdoLoad.h"
Packit Service d40955
#include "vdoResize.h"
Packit Service d40955
#include "vdoResizeLogical.h"
Packit Service d40955
#include "vdoResume.h"
Packit Service d40955
#include "vdoSuspend.h"
Packit Service d40955
Packit Service d40955
#include "kernelLayer.h"
Packit Service d40955
#include "kvio.h"
Packit Service d40955
#include "logger.h"
Packit Service d40955
Packit Service d40955
enum { PARANOID_THREAD_CONSISTENCY_CHECKS = 0 };
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static void startKVDORequestQueue(void *ptr)
Packit Service d40955
{
Packit Service d40955
  KVDOThread  *thread = ptr;
Packit Service d40955
  KVDO        *kvdo   = thread->kvdo;
Packit Service d40955
  KernelLayer *layer  = container_of(kvdo, KernelLayer, kvdo);
Packit Service d40955
  registerAllocatingThread(&thread->allocatingThread,
Packit Service d40955
                           &layer->allocationsAllowed);
Packit Service d40955
  setWorkQueuePrivateData(thread);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static void finishKVDORequestQueue(void *ptr)
Packit Service d40955
{
Packit Service d40955
  unregisterAllocatingThread();
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static const KvdoWorkQueueType requestQueueType = {
Packit Service d40955
  .start       = startKVDORequestQueue,
Packit Service d40955
  .finish      = finishKVDORequestQueue,
Packit Service d40955
  .actionTable = {
Packit Service d40955
    { .name = "req_completion",
Packit Service d40955
      .code = REQ_Q_ACTION_COMPLETION,
Packit Service d40955
      .priority = 1 },
Packit Service d40955
    { .name = "req_flush",
Packit Service d40955
      .code = REQ_Q_ACTION_FLUSH,
Packit Service d40955
      .priority = 2 },
Packit Service d40955
    { .name = "req_map_bio",
Packit Service d40955
      .code = REQ_Q_ACTION_MAP_BIO,
Packit Service d40955
      .priority = 0 },
Packit Service d40955
    { .name = "req_sync",
Packit Service d40955
      .code = REQ_Q_ACTION_SYNC,
Packit Service d40955
      .priority = 2 },
Packit Service d40955
    { .name = "req_vio_callback",
Packit Service d40955
      .code = REQ_Q_ACTION_VIO_CALLBACK,
Packit Service d40955
      .priority = 1 },
Packit Service d40955
  },
Packit Service d40955
};
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int initializeKVDO(KVDO                *kvdo,
Packit Service d40955
                   const ThreadConfig  *threadConfig,
Packit Service d40955
                   char               **reason)
Packit Service d40955
{
Packit Service d40955
  unsigned int baseThreads = threadConfig->baseThreadCount;
Packit Service d40955
  int result = ALLOCATE(baseThreads, KVDOThread,
Packit Service d40955
                        "request processing work queue",
Packit Service d40955
                        &kvdo->threads);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    *reason = "Cannot allocation thread structures";
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
  KernelLayer *layer = container_of(kvdo, KernelLayer, kvdo);
Packit Service d40955
  for (kvdo->initializedThreadCount = 0;
Packit Service d40955
       kvdo->initializedThreadCount < baseThreads;
Packit Service d40955
       kvdo->initializedThreadCount++) {
Packit Service d40955
    KVDOThread *thread = &kvdo->threads[kvdo->initializedThreadCount];
Packit Service d40955
Packit Service d40955
    thread->kvdo = kvdo;
Packit Service d40955
    thread->threadID = kvdo->initializedThreadCount;
Packit Service d40955
Packit Service d40955
    char queueName[MAX_QUEUE_NAME_LEN];
Packit Service d40955
    // Copy only LEN - 1 bytes and ensure NULL termination.
Packit Service d40955
    getVDOThreadName(threadConfig, kvdo->initializedThreadCount,
Packit Service d40955
                     queueName, sizeof(queueName));
Packit Service d40955
    int result = makeWorkQueue(layer->threadNamePrefix, queueName,
Packit Service d40955
                               &layer->wqDirectory, layer, thread,
Packit Service d40955
                               &requestQueueType, 1, &thread->requestQueue);
Packit Service d40955
    if (result != VDO_SUCCESS) {
Packit Service d40955
      *reason = "Cannot initialize request queue";
Packit Service d40955
      while (kvdo->initializedThreadCount > 0) {
Packit Service d40955
        unsigned int threadToDestroy = kvdo->initializedThreadCount - 1;
Packit Service d40955
        thread = &kvdo->threads[threadToDestroy];
Packit Service d40955
        finishWorkQueue(thread->requestQueue);
Packit Service d40955
        freeWorkQueue(&thread->requestQueue);
Packit Service d40955
        kvdo->initializedThreadCount--;
Packit Service d40955
      }
Packit Service d40955
      FREE(kvdo->threads);
Packit Service d40955
      return result;
Packit Service d40955
    }
Packit Service d40955
Packit Service d40955
  }
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int preloadKVDO(KVDO                 *kvdo,
Packit Service d40955
                PhysicalLayer        *common,
Packit Service d40955
                const VDOLoadConfig  *loadConfig,
Packit Service d40955
                bool                  vioTraceRecording,
Packit Service d40955
                char                **reason)
Packit Service d40955
{
Packit Service d40955
  KernelLayer *layer = asKernelLayer(common);
Packit Service d40955
  init_completion(&layer->callbackSync);
Packit Service d40955
  int result = prepareToLoadVDO(kvdo->vdo, loadConfig);
Packit Service d40955
  if ((result != VDO_SUCCESS) && (result != VDO_READ_ONLY)) {
Packit Service d40955
    *reason = "Cannot load metadata from device";
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  setVDOTracingFlags(kvdo->vdo, vioTraceRecording);
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int startKVDO(KVDO *kvdo, PhysicalLayer *common, char **reason)
Packit Service d40955
{
Packit Service d40955
  KernelLayer *layer = asKernelLayer(common);
Packit Service d40955
  init_completion(&layer->callbackSync);
Packit Service d40955
  int result = performVDOLoad(kvdo->vdo);
Packit Service d40955
  if ((result != VDO_SUCCESS) && (result != VDO_READ_ONLY)) {
Packit Service d40955
    *reason = "Cannot load metadata from device";
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int suspendKVDO(KVDO *kvdo)
Packit Service d40955
{
Packit Service d40955
  if (kvdo->vdo == NULL) {
Packit Service d40955
    return VDO_SUCCESS;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  KernelLayer *layer = container_of(kvdo, KernelLayer, kvdo);
Packit Service d40955
  init_completion(&layer->callbackSync);
Packit Service d40955
  int result = performVDOSuspend(kvdo->vdo, !layer->noFlushSuspend);
Packit Service d40955
  if ((result != VDO_SUCCESS) && (result != VDO_READ_ONLY)) {
Packit Service d40955
    char errorName[80] = "";
Packit Service d40955
    char errorMessage[ERRBUF_SIZE] = "";
Packit Service d40955
    logError("%s: Suspend device failed %d (%s: %s)",
Packit Service d40955
             __func__, result,
Packit Service d40955
             stringErrorName(result, errorName, sizeof(errorName)),
Packit Service d40955
             stringError(result, errorMessage, sizeof(errorMessage)));
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  // Convert VDO_READ_ONLY to VDO_SUCCESS since a read-only suspension still
Packit Service d40955
  // leaves the VDO suspended.
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int resumeKVDO(KVDO *kvdo)
Packit Service d40955
{
Packit Service d40955
  if (kvdo->vdo == NULL) {
Packit Service d40955
    return VDO_SUCCESS;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  KernelLayer *layer = container_of(kvdo, KernelLayer, kvdo);
Packit Service d40955
  init_completion(&layer->callbackSync);
Packit Service d40955
  return performVDOResume(kvdo->vdo);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void finishKVDO(KVDO *kvdo)
Packit Service d40955
{
Packit Service d40955
  for (int i = 0; i < kvdo->initializedThreadCount; i++) {
Packit Service d40955
    finishWorkQueue(kvdo->threads[i].requestQueue);
Packit Service d40955
  }
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void destroyKVDO(KVDO *kvdo)
Packit Service d40955
{
Packit Service d40955
  destroyVDO(kvdo->vdo);
Packit Service d40955
  for (int i = 0; i < kvdo->initializedThreadCount; i++) {
Packit Service d40955
    freeWorkQueue(&kvdo->threads[i].requestQueue);
Packit Service d40955
  }
Packit Service d40955
  FREE(kvdo->threads);
Packit Service d40955
  kvdo->threads = NULL;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void dumpKVDOWorkQueue(KVDO *kvdo)
Packit Service d40955
{
Packit Service d40955
  for (int i = 0; i < kvdo->initializedThreadCount; i++) {
Packit Service d40955
    dumpWorkQueue(kvdo->threads[i].requestQueue);
Packit Service d40955
  }
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
typedef struct {
Packit Service d40955
  KvdoWorkItem       workItem;
Packit Service d40955
  KVDO              *kvdo;
Packit Service d40955
  void              *data;
Packit Service d40955
  struct completion *completion;
Packit Service d40955
} SyncQueueWork;
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Initiate an arbitrary asynchronous base-code operation and wait for
Packit Service d40955
 * it.
Packit Service d40955
 *
Packit Service d40955
 * An async queue operation is performed and we wait for completion.
Packit Service d40955
 *
Packit Service d40955
 * @param kvdo       The kvdo data handle
Packit Service d40955
 * @param action     The operation to perform
Packit Service d40955
 * @param data       Unique data that can be used by the operation
Packit Service d40955
 * @param threadID   The thread on which to perform the operation
Packit Service d40955
 * @param completion The completion to wait on
Packit Service d40955
 *
Packit Service d40955
 * @return VDO_SUCCESS of an error code
Packit Service d40955
 **/
Packit Service d40955
static void performKVDOOperation(KVDO              *kvdo,
Packit Service d40955
                                 KvdoWorkFunction   action,
Packit Service d40955
                                 void              *data,
Packit Service d40955
                                 ThreadID           threadID,
Packit Service d40955
                                 struct completion *completion)
Packit Service d40955
{
Packit Service d40955
  SyncQueueWork  sync;
Packit Service d40955
Packit Service d40955
  memset(&sync, 0, sizeof(sync));
Packit Service d40955
  setupWorkItem(&sync.workItem, action, NULL, REQ_Q_ACTION_SYNC);
Packit Service d40955
  sync.kvdo       = kvdo;
Packit Service d40955
  sync.data       = data;
Packit Service d40955
  sync.completion = completion;
Packit Service d40955
Packit Service d40955
  init_completion(completion);
Packit Service d40955
  enqueueKVDOWork(kvdo, &sync.workItem, threadID);
Packit Service d40955
  wait_for_completion(completion);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
typedef struct {
Packit Service d40955
  bool enable;
Packit Service d40955
  bool wasEnabled;
Packit Service d40955
} VDOCompressData;
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Does the work of calling the base code to set compress state, then
Packit Service d40955
 * tells the function waiting on completion to go ahead.
Packit Service d40955
 *
Packit Service d40955
 * @param item  The work item
Packit Service d40955
 **/
Packit Service d40955
static void setCompressingWork(KvdoWorkItem *item)
Packit Service d40955
{
Packit Service d40955
  SyncQueueWork   *work  = container_of(item, SyncQueueWork, workItem);
Packit Service d40955
  VDOCompressData *data  = (VDOCompressData *)work->data;
Packit Service d40955
  data->wasEnabled = setVDOCompressing(getVDO(work->kvdo), data->enable);
Packit Service d40955
  complete(work->completion);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/***********************************************************************/
Packit Service d40955
bool setKVDOCompressing(KVDO *kvdo, bool enableCompression)
Packit Service d40955
{
Packit Service d40955
  struct completion compressWait;
Packit Service d40955
  VDOCompressData data;
Packit Service d40955
  data.enable = enableCompression;
Packit Service d40955
  performKVDOOperation(kvdo, setCompressingWork, &data,
Packit Service d40955
                       getPackerZoneThread(getThreadConfig(kvdo->vdo)),
Packit Service d40955
                       &compressWait);
Packit Service d40955
  return data.wasEnabled;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
typedef struct {
Packit Service d40955
  int result;
Packit Service d40955
} VDOReadOnlyData;
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static void enterReadOnlyModeWork(KvdoWorkItem *item)
Packit Service d40955
{
Packit Service d40955
  SyncQueueWork   *work = container_of(item, SyncQueueWork, workItem);
Packit Service d40955
  VDOReadOnlyData *data = work->data;
Packit Service d40955
  makeVDOReadOnly(getVDO(work->kvdo), data->result);
Packit Service d40955
  complete(work->completion);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/***********************************************************************/
Packit Service d40955
void setKVDOReadOnly(KVDO *kvdo, int result)
Packit Service d40955
{
Packit Service d40955
  struct completion readOnlyWait;
Packit Service d40955
  VDOReadOnlyData data;
Packit Service d40955
  data.result = result;
Packit Service d40955
  performKVDOOperation(kvdo, enterReadOnlyModeWork, &data,
Packit Service d40955
                       getAdminThread(getThreadConfig(kvdo->vdo)),
Packit Service d40955
                       &readOnlyWait);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Does the work of calling the vdo statistics gathering tool
Packit Service d40955
 *
Packit Service d40955
 * @param item   The work item
Packit Service d40955
 **/
Packit Service d40955
static void getVDOStatisticsWork(KvdoWorkItem *item)
Packit Service d40955
{
Packit Service d40955
  SyncQueueWork *work  = container_of(item, SyncQueueWork, workItem);
Packit Service d40955
  VDOStatistics *stats = (VDOStatistics *)work->data;
Packit Service d40955
  getVDOStatistics(getVDO(work->kvdo), stats);
Packit Service d40955
  complete(work->completion);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/***********************************************************************/
Packit Service d40955
void getKVDOStatistics(KVDO *kvdo, VDOStatistics *stats)
Packit Service d40955
{
Packit Service d40955
  struct completion statsWait;
Packit Service d40955
  memset(stats, 0, sizeof(VDOStatistics));
Packit Service d40955
  performKVDOOperation(kvdo, getVDOStatisticsWork, stats,
Packit Service d40955
                       getAdminThread(getThreadConfig(kvdo->vdo)),
Packit Service d40955
                       &statsWait);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * A structure to invoke an arbitrary VDO action.
Packit Service d40955
 **/
Packit Service d40955
typedef struct vdoActionData {
Packit Service d40955
  VDOAction          *action;
Packit Service d40955
  VDOCompletion      *vdoCompletion;
Packit Service d40955
  struct completion   waiter;
Packit Service d40955
} VDOActionData;
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Initialize a VDOActionData structure so that the specified action
Packit Service d40955
 * can be invoked on the specified completion.
Packit Service d40955
 *
Packit Service d40955
 * @param data              A VDOActionData.
Packit Service d40955
 * @param action            The VDOAction to execute.
Packit Service d40955
 * @param vdoCompletion     The VDO completion upon which the action acts.
Packit Service d40955
 **/
Packit Service d40955
static void initializeVDOActionData(VDOActionData *data,
Packit Service d40955
                                    VDOAction     *action,
Packit Service d40955
                                    VDOCompletion *vdoCompletion)
Packit Service d40955
{
Packit Service d40955
  *data = (VDOActionData) {
Packit Service d40955
    .action        = action,
Packit Service d40955
    .vdoCompletion = vdoCompletion,
Packit Service d40955
  };
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * The VDO callback that completes the KVDO completion.
Packit Service d40955
 *
Packit Service d40955
 * @param vdoCompletion     The VDO completion which was acted upon.
Packit Service d40955
 **/
Packit Service d40955
static void finishVDOAction(VDOCompletion *vdoCompletion)
Packit Service d40955
{
Packit Service d40955
  SyncQueueWork *work = vdoCompletion->parent;
Packit Service d40955
  complete(work->completion);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Perform a VDO base code action as specified by a VDOActionData.
Packit Service d40955
 *
Packit Service d40955
 * Sets the completion callback and parent inside the VDOActionData
Packit Service d40955
 * so that the corresponding kernel completion is completed when
Packit Service d40955
 * the VDO completion is.
Packit Service d40955
 *
Packit Service d40955
 * @param item          A KVDO work queue item.
Packit Service d40955
 **/
Packit Service d40955
static void performVDOActionWork(KvdoWorkItem *item)
Packit Service d40955
{
Packit Service d40955
  SyncQueueWork *work = container_of(item, SyncQueueWork, workItem);
Packit Service d40955
  VDOActionData *data = work->data;
Packit Service d40955
  ThreadID       id   = getPhysicalLayer()->getCurrentThreadID();
Packit Service d40955
Packit Service d40955
  setCallbackWithParent(data->vdoCompletion, finishVDOAction, id, work);
Packit Service d40955
  data->action(data->vdoCompletion);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int performKVDOExtendedCommand(KVDO *kvdo, int argc, char **argv)
Packit Service d40955
{
Packit Service d40955
  VDOActionData        data;
Packit Service d40955
  VDOCommandCompletion cmd;
Packit Service d40955
Packit Service d40955
  int result = initializeVDOCommandCompletion(&cmd, getVDO(kvdo), argc, argv);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  initializeVDOActionData(&data, executeVDOExtendedCommand, &cmd.completion);
Packit Service d40955
  performKVDOOperation(kvdo, performVDOActionWork, &data,
Packit Service d40955
                       getAdminThread(getThreadConfig(kvdo->vdo)),
Packit Service d40955
                       &data.waiter);
Packit Service d40955
Packit Service d40955
  return destroyVDOCommandCompletion(&cmd);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void dumpKVDOStatus(KVDO *kvdo)
Packit Service d40955
{
Packit Service d40955
  dumpVDOStatus(kvdo->vdo);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
bool getKVDOCompressing(KVDO *kvdo)
Packit Service d40955
{
Packit Service d40955
  return getVDOCompressing(kvdo->vdo);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int kvdoPrepareToGrowPhysical(KVDO *kvdo, BlockCount physicalCount)
Packit Service d40955
{
Packit Service d40955
  VDO *vdo = kvdo->vdo;
Packit Service d40955
  return prepareToGrowPhysical(vdo, physicalCount);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int kvdoResizePhysical(KVDO *kvdo, BlockCount physicalCount)
Packit Service d40955
{
Packit Service d40955
  KernelLayer *layer = container_of(kvdo, KernelLayer, kvdo);
Packit Service d40955
  init_completion(&layer->callbackSync);
Packit Service d40955
  int result = performGrowPhysical(kvdo->vdo, physicalCount);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    logError("resize operation failed, result = %d", result);
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int kvdoPrepareToGrowLogical(KVDO *kvdo, BlockCount logicalCount)
Packit Service d40955
{
Packit Service d40955
  VDO *vdo = kvdo->vdo;
Packit Service d40955
  return prepareToGrowLogical(vdo, logicalCount);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int kvdoResizeLogical(KVDO *kvdo, BlockCount logicalCount)
Packit Service d40955
{
Packit Service d40955
  KernelLayer *layer = container_of(kvdo, KernelLayer, kvdo);
Packit Service d40955
  init_completion(&layer->callbackSync);
Packit Service d40955
  int result = performGrowLogical(kvdo->vdo, logicalCount);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    logError("grow logical operation failed, result = %d", result);
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  return result;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
WritePolicy getKVDOWritePolicy(KVDO *kvdo)
Packit Service d40955
{
Packit Service d40955
  return getWritePolicy(kvdo->vdo);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void enqueueKVDOThreadWork(KVDOThread    *thread,
Packit Service d40955
                           KvdoWorkItem  *item)
Packit Service d40955
{
Packit Service d40955
  enqueueWorkQueue(thread->requestQueue, item);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void enqueueKVDOWork(KVDO *kvdo, KvdoWorkItem *item, ThreadID threadID)
Packit Service d40955
{
Packit Service d40955
  enqueueKVDOThreadWork(&kvdo->threads[threadID], item);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void enqueueKVIO(KVIO             *kvio,
Packit Service d40955
                 KvdoWorkFunction  work,
Packit Service d40955
                 void             *statsFunction,
Packit Service d40955
                 unsigned int      action)
Packit Service d40955
{
Packit Service d40955
  ThreadID threadID = vioAsCompletion(kvio->vio)->callbackThreadID;
Packit Service d40955
  BUG_ON(threadID >= kvio->layer->kvdo.initializedThreadCount);
Packit Service d40955
  launchKVIO(kvio, work, statsFunction, action,
Packit Service d40955
             kvio->layer->kvdo.threads[threadID].requestQueue);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static void kvdoEnqueueWork(KvdoWorkItem *workItem)
Packit Service d40955
{
Packit Service d40955
  KvdoEnqueueable *kvdoEnqueueable = container_of(workItem,
Packit Service d40955
                                                  KvdoEnqueueable,
Packit Service d40955
                                                  workItem);
Packit Service d40955
  runCallback(kvdoEnqueueable->enqueueable.completion);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void kvdoEnqueue(Enqueueable *enqueueable)
Packit Service d40955
{
Packit Service d40955
  KvdoEnqueueable *kvdoEnqueueable = container_of(enqueueable,
Packit Service d40955
                                                  KvdoEnqueueable,
Packit Service d40955
                                                  enqueueable);
Packit Service d40955
  KernelLayer *layer    = asKernelLayer(enqueueable->completion->layer);
Packit Service d40955
  ThreadID     threadID = enqueueable->completion->callbackThreadID;
Packit Service d40955
  if (ASSERT(threadID < layer->kvdo.initializedThreadCount,
Packit Service d40955
             "threadID %u (completion type %d) is less than thread count %u",
Packit Service d40955
             threadID, enqueueable->completion->type,
Packit Service d40955
             layer->kvdo.initializedThreadCount) != UDS_SUCCESS) {
Packit Service d40955
    BUG();
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  if (enqueueable->completion->type == VIO_COMPLETION) {
Packit Service d40955
    vioAddTraceRecord(asVIO(enqueueable->completion),
Packit Service d40955
                      THIS_LOCATION("$F($cb)"));
Packit Service d40955
  }
Packit Service d40955
  setupWorkItem(&kvdoEnqueueable->workItem, kvdoEnqueueWork,
Packit Service d40955
                (KvdoWorkFunction) enqueueable->completion->callback,
Packit Service d40955
                REQ_Q_ACTION_COMPLETION);
Packit Service d40955
  enqueueKVDOThreadWork(&layer->kvdo.threads[threadID],
Packit Service d40955
                        &kvdoEnqueueable->workItem);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
ThreadID kvdoGetCurrentThreadID(void)
Packit Service d40955
{
Packit Service d40955
  KVDOThread *thread = getWorkQueuePrivateData();
Packit Service d40955
  if (thread == NULL) {
Packit Service d40955
    return INVALID_THREAD_ID;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  ThreadID threadID = thread->threadID;
Packit Service d40955
  if (PARANOID_THREAD_CONSISTENCY_CHECKS) {
Packit Service d40955
    KVDO        *kvdo        = thread->kvdo;
Packit Service d40955
    KernelLayer *kernelLayer = asKernelLayer(getPhysicalLayer());
Packit Service d40955
    BUG_ON(&kernelLayer->kvdo != kvdo);
Packit Service d40955
    BUG_ON(threadID >= kvdo->initializedThreadCount);
Packit Service d40955
    BUG_ON(thread != &kvdo->threads[threadID]);
Packit Service d40955
  }
Packit Service d40955
  return threadID;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static PhysicalLayer *getKernelPhysicalLayer(void)
Packit Service d40955
{
Packit Service d40955
  KVDOThread  *thread = getWorkQueuePrivateData();
Packit Service d40955
  if (thread == NULL) {
Packit Service d40955
    return NULL;
Packit Service d40955
  }
Packit Service d40955
  KVDO        *kvdo   = thread->kvdo;
Packit Service d40955
  KernelLayer *layer  = container_of(kvdo, KernelLayer, kvdo);
Packit Service d40955
  return &layer->common;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
void initKernelVDOOnce(void)
Packit Service d40955
{
Packit Service d40955
  registerPhysicalLayerGetter(getKernelPhysicalLayer);
Packit Service d40955
}