Blame source/vdo/kernel/bio.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/kernel/bio.h#6 $
Packit Service d40955
 */
Packit Service d40955
Packit Service d40955
#ifndef BIO_H
Packit Service d40955
#define BIO_H
Packit Service d40955
Packit Service d40955
#include <linux/bio.h>
Packit Service d40955
#include <linux/blkdev.h>
Packit Service d40955
#include <linux/version.h>
Packit Service d40955
Packit Service d40955
#include "kernelTypes.h"
Packit Service d40955
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)
Packit Service d40955
#define USE_BI_ITER 1
Packit Service d40955
#endif
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Copy the bio data to a char array.
Packit Service d40955
 *
Packit Service d40955
 * @param bio      The bio to copy the data from
Packit Service d40955
 * @param dataPtr  The local array to copy the data to
Packit Service d40955
 **/
Packit Service d40955
void bioCopyDataIn(BIO *bio, char *dataPtr);
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Copy a char array to the bio data.
Packit Service d40955
 *
Packit Service d40955
 * @param bio      The bio to copy the data to
Packit Service d40955
 * @param dataPtr  The local array to copy the data from
Packit Service d40955
 **/
Packit Service d40955
void bioCopyDataOut(BIO *bio, char *dataPtr);
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Set the bi_rw or equivalent field of a bio to a particular data
Packit Service d40955
 * operation. Intended to be called only by setBioOperationRead() etc.
Packit Service d40955
 *
Packit Service d40955
 * @param bio        The bio to modify
Packit Service d40955
 * @param operation  The operation to set it to
Packit Service d40955
 **/
