|
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/base/vioRead.c#1 $
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "vioRead.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "logger.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "blockMap.h"
|
|
Packit Service |
d40955 |
#include "dataVIO.h"
|
|
Packit Service |
d40955 |
#include "vdoInternal.h"
|
|
Packit Service |
d40955 |
#include "vioWrite.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Do the modify-write part of a read-modify-write cycle. This callback is
|
|
Packit Service |
d40955 |
* registered in readBlock().
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param completion The DataVIO which has just finished its read
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static void modifyForPartialWrite(VDOCompletion *completion)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
DataVIO *dataVIO = asDataVIO(completion);
|
|
Packit Service |
d40955 |
assertInLogicalZone(dataVIO);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
if (completion->result != VDO_SUCCESS) {
|
|
Packit Service |
d40955 |
completeDataVIO(completion);
|
|
Packit Service |
d40955 |
return;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
completion->layer->applyPartialWrite(dataVIO);
|
|
Packit Service |
d40955 |
VIO *vio = dataVIOAsVIO(dataVIO);
|
|
Packit Service |
d40955 |
vio->operation = VIO_WRITE | (vio->operation & ~VIO_READ_WRITE_MASK);
|
|
Packit Service |
d40955 |
dataVIO->isPartialWrite = true;
|
|
Packit Service |
d40955 |
launchWriteDataVIO(dataVIO);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Read a block asynchronously. This is the callback registered in
|
|
Packit Service |
d40955 |
* readBlockMapping().
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param completion The DataVIO to read
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static void readBlock(VDOCompletion *completion)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
if (completion->result != VDO_SUCCESS) {
|
|
Packit Service |
d40955 |
completeDataVIO(completion);
|
|
Packit Service |
d40955 |
return;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
DataVIO *dataVIO = asDataVIO(completion);
|
|
Packit Service |
d40955 |
VIO *vio = asVIO(completion);
|
|
Packit Service |
d40955 |
completion->callback
|
|
Packit Service |
d40955 |
= (isReadVIO(vio) ? completeDataVIO : modifyForPartialWrite);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
if (dataVIO->mapped.pbn == ZERO_BLOCK) {
|
|
Packit Service |
d40955 |
completion->layer->zeroDataVIO(dataVIO);
|
|
Packit Service |
d40955 |
invokeCallback(completion);
|
|
Packit Service |
d40955 |
return;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
vio->physical = dataVIO->mapped.pbn;
|
|
Packit Service |
d40955 |
dataVIO->lastAsyncOperation = READ_DATA;
|
|
Packit Service |
d40955 |
completion->layer->readData(dataVIO);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Read the DataVIO's mapping from the block map. This callback is registered
|
|
Packit Service |
d40955 |
* in launchReadDataVIO().
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param completion The DataVIO to be read
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static void readBlockMapping(VDOCompletion *completion)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
if (completion->result != VDO_SUCCESS) {
|
|
Packit Service |
d40955 |
completeDataVIO(completion);
|
|
Packit Service |
d40955 |
return;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
DataVIO *dataVIO = asDataVIO(completion);
|
|
Packit Service |
d40955 |
assertInLogicalZone(dataVIO);
|
|
Packit Service |
d40955 |
setLogicalCallback(dataVIO, readBlock, THIS_LOCATION("$F;cb=readBlock"));
|
|
Packit Service |
d40955 |
dataVIO->lastAsyncOperation = GET_MAPPED_BLOCK;
|
|
Packit Service |
d40955 |
getMappedBlockAsync(dataVIO);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**********************************************************************/
|
|
Packit Service |
d40955 |
void launchReadDataVIO(DataVIO *dataVIO)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
assertInLogicalZone(dataVIO);
|
|
Packit Service |
d40955 |
dataVIO->lastAsyncOperation = FIND_BLOCK_MAP_SLOT;
|
|
Packit Service |
d40955 |
// Go find the block map slot for the LBN mapping.
|
|
Packit Service |
d40955 |
findBlockMapSlotAsync(dataVIO, readBlockMapping,
|
|
Packit Service |
d40955 |
getLogicalZoneThreadID(dataVIO->logical.zone));
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Release the logical block lock which a read DataVIO obtained now that it
|
|
Packit Service |
d40955 |
* is done.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param completion The DataVIO
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static void releaseLogicalLock(VDOCompletion *completion)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
DataVIO *dataVIO = asDataVIO(completion);
|
|
Packit Service |
d40955 |
assertInLogicalZone(dataVIO);
|
|
Packit Service |
d40955 |
releaseLogicalBlockLock(dataVIO);
|
|
Packit Service |
d40955 |
vioDoneCallback(completion);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Clean up a DataVIO which has finished processing a read.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param dataVIO The DataVIO to clean up
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void cleanupReadDataVIO(DataVIO *dataVIO)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
launchLogicalCallback(dataVIO, releaseLogicalLock,
|
|
Packit Service |
d40955 |
THIS_LOCATION("$F;cb=releaseLL"));
|
|
Packit Service |
d40955 |
}
|