Blame vdo/base/vio.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/base/vio.c#5 $
Packit Service b3514a
 */
Packit Service b3514a
Packit Service b3514a
#include "vio.h"
Packit Service b3514a
Packit Service b3514a
#include "logger.h"
Packit Service b3514a
Packit Service b3514a
#include "dataVIO.h"
Packit Service b3514a
#include "vdoInternal.h"
Packit Service b3514a
Packit Service b3514a
#ifdef __KERNEL__
Packit Service b3514a
#include <linux/ratelimit.h>
Packit Service b3514a
#endif
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
void freeVIO(VIO **vioPtr)
Packit Service b3514a
{
Packit Service b3514a
  VIO *vio = *vioPtr;
Packit Service b3514a
  if (vio == NULL) {
Packit Service b3514a
    return;
Packit Service b3514a
  }
Packit Service b3514a
Packit Service b3514a
  vio->completion.layer->freeVIO(vioPtr);
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
void initializeVIO(VIO           *vio,
Packit Service b3514a
                   VIOType        type,
Packit Service b3514a
                   VIOPriority    priority,
Packit Service b3514a
                   VDOCompletion *parent,
Packit Service b3514a
                   VDO           *vdo,
Packit Service b3514a
                   PhysicalLayer *layer)
Packit Service b3514a
{
Packit Service b3514a
  vio->vdo      = vdo;
Packit Service b3514a
  vio->type     = type;
Packit Service b3514a
  vio->priority = priority;
Packit Service b3514a
Packit Service b3514a
  VDOCompletion *completion = vioAsCompletion(vio);
Packit Service b3514a
  initializeCompletion(completion, VIO_COMPLETION, layer);
Packit Service b3514a
  completion->parent = parent;
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
void vioDoneCallback(VDOCompletion *completion)
Packit Service b3514a
{
Packit Service b3514a
  VIO *vio = asVIO(completion);
Packit Service b3514a
  completion->callback     = vio->callback;
Packit Service b3514a
  completion->errorHandler = vio->errorHandler;
Packit Service b3514a
  completeCompletion(completion);
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
const char *getVIOReadWriteFlavor(const VIO *vio)
Packit Service b3514a
{
Packit Service b3514a
  if (isReadVIO(vio)) {
Packit Service b3514a
    return "read";
Packit Service b3514a
  }
Packit Service b3514a
  return (isWriteVIO(vio) ? "write" : "read-modify-write");
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
void updateVIOErrorStats(VIO *vio, const char *format, ...)
Packit Service b3514a
{
Packit Service b3514a
  int priority;
Packit Service b3514a
  int result = vioAsCompletion(vio)->result;
Packit Service b3514a
  switch (result) {
Packit Service b3514a
  case VDO_READ_ONLY:
Packit Service b3514a
    atomicAdd64(&vio->vdo->errorStats.readOnlyErrorCount, 1);
Packit Service b3514a
    return;
Packit Service b3514a
Packit Service b3514a
  case VDO_NO_SPACE:
Packit Service b3514a
    atomicAdd64(&vio->vdo->errorStats.noSpaceErrorCount, 1);
Packit Service b3514a
    priority = LOG_DEBUG;
Packit Service b3514a
    break;
Packit Service b3514a
Packit Service b3514a
  default:
Packit Service b3514a
    priority = LOG_ERR;
Packit Service b3514a
  }
Packit Service b3514a
Packit Service b3514a
#ifdef __KERNEL__
Packit Service b3514a
  static DEFINE_RATELIMIT_STATE(errorLimiter, DEFAULT_RATELIMIT_INTERVAL,
Packit Service b3514a
                                DEFAULT_RATELIMIT_BURST);
Packit Service b3514a
Packit Service b3514a
  if (!__ratelimit(&errorLimiter)) {
Packit Service b3514a
    return;
Packit Service b3514a
  }
Packit Service b3514a
#endif
Packit Service b3514a
Packit Service b3514a
  va_list args;
Packit Service b3514a
  va_start(args, format);
Packit Service b3514a
  vLogWithStringError(priority, result, format, args);
Packit Service b3514a
  va_end(args);
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**
Packit Service b3514a
 * Handle an error from a metadata I/O.
Packit Service b3514a
 *
Packit Service b3514a
 * @param completion  The VIO
Packit Service b3514a
 **/
Packit Service b3514a
static void handleMetadataIOError(VDOCompletion *completion)
Packit Service b3514a
{
Packit Service b3514a
  VIO *vio = asVIO(completion);
Packit Service b3514a
  updateVIOErrorStats(vio,
Packit Service b3514a
                      "Completing %s VIO of type %u for physical block %"
Packit Service b3514a
                       PRIu64 " with error",
Packit Service b3514a
                       getVIOReadWriteFlavor(vio), vio->type, vio->physical);
Packit Service b3514a
  vioDoneCallback(completion);
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
void launchMetadataVIO(VIO                 *vio,
Packit Service b3514a
                       PhysicalBlockNumber  physical,
Packit Service b3514a
                       VDOAction           *callback,
Packit Service b3514a
                       VDOAction           *errorHandler,
Packit Service b3514a
                       VIOOperation         operation)
Packit Service b3514a
{
Packit Service b3514a
  vio->operation    = operation;
Packit Service b3514a
  vio->physical     = physical;
Packit Service b3514a
  vio->callback     = callback;
Packit Service b3514a
  vio->errorHandler = errorHandler;
Packit Service b3514a
Packit Service b3514a
  VDOCompletion *completion = vioAsCompletion(vio);
Packit Service b3514a
  resetCompletion(completion);
Packit Service b3514a
  completion->callback     = vioDoneCallback;
Packit Service b3514a
  completion->errorHandler = handleMetadataIOError;
Packit Service b3514a
Packit Service b3514a
  if (isReadVIO(vio)) {
Packit Service b3514a
    completion->layer->readMetadata(vio);
Packit Service b3514a
  } else {
Packit Service b3514a
    completion->layer->writeMetadata(vio);
Packit Service b3514a
  }
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**
Packit Service b3514a
 * Handle a flush error.
Packit Service b3514a
 *
Packit Service b3514a
 * @param completion  The flush VIO
Packit Service b3514a
 **/
Packit Service b3514a
static void handleFlushError(VDOCompletion *completion)
Packit Service b3514a
{
Packit Service b3514a
  logErrorWithStringError(completion->result, "Error flushing layer");
Packit Service b3514a
  completion->errorHandler = asVIO(completion)->errorHandler;
Packit Service b3514a
  completeCompletion(completion);
Packit Service b3514a
}
Packit Service b3514a
Packit Service b3514a
/**********************************************************************/
Packit Service b3514a
void launchFlush(VIO *vio, VDOAction *callback, VDOAction *errorHandler)
Packit Service b3514a
{
Packit Service b3514a
  VDOCompletion *completion = vioAsCompletion(vio);
Packit Service b3514a
  resetCompletion(completion);
Packit Service b3514a
  completion->callback     = callback;
Packit Service b3514a
  completion->errorHandler = handleFlushError;
Packit Service b3514a
  vio->errorHandler        = errorHandler;
Packit Service b3514a
  vio->operation           = VIO_FLUSH_BEFORE;
Packit Service b3514a
  vio->physical            = ZERO_BLOCK;
Packit Service b3514a
Packit Service b3514a
  PhysicalLayer *layer = completion->layer;
Packit Service b3514a
  if (layer->getWritePolicy(layer) == WRITE_POLICY_SYNC) {
Packit Service b3514a
    // XXX It is dangerous to be subtly dropping flushes possibly
Packit Service b3514a
    // needed for correctness in sync mode.
Packit Service b3514a
    finishCompletion(completion, VDO_SUCCESS);
Packit Service b3514a
    return;
Packit Service b3514a
  }
Packit Service b3514a
Packit Service b3514a
  layer->flush(vio);
Packit Service b3514a
}