Packit Service d40955
void setBioOperation(BIO *bio, unsigned int operation);
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void setBioOperationRead(BIO *bio)
Packit Service d40955
{
Packit Service d40955
  setBioOperation(bio, READ);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void setBioOperationWrite(BIO *bio)
Packit Service d40955
{
Packit Service d40955
  setBioOperation(bio, WRITE);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void clearBioOperationAndFlags(BIO *bio)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
Packit Service d40955
  bio->bi_opf = 0;
Packit Service d40955
#else
Packit Service d40955
  bio->bi_rw = 0;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void copyBioOperationAndFlags(BIO *to, BIO *from)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
Packit Service d40955
  to->bi_opf = from->bi_opf;
Packit Service d40955
#else
Packit Service d40955
  to->bi_rw = from->bi_rw;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void setBioOperationFlag(BIO *bio, unsigned int flag)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
Packit Service d40955
  bio->bi_opf |= flag;
Packit Service d40955
#else
Packit Service d40955
  bio->bi_rw |= flag;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void clearBioOperationFlag(BIO *bio, unsigned int flag)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
Packit Service d40955
  bio->bi_opf &= ~flag;
Packit Service d40955
#else
Packit Service d40955
  bio->bi_rw &= ~flag;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void setBioOperationFlagPreflush(BIO *bio)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
Packit Service d40955
  setBioOperationFlag(bio, REQ_PREFLUSH);
Packit Service d40955
#else
Packit Service d40955
  // Preflushes and empty flushes are not currently distinguished.
Packit Service d40955
  setBioOperation(bio, WRITE_FLUSH);
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void setBioOperationFlagSync(BIO *bio)
Packit Service d40955
{
Packit Service d40955
  setBioOperationFlag(bio, REQ_SYNC);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void clearBioOperationFlagSync(BIO *bio)
Packit Service d40955
{
Packit Service d40955
  clearBioOperationFlag(bio, REQ_SYNC);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void setBioOperationFlagFua(BIO *bio)
Packit Service d40955
{
Packit Service d40955
  setBioOperationFlag(bio, REQ_FUA);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline void clearBioOperationFlagFua(BIO *bio)
Packit Service d40955
{
Packit Service d40955
  clearBioOperationFlag(bio, REQ_FUA);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline bool isDiscardBio(BIO *bio)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
Packit Service d40955
  return (bio != NULL) && (bio_op(bio) == REQ_OP_DISCARD);
Packit Service d40955
#else
Packit Service d40955
  return (bio != NULL) && ((bio->bi_rw & REQ_DISCARD) != 0);
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline bool isFlushBio(BIO *bio)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
Packit Service d40955
  return (bio_op(bio) == REQ_OP_FLUSH) || ((bio->bi_opf & REQ_PREFLUSH) != 0);
Packit Service d40955
#else
Packit Service d40955
  return (bio->bi_rw & REQ_FLUSH) != 0;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline bool isFUABio(BIO *bio)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
Packit Service d40955
  return (bio->bi_opf & REQ_FUA) != 0;
Packit Service d40955
#else
Packit Service d40955
  return (bio->bi_rw & REQ_FUA) != 0;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline bool isReadBio(BIO *bio)
Packit Service d40955
{
Packit Service d40955
  return bio_data_dir(bio) == READ;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static inline bool isWriteBio(BIO *bio)
Packit Service d40955
{
Packit Service d40955
  return bio_data_dir(bio) == WRITE;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
Packit Service d40955
/**
Packit Service d40955
 * Get the error from the bio.
Packit Service d40955
 *
Packit Service d40955
 * @param bio  The bio
Packit Service d40955
 *
Packit Service d40955
 * @return the bio's error if any
Packit Service d40955
 **/
Packit Service d40955
static inline int getBioResult(BIO *bio)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
Packit Service d40955
  return blk_status_to_errno(bio->bi_status);
Packit Service d40955
#else
Packit Service d40955
  return bio->bi_error;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
#endif // newer than 4.4
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Set the block device for a bio.
Packit Service d40955
 *
Packit Service d40955
 * @param bio     The bio to modify
Packit Service d40955
 * @param device  The new block device for the bio
Packit Service d40955
 **/
Packit Service d40955
static inline void setBioBlockDevice(BIO *bio, struct block_device *device)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
Packit Service d40955
  bio_set_dev(bio, device);
Packit Service d40955
#else
Packit Service d40955
  bio->bi_bdev = device;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Get a bio's size.
Packit Service d40955
 *
Packit Service d40955
 * @param bio  The bio
Packit Service d40955
 *
Packit Service d40955
 * @return the bio's size
Packit Service d40955
 **/
Packit Service d40955
static inline unsigned int getBioSize(BIO *bio)
Packit Service d40955
{
Packit Service d40955
#ifdef USE_BI_ITER
Packit Service d40955
  return bio->bi_iter.bi_size;
Packit Service d40955
#else
Packit Service d40955
  return bio->bi_size;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Set the bio's sector.
Packit Service d40955
 *
Packit Service d40955
 * @param bio     The bio
Packit Service d40955
 * @param sector  The sector
Packit Service d40955
 **/
Packit Service d40955
static inline void setBioSector(BIO *bio, sector_t sector)
Packit Service d40955
{
Packit Service d40955
#ifdef USE_BI_ITER
Packit Service d40955
  bio->bi_iter.bi_sector = sector;
Packit Service d40955
#else
Packit Service d40955
  bio->bi_sector = sector;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Get the bio's sector.
Packit Service d40955
 *
Packit Service d40955
 * @param bio  The bio
Packit Service d40955
 *
Packit Service d40955
 * @return the sector
Packit Service d40955
 **/
Packit Service d40955
static inline sector_t getBioSector(BIO *bio)
Packit Service d40955
{
Packit Service d40955
#ifdef USE_BI_ITER
Packit Service d40955
  return bio->bi_iter.bi_sector;
Packit Service d40955
#else
Packit Service d40955
  return bio->bi_sector;
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Tell the kernel we've completed processing of this bio.
Packit Service d40955
 *
Packit Service d40955
 * @param bio    The bio to complete
Packit Service d40955
 * @param error  A system error code, or 0 for success
Packit Service d40955
 **/
Packit Service d40955
static inline void completeBio(BIO *bio, int error)
Packit Service d40955
{
Packit Service d40955
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
Packit Service d40955
  bio->bi_status = errno_to_blk_status(error);
Packit Service d40955
  bio_endio(bio);
Packit Service d40955
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
Packit Service d40955
  bio->bi_error = error;
Packit Service d40955
  bio_endio(bio);
Packit Service d40955
#else
Packit Service d40955
  bio_endio(bio, error);
Packit Service d40955
#endif
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Frees up a bio structure
Packit Service d40955
 *
Packit Service d40955
 * @param bio    The bio to free
Packit Service d40955
 * @param layer  The layer the bio was created in
Packit Service d40955
 **/
Packit Service d40955
void freeBio(BIO *bio, KernelLayer *layer);
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Count the statistics for the bios.  This is used for calls into VDO and
Packit Service d40955
 * for calls out of VDO.
Packit Service d40955
 *
Packit Service d40955
 * @param bioStats  Statistics structure to update
Packit Service d40955
 * @param bio       The bio
Packit Service d40955
 **/
Packit Service d40955
void countBios(AtomicBioStats *bioStats, BIO *bio);
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Reset a bio so it can be used again.
Packit Service d40955
 *
Packit Service d40955
 * @param bio    The bio to reset
Packit Service d40955
 * @param layer  The physical layer
Packit Service d40955
 **/
Packit Service d40955
void resetBio(BIO *bio, KernelLayer *layer);
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Check to see whether a bio's data are all zeroes.
Packit Service d40955
 *
Packit Service d40955
 * @param bio  The bio
Packit Service d40955
 *
Packit Service d40955
 * @return true if the bio's data are all zeroes
Packit Service d40955
 **/
Packit Service d40955
bool bioIsZeroData(BIO *bio);
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Set a bio's data to all zeroes.
Packit Service d40955
 *
Packit Service d40955
 * @param [in] bio  The bio
Packit Service d40955
 **/
Packit Service d40955
void bioZeroData(BIO *bio);
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Create a new bio structure for kernel buffer storage.
Packit Service d40955
 *
Packit Service d40955
 * @param [in]  layer   The physical layer
Packit Service d40955
 * @param [in]  data    The buffer (can be NULL)
Packit Service d40955
 * @param [out] bioPtr  A pointer to hold new bio
Packit Service d40955
 *
Packit Service d40955
 * @return VDO_SUCCESS or an error
Packit Service d40955
 **/
Packit Service d40955
int createBio(KernelLayer *layer, char *data, BIO **bioPtr);
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Prepare a BIO to issue a flush to the device below.
Packit Service d40955
 *
Packit Service d40955
 * @param bio            The flush BIO
Packit Service d40955
 * @param context        The context for the callback
Packit Service d40955
 * @param device         The device to flush
Packit Service d40955
 * @param endIOCallback  The function to call when the flush is complete
Packit Service d40955
 **/
Packit Service d40955
void prepareFlushBIO(BIO                 *bio,
Packit Service d40955
                     void                *context,
Packit Service d40955
                     struct block_device *device,
Packit Service d40955
                     bio_end_io_t        *endIOCallback);
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Perform IO with a bio, waiting for completion and returning its result.
Packit Service d40955
 * The bio must already have its sector, block device, and operation set.
Packit Service d40955
 *
Packit Service d40955
 * @param bio  The bio to do IO with
Packit Service d40955
 *
Packit Service d40955
 * @return The bio result
Packit Service d40955
 **/
Packit Service d40955
static inline int submitBioAndWait(BIO *bio)
Packit Service d40955
{
Packit Service d40955
  submit_bio_wait(bio);
Packit Service d40955
  return getBioResult(bio);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
#endif /* BIO_H */