|
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/vio.h#3 $
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#ifndef VIO_H
|
|
Packit Service |
d40955 |
#define VIO_H
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include <stdarg.h>
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "completion.h"
|
|
Packit Service |
d40955 |
#include "trace.h"
|
|
Packit Service |
d40955 |
#include "types.h"
|
|
Packit Service |
d40955 |
#include "vdo.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* A representation of a single block which may be passed between the VDO base
|
|
Packit Service |
d40955 |
* and the physical layer.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
struct vio {
|
|
Packit Service |
d40955 |
/* The completion for this VIO */
|
|
Packit Service |
d40955 |
VDOCompletion completion;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/* The functions to call when this VIO's operation is complete */
|
|
Packit Service |
d40955 |
VDOAction *callback;
|
|
Packit Service |
d40955 |
VDOAction *errorHandler;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/* The VDO handling this VIO */
|
|
Packit Service |
d40955 |
VDO *vdo;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/* The address on the underlying device of the block to be read/written */
|
|
Packit Service |
d40955 |
PhysicalBlockNumber physical;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/* The type of request this VIO is servicing */
|
|
Packit Service |
d40955 |
VIOOperation operation;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/* The queueing priority of the VIO operation */
|
|
Packit Service |
d40955 |
VIOPriority priority;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/* The VIO type is used for statistics and instrumentation. */
|
|
Packit Service |
d40955 |
VIOType type;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/* Used for logging and debugging */
|
|
Packit Service |
d40955 |
Trace *trace;
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Convert a generic VDOCompletion to a VIO.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param completion The completion to convert
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return The completion as a VIO
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline VIO *asVIO(VDOCompletion *completion)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
STATIC_ASSERT(offsetof(VIO, completion) == 0);
|
|
Packit Service |
d40955 |
assertCompletionType(completion->type, VIO_COMPLETION);
|
|
Packit Service |
d40955 |
return (VIO *) completion;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Convert a VIO to a generic completion.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to convert
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return The VIO as a completion
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline VDOCompletion *vioAsCompletion(VIO *vio)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return &vio->completion;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Create a VIO.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param [in] layer The physical layer
|
|
Packit Service |
d40955 |
* @param [in] vioType The type of VIO to create
|
|
Packit Service |
d40955 |
* @param [in] priority The relative priority to assign to the VIO
|
|
Packit Service |
d40955 |
* @param [in] parent The parent of the VIO
|
|
Packit Service |
d40955 |
* @param [in] data The buffer
|
|
Packit Service |
d40955 |
* @param [out] vioPtr A pointer to hold the new VIO
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline int createVIO(PhysicalLayer *layer,
|
|
Packit Service |
d40955 |
VIOType vioType,
|
|
Packit Service |
d40955 |
VIOPriority priority,
|
|
Packit Service |
d40955 |
void *parent,
|
|
Packit Service |
d40955 |
char *data,
|
|
Packit Service |
d40955 |
VIO **vioPtr)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return layer->createMetadataVIO(layer, vioType, priority, parent, data,
|
|
Packit Service |
d40955 |
vioPtr);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Destroy a vio. The pointer to the VIO will be nulled out.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vioPtr A pointer to the VIO to destroy
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void freeVIO(VIO **vioPtr);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Initialize a VIO.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to initialize
|
|
Packit Service |
d40955 |
* @param type The VIO type
|
|
Packit Service |
d40955 |
* @param priority The relative priority of the VIO
|
|
Packit Service |
d40955 |
* @param parent The parent (the extent completion) to assign to the VIO
|
|
Packit Service |
d40955 |
* completion
|
|
Packit Service |
d40955 |
* @param vdo The VDO for this VIO
|
|
Packit Service |
d40955 |
* @param layer The layer for this VIO
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void initializeVIO(VIO *vio,
|
|
Packit Service |
d40955 |
VIOType type,
|
|
Packit Service |
d40955 |
VIOPriority priority,
|
|
Packit Service |
d40955 |
VDOCompletion *parent,
|
|
Packit Service |
d40955 |
VDO *vdo,
|
|
Packit Service |
d40955 |
PhysicalLayer *layer);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* The very last step in processing a VIO. Set the VIO's completion's callback
|
|
Packit Service |
d40955 |
* and error handler from the fields set in the VIO itself on launch and then
|
|
Packit Service |
d40955 |
* actually complete the VIO's completion.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param completion The VIO
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void vioDoneCallback(VDOCompletion *completion);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Get the name of a VIO's operation.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return The name of the VIO's operation (read, write, or read-modify-write)
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
const char *getVIOReadWriteFlavor(const VIO *vio);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Update per-VIO error stats and log the error.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO which got an error
|
|
Packit Service |
d40955 |
* @param format The format of the message to log (a printf style format)
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void updateVIOErrorStats(VIO *vio, const char *format, ...)
|
|
Packit Service |
d40955 |
__attribute__((format(printf, 2, 3)));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Add a trace record for the current source location.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO structure to be updated
|
|
Packit Service |
d40955 |
* @param location The source-location descriptor to be recorded
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void vioAddTraceRecord(VIO *vio, TraceLocation location)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
if (unlikely(vio->trace != NULL)) {
|
|
Packit Service |
d40955 |
addTraceRecord(vio->trace, location);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a VIO is servicing an external data request.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to check
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool isDataVIO(VIO *vio)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return isDataVIOType(vio->type);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a VIO is for compressed block writes
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to check
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool isCompressedWriteVIO(VIO *vio)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return isCompressedWriteVIOType(vio->type);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a VIO is for metadata
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to check
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool isMetadataVIO(VIO *vio)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return isMetadataVIOType(vio->type);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a VIO is a read.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return true if the VIO is a read
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool isReadVIO(const VIO *vio)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return ((vio->operation & VIO_READ_WRITE_MASK) == VIO_READ);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a VIO is a read-modify-write.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return true if the VIO is a read-modify-write
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool isReadModifyWriteVIO(const VIO *vio)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return ((vio->operation & VIO_READ_WRITE_MASK) == VIO_READ_MODIFY_WRITE);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a VIO is a write.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return true if the VIO is a write
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool isWriteVIO(const VIO *vio)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return ((vio->operation & VIO_READ_WRITE_MASK) == VIO_WRITE);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a VIO requires a flush before doing its I/O.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return true if the VIO requires a flush before
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool vioRequiresFlushBefore(const VIO *vio)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return ((vio->operation & VIO_FLUSH_BEFORE) == VIO_FLUSH_BEFORE);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a VIO requires a flush after doing its I/O.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return true if the VIO requires a flush after
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool vioRequiresFlushAfter(const VIO *vio)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return ((vio->operation & VIO_FLUSH_AFTER) == VIO_FLUSH_AFTER);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Launch a metadata VIO.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to launch
|
|
Packit Service |
d40955 |
* @param physical The physical block number to read or write
|
|
Packit Service |
d40955 |
* @param callback The function to call when the VIO completes its I/O
|
|
Packit Service |
d40955 |
* @param errorHandler The handler for write errors
|
|
Packit Service |
d40955 |
* @param operation The operation to perform (read or write)
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void launchMetadataVIO(VIO *vio,
|
|
Packit Service |
d40955 |
PhysicalBlockNumber physical,
|
|
Packit Service |
d40955 |
VDOAction *callback,
|
|
Packit Service |
d40955 |
VDOAction *errorHandler,
|
|
Packit Service |
d40955 |
VIOOperation operation);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Launch a metadata read VIO.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to launch
|
|
Packit Service |
d40955 |
* @param physical The physical block number to read
|
|
Packit Service |
d40955 |
* @param callback The function to call when the VIO completes its read
|
|
Packit Service |
d40955 |
* @param errorHandler The handler for write errors
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void launchReadMetadataVIO(VIO *vio,
|
|
Packit Service |
d40955 |
PhysicalBlockNumber physical,
|
|
Packit Service |
d40955 |
VDOAction *callback,
|
|
Packit Service |
d40955 |
VDOAction *errorHandler)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
launchMetadataVIO(vio, physical, callback, errorHandler, VIO_READ);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Launch a metadata write VIO.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to launch
|
|
Packit Service |
d40955 |
* @param physical The physical block number to write
|
|
Packit Service |
d40955 |
* @param callback The function to call when the VIO completes its write
|
|
Packit Service |
d40955 |
* @param errorHandler The handler for write errors
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void launchWriteMetadataVIO(VIO *vio,
|
|
Packit Service |
d40955 |
PhysicalBlockNumber physical,
|
|
Packit Service |
d40955 |
VDOAction *callback,
|
|
Packit Service |
d40955 |
VDOAction *errorHandler)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
launchMetadataVIO(vio, physical, callback, errorHandler, VIO_WRITE);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Launch a metadata write VIO optionally flushing the layer before and/or
|
|
Packit Service |
d40955 |
* after the write operation.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to launch
|
|
Packit Service |
d40955 |
* @param physical The physical block number to write
|
|
Packit Service |
d40955 |
* @param callback The function to call when the VIO completes its
|
|
Packit Service |
d40955 |
* operation
|
|
Packit Service |
d40955 |
* @param errorHandler The handler for flush or write errors
|
|
Packit Service |
d40955 |
* @param flushBefore Whether or not to flush before writing
|
|
Packit Service |
d40955 |
* @param flushAfter Whether or not to flush after writing
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline
|
|
Packit Service |
d40955 |
void launchWriteMetadataVIOWithFlush(VIO *vio,
|
|
Packit Service |
d40955 |
PhysicalBlockNumber physical,
|
|
Packit Service |
d40955 |
VDOAction *callback,
|
|
Packit Service |
d40955 |
VDOAction *errorHandler,
|
|
Packit Service |
d40955 |
bool flushBefore,
|
|
Packit Service |
d40955 |
bool flushAfter)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
launchMetadataVIO(vio, physical, callback, errorHandler,
|
|
Packit Service |
d40955 |
(VIO_WRITE
|
|
Packit Service |
d40955 |
| (flushBefore ? VIO_FLUSH_BEFORE : 0)
|
|
Packit Service |
d40955 |
| (flushAfter ? VIO_FLUSH_AFTER : 0)));
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Issue a flush to the layer. If the layer does not require flushing, this
|
|
Packit Service |
d40955 |
* method will immediately finish the VIO with which it was called. Care must
|
|
Packit Service |
d40955 |
* be taken to avoid introducing a stack overflow in that case.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param vio The VIO to notify when the flush is complete
|
|
Packit Service |
d40955 |
* @param callback The function to call when the flush is complete
|
|
Packit Service |
d40955 |
* @param errorHandler The handler for flush errors
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void launchFlush(VIO *vio, VDOAction *callback, VDOAction *errorHandler);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#endif // VIO_H
|