Blame source/vdo/base/extent.c

Packit Service 310c69
/*
Packit Service 310c69
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 310c69
 *
Packit Service 310c69
 * This program is free software; you can redistribute it and/or
Packit Service 310c69
 * modify it under the terms of the GNU General Public License
Packit Service 310c69
 * as published by the Free Software Foundation; either version 2
Packit Service 310c69
 * of the License, or (at your option) any later version.
Packit Service 310c69
 * 
Packit Service 310c69
 * This program is distributed in the hope that it will be useful,
Packit Service 310c69
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 310c69
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 310c69
 * GNU General Public License for more details.
Packit Service 310c69
 * 
Packit Service 310c69
 * You should have received a copy of the GNU General Public License
Packit Service 310c69
 * along with this program; if not, write to the Free Software
Packit Service 310c69
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 310c69
 * 02110-1301, USA. 
Packit Service 310c69
 *
Packit Service 310c69
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/extent.c#3 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#include "extent.h"
Packit Service 310c69
Packit Service 310c69
#include "memoryAlloc.h"
Packit Service 310c69
Packit Service 310c69
#include "completion.h"
Packit Service 310c69
#include "constants.h"
Packit Service 310c69
#include "logger.h"
Packit Service 310c69
#include "physicalLayer.h"
Packit Service 310c69
#include "types.h"
Packit Service 310c69
#include "vdo.h"
Packit Service 310c69
#include "vioRead.h"
Packit Service 310c69
#include "vioWrite.h"
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int createExtent(PhysicalLayer  *layer,
Packit Service 310c69
                 VIOType         vioType,
Packit Service 310c69
                 VIOPriority     priority,
Packit Service 310c69
                 BlockCount      blockCount,
Packit Service 310c69
                 char           *data,
Packit Service 310c69
                 VDOExtent     **extentPtr)
Packit Service 310c69
{
Packit Service 310c69
  int result = ASSERT(isMetadataVIOType(vioType),
Packit Service 310c69
                      "createExtent() called for metadata");
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  VDOExtent *extent;
Packit Service 310c69
  result = ALLOCATE_EXTENDED(VDOExtent, blockCount, VIO *, __func__, &extent);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = initializeEnqueueableCompletion(&extent->completion,
Packit Service 310c69
                                           VDO_EXTENT_COMPLETION, layer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    FREE(extent);
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  for (; extent->count < blockCount; extent->count++) {
Packit Service 310c69
    result = layer->createMetadataVIO(layer, vioType, priority, extent, data,
Packit Service 310c69
                                      &extent->vios[extent->count]);
Packit Service 310c69
    if (result != VDO_SUCCESS) {
Packit Service 310c69
      freeExtent(&extent);
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
Packit Service 310c69
    data += VDO_BLOCK_SIZE;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  *extentPtr = extent;
Packit Service 310c69
  return VDO_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void freeExtent(VDOExtent **extentPtr)
Packit Service 310c69
{
Packit Service 310c69
  VDOExtent *extent = *extentPtr;
Packit Service 310c69
  if (extent == NULL) {
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  for (BlockCount i = 0; i < extent->count; i++) {
Packit Service 310c69
    freeVIO(&extent->vios[i]);
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  destroyEnqueueable(&extent->completion);
Packit Service 310c69
  FREE(extent);
Packit Service 310c69
  *extentPtr = NULL;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Launch a metadata extent.
Packit Service 310c69
 *
Packit Service 310c69
 * @param extent      The extent
Packit Service 310c69
 * @param startBlock  The absolute physical block at which the extent should
Packit Service 310c69
 *                    begin its I/O
Packit Service 310c69
 * @param count       The number of blocks to write
Packit Service 310c69
 * @param operation   The operation to perform on the extent
Packit Service 310c69
 **/
Packit Service 310c69
static void launchMetadataExtent(VDOExtent           *extent,
Packit Service 310c69
                                 PhysicalBlockNumber  startBlock,
Packit Service 310c69
                                 BlockCount           count,
Packit Service 310c69
                                 VIOOperation         operation)
Packit Service 310c69
{
Packit Service 310c69
  resetCompletion(&extent->completion);
Packit Service 310c69
  if (count > extent->count) {
Packit Service 310c69
    finishCompletion(&extent->completion, VDO_OUT_OF_RANGE);
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  extent->completeCount = extent->count - count;
Packit Service 310c69
  for (BlockCount i = 0; i < count; i++) {
Packit Service 310c69
    VIO *vio = extent->vios[i];
Packit Service 310c69
    vio->completion.callbackThreadID = extent->completion.callbackThreadID;
Packit Service 310c69
    launchMetadataVIO(vio, startBlock++, handleVIOCompletion,
Packit Service 310c69
                      handleVIOCompletion, operation);
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void readPartialMetadataExtent(VDOExtent           *extent,
Packit Service 310c69
                               PhysicalBlockNumber  startBlock,
Packit Service 310c69
                               BlockCount           count)
Packit Service 310c69
{
Packit Service 310c69
  launchMetadataExtent(extent, startBlock, count, VIO_READ);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void writePartialMetadataExtent(VDOExtent           *extent,
Packit Service 310c69
                                PhysicalBlockNumber  startBlock,
Packit Service 310c69
                                BlockCount           count)
Packit Service 310c69
{
Packit Service 310c69
  launchMetadataExtent(extent, startBlock, count, VIO_WRITE);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void handleVIOCompletion(VDOCompletion *completion)
Packit Service 310c69
{
Packit Service 310c69
  VDOExtent *extent = asVDOExtent(completion->parent);
Packit Service 310c69
  if (++extent->completeCount != extent->count) {
Packit Service 310c69
    setCompletionResult(extentAsCompletion(extent), completion->result);
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  finishCompletion(extentAsCompletion(extent), completion->result);
Packit Service 310c69
}