Blame source/vdo/base/vio.h

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