|
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 |
}
|