|
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/kernelLayer.h#18 $
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#ifndef KERNELLAYER_H
|
|
Packit Service |
d40955 |
#define KERNELLAYER_H
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include <linux/device-mapper.h>
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "atomic.h"
|
|
Packit Service |
d40955 |
#include "constants.h"
|
|
Packit Service |
d40955 |
#include "flush.h"
|
|
Packit Service |
d40955 |
#include "intMap.h"
|
|
Packit Service |
d40955 |
#include "physicalLayer.h"
|
|
Packit Service |
d40955 |
#include "ringNode.h"
|
|
Packit Service |
d40955 |
#include "volumeGeometry.h"
|
|
Packit Service |
d40955 |
#include "waitQueue.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "batchProcessor.h"
|
|
Packit Service |
d40955 |
#include "bufferPool.h"
|
|
Packit Service |
d40955 |
#include "deadlockQueue.h"
|
|
Packit Service |
d40955 |
#include "deviceConfig.h"
|
|
Packit Service |
d40955 |
#include "histogram.h"
|
|
Packit Service |
d40955 |
#include "kernelStatistics.h"
|
|
Packit Service |
d40955 |
#include "kernelTypes.h"
|
|
Packit Service |
d40955 |
#include "kernelVDO.h"
|
|
Packit Service |
d40955 |
#include "ktrace.h"
|
|
Packit Service |
d40955 |
#include "limiter.h"
|
|
Packit Service |
d40955 |
#include "statistics.h"
|
|
Packit Service |
d40955 |
#include "workQueue.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
enum {
|
|
Packit Service |
d40955 |
VDO_SECTORS_PER_BLOCK = (VDO_BLOCK_SIZE >> SECTOR_SHIFT)
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
typedef enum {
|
|
Packit Service |
d40955 |
LAYER_SIMPLE_THINGS_INITIALIZED,
|
|
Packit Service |
d40955 |
LAYER_BUFFER_POOLS_INITIALIZED,
|
|
Packit Service |
d40955 |
LAYER_REQUEST_QUEUE_INITIALIZED,
|
|
Packit Service |
d40955 |
LAYER_CPU_QUEUE_INITIALIZED,
|
|
Packit Service |
d40955 |
LAYER_BIO_ACK_QUEUE_INITIALIZED,
|
|
Packit Service |
d40955 |
LAYER_BIO_DATA_INITIALIZED,
|
|
Packit Service |
d40955 |
LAYER_STARTING,
|
|
Packit Service |
d40955 |
LAYER_RUNNING,
|
|
Packit Service |
d40955 |
LAYER_SUSPENDED,
|
|
Packit Service |
d40955 |
LAYER_STOPPING,
|
|
Packit Service |
d40955 |
LAYER_STOPPED,
|
|
Packit Service |
d40955 |
LAYER_RESUMING,
|
|
Packit Service |
d40955 |
} KernelLayerState;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/* Keep BIO statistics atomically */
|
|
Packit Service |
d40955 |
struct atomicBioStats {
|
|
Packit Service |
d40955 |
atomic64_t read; // Number of not REQ_WRITE bios
|
|
Packit Service |
d40955 |
atomic64_t write; // Number of REQ_WRITE bios
|
|
Packit Service |
d40955 |
atomic64_t discard; // Number of REQ_DISCARD bios
|
|
Packit Service |
d40955 |
atomic64_t flush; // Number of REQ_FLUSH bios
|
|
Packit Service |
d40955 |
atomic64_t fua; // Number of REQ_FUA bios
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
// Data managing the reporting of Albireo timeouts
|
|
Packit Service |
d40955 |
typedef struct periodicEventReporter {
|
|
Packit Service |
d40955 |
uint64_t lastReportedValue;
|
|
Packit Service |
d40955 |
const char *format;
|
|
Packit Service |
d40955 |
atomic64_t value;
|
|
Packit Service |
d40955 |
Jiffies reportingInterval; // jiffies
|
|
Packit Service |
d40955 |
/*
|
|
Packit Service |
d40955 |
* Just an approximation. If nonzero, then either the work item has
|
|
Packit Service |
d40955 |
* been queued to run, or some other thread currently has
|
|
Packit Service |
d40955 |
* responsibility for enqueueing it, or the reporter function is
|
|
Packit Service |
d40955 |
* running but hasn't looked at the current value yet.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* If this is set, don't set the timer again, because we don't want
|
|
Packit Service |
d40955 |
* the work item queued twice. Use an atomic xchg or cmpxchg to
|
|
Packit Service |
d40955 |
* test-and-set it, and an atomic store to clear it.
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
atomic_t workItemQueued;
|
|
Packit Service |
d40955 |
KvdoWorkItem workItem;
|
|
Packit Service |
d40955 |
KernelLayer *layer;
|
|
Packit Service |
d40955 |
} PeriodicEventReporter;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
static inline uint64_t getEventCount(PeriodicEventReporter *reporter)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return atomic64_read(&reporter->value);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* The VDO representation of the target device
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
struct kernelLayer {
|
|
Packit Service |
d40955 |
PhysicalLayer common;
|
|
Packit Service |
d40955 |
// Layer specific info
|
|
Packit Service |
d40955 |
DeviceConfig *deviceConfig;
|
|
Packit Service |
d40955 |
/** A ring of all DeviceConfigs referencing this layer */
|
|
Packit Service |
d40955 |
RingNode deviceConfigRing;
|
|
Packit Service |
d40955 |
char threadNamePrefix[MAX_QUEUE_NAME_LEN];
|
|
Packit Service |
d40955 |
struct kobject kobj;
|
|
Packit Service |
d40955 |
struct kobject wqDirectory;
|
|
Packit Service |
d40955 |
struct kobject statsDirectory;
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* A counter value to attach to thread names and log messages to
|
|
Packit Service |
d40955 |
* identify the individual device.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
unsigned int instance;
|
|
Packit Service |
d40955 |
/** Contains the current KernelLayerState, which rarely changes */
|
|
Packit Service |
d40955 |
Atomic32 state;
|
|
Packit Service |
d40955 |
bool noFlushSuspend;
|
|
Packit Service |
d40955 |
bool allocationsAllowed;
|
|
Packit Service |
d40955 |
AtomicBool processingMessage;
|
|
Packit Service |
d40955 |
/** Limit the number of requests that are being processed. */
|
|
Packit Service |
d40955 |
Limiter requestLimiter;
|
|
Packit Service |
d40955 |
Limiter discardLimiter;
|
|
Packit Service |
d40955 |
KVDO kvdo;
|
|
Packit Service |
d40955 |
/** Incoming bios we've had to buffer to avoid deadlock. */
|
|
Packit Service |
d40955 |
DeadlockQueue deadlockQueue;
|
|
Packit Service |
d40955 |
// for REQ_FLUSH processing
|
|
Packit Service |
d40955 |
struct bio_list waitingFlushes;
|
|
Packit Service |
d40955 |
KVDOFlush *spareKVDOFlush;
|
|
Packit Service |
d40955 |
spinlock_t flushLock;
|
|
Packit Service |
d40955 |
Jiffies flushArrivalTime;
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Bio submission manager used for sending bios to the storage
|
|
Packit Service |
d40955 |
* device.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
IOSubmitter *ioSubmitter;
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Work queue (possibly with multiple threads) for miscellaneous
|
|
Packit Service |
d40955 |
* CPU-intensive, non-blocking work.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
KvdoWorkQueue *cpuQueue;
|
|
Packit Service |
d40955 |
/** N blobs of context data for LZ4 code, one per CPU thread. */
|
|
Packit Service |
d40955 |
char **compressionContext;
|
|
Packit Service |
d40955 |
Atomic32 compressionContextIndex;
|
|
Packit Service |
d40955 |
/** Optional work queue for calling bio_endio. */
|
|
Packit Service |
d40955 |
KvdoWorkQueue *bioAckQueue;
|
|
Packit Service |
d40955 |
/** Underlying block device info. */
|
|
Packit Service |
d40955 |
uint64_t startingSectorOffset;
|
|
Packit Service |
d40955 |
VolumeGeometry geometry;
|
|
Packit Service |
d40955 |
// Memory allocation
|
|
Packit Service |
d40955 |
BufferPool *dataKVIOPool;
|
|
Packit Service |
d40955 |
struct bio_set *bioset;
|
|
Packit Service |
d40955 |
// Albireo specific info
|
|
Packit Service |
d40955 |
DedupeIndex *dedupeIndex;
|
|
Packit Service |
d40955 |
// Statistics
|
|
Packit Service |
d40955 |
atomic64_t biosSubmitted;
|
|
Packit Service |
d40955 |
atomic64_t biosCompleted;
|
|
Packit Service |
d40955 |
atomic64_t dedupeContextBusy;
|
|
Packit Service |
d40955 |
atomic64_t flushOut;
|
|
Packit Service |
d40955 |
AtomicBioStats biosIn;
|
|
Packit Service |
d40955 |
AtomicBioStats biosInPartial;
|
|
Packit Service |
d40955 |
AtomicBioStats biosOut;
|
|
Packit Service |
d40955 |
AtomicBioStats biosOutCompleted;
|
|
Packit Service |
d40955 |
AtomicBioStats biosAcknowledged;
|
|
Packit Service |
d40955 |
AtomicBioStats biosAcknowledgedPartial;
|
|
Packit Service |
d40955 |
AtomicBioStats biosMeta;
|
|
Packit Service |
d40955 |
AtomicBioStats biosMetaCompleted;
|
|
Packit Service |
d40955 |
AtomicBioStats biosJournal;
|
|
Packit Service |
d40955 |
AtomicBioStats biosPageCache;
|
|
Packit Service |
d40955 |
AtomicBioStats biosJournalCompleted;
|
|
Packit Service |
d40955 |
AtomicBioStats biosPageCacheCompleted;
|
|
Packit Service |
d40955 |
// for reporting Albireo timeouts
|
|
Packit Service |
d40955 |
PeriodicEventReporter albireoTimeoutReporter;
|
|
Packit Service |
d40955 |
// Debugging
|
|
Packit Service |
d40955 |
/* Whether to dump VDO state on shutdown */
|
|
Packit Service |
d40955 |
bool dumpOnShutdown;
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Whether we should collect tracing info. (Actually, this controls
|
|
Packit Service |
d40955 |
* allocations; non-null record pointers cause recording.)
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
bool vioTraceRecording;
|
|
Packit Service |
d40955 |
SampleCounter traceSampleCounter;
|
|
Packit Service |
d40955 |
/* Should we log tracing info? */
|
|
Packit Service |
d40955 |
bool traceLogging;
|
|
Packit Service |
d40955 |
/* Storage for trace data. */
|
|
Packit Service |
d40955 |
BufferPool *traceBufferPool;
|
|
Packit Service |
d40955 |
/* Private storage for procfs. */
|
|
Packit Service |
d40955 |
void *procfsPrivate;
|
|
Packit Service |
d40955 |
/* For returning batches of DataKVIOs to their pool */
|
|
Packit Service |
d40955 |
BatchProcessor *dataKVIOReleaser;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
// Administrative operations
|
|
Packit Service |
d40955 |
/* The object used to wait for administrative operations to complete */
|
|
Packit Service |
d40955 |
struct completion callbackSync;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
// Statistics reporting
|
|
Packit Service |
d40955 |
/* Protects the *statsStorage structs */
|
|
Packit Service |
d40955 |
struct mutex statsMutex;
|
|
Packit Service |
d40955 |
/* Used when shutting down the sysfs statistics */
|
|
Packit Service |
d40955 |
struct completion statsShutdown;;
|
|
Packit Service |
d40955 |
/* true if sysfs statistics directory is set up */
|
|
Packit Service |
d40955 |
bool statsAdded;
|
|
Packit Service |
d40955 |
/* Used to gather statistics without allocating memory */
|
|
Packit Service |
d40955 |
VDOStatistics vdoStatsStorage;
|
|
Packit Service |
d40955 |
KernelStatistics kernelStatsStorage;
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
typedef enum bioQAction {
|
|
Packit Service |
d40955 |
BIO_Q_ACTION_COMPRESSED_DATA,
|
|
Packit Service |
d40955 |
BIO_Q_ACTION_DATA,
|
|
Packit Service |
d40955 |
BIO_Q_ACTION_FLUSH,
|
|
Packit Service |
d40955 |
BIO_Q_ACTION_HIGH,
|
|
Packit Service |
d40955 |
BIO_Q_ACTION_METADATA,
|
|
Packit Service |
d40955 |
BIO_Q_ACTION_READCACHE,
|
|
Packit Service |
d40955 |
BIO_Q_ACTION_VERIFY
|
|
Packit Service |
d40955 |
} BioQAction;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
typedef enum cpuQAction {
|
|
Packit Service |
d40955 |
CPU_Q_ACTION_COMPLETE_KVIO,
|
|
Packit Service |
d40955 |
CPU_Q_ACTION_COMPRESS_BLOCK,
|
|
Packit Service |
d40955 |
CPU_Q_ACTION_EVENT_REPORTER,
|
|
Packit Service |
d40955 |
CPU_Q_ACTION_HASH_BLOCK,
|
|
Packit Service |
d40955 |
} CPUQAction;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
typedef enum bioAckQAction {
|
|
Packit Service |
d40955 |
BIO_ACK_Q_ACTION_ACK,
|
|
Packit Service |
d40955 |
} BioAckQAction;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
typedef void (*DedupeShutdownCallbackFunction)(KernelLayer *layer);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/*
|
|
Packit Service |
d40955 |
* Wrapper for the Enqueueable object, to associate it with a kernel
|
|
Packit Service |
d40955 |
* layer work item.
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
typedef struct kvdoEnqueueable {
|
|
Packit Service |
d40955 |
KvdoWorkItem workItem;
|
|
Packit Service |
d40955 |
Enqueueable enqueueable;
|
|
Packit Service |
d40955 |
} KvdoEnqueueable;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Implements LayerFilter.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
bool layerIsNamed(KernelLayer *layer, void *context)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Creates a kernel specific physical layer to be used by VDO
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param startingSector The sector offset of our table entry in the
|
|
Packit Service |
d40955 |
* DM device
|
|
Packit Service |
d40955 |
* @param instance Device instantiation counter
|
|
Packit Service |
d40955 |
* @param parentKobject The parent sysfs node
|
|
Packit Service |
d40955 |
* @param config The device configuration
|
|
Packit Service |
d40955 |
* @param threadConfigPointer Where to store the new threadConfig handle
|
|
Packit Service |
d40955 |
* @param reason The reason for any failure during this call
|
|
Packit Service |
d40955 |
* @param layerPtr A pointer to hold the created layer
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int makeKernelLayer(uint64_t startingSector,
|
|
Packit Service |
d40955 |
unsigned int instance,
|
|
Packit Service |
d40955 |
DeviceConfig *config,
|
|
Packit Service |
d40955 |
struct kobject *parentKobject,
|
|
Packit Service |
d40955 |
ThreadConfig **threadConfigPointer,
|
|
Packit Service |
d40955 |
char **reason,
|
|
Packit Service |
d40955 |
KernelLayer **layerPtr)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Prepare to modify a kernel layer.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The layer to modify
|
|
Packit Service |
d40955 |
* @param config The new device configuration
|
|
Packit Service |
d40955 |
* @param errorPtr A pointer to store the reason for any failure
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int prepareToModifyKernelLayer(KernelLayer *layer,
|
|
Packit Service |
d40955 |
DeviceConfig *config,
|
|
Packit Service |
d40955 |
char **errorPtr)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Modify a kernel physical layer.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The layer to modify
|
|
Packit Service |
d40955 |
* @param config The new device configuration
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int modifyKernelLayer(KernelLayer *layer,
|
|
Packit Service |
d40955 |
DeviceConfig *config)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Free a kernel physical layer.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The layer, which must have been created by
|
|
Packit Service |
d40955 |
* makeKernelLayer
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void freeKernelLayer(KernelLayer *layer);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Make and configure a kernel layer. This method does not alter the VDO state
|
|
Packit Service |
d40955 |
* on disk. It should be run from the VDO constructor for devices which have
|
|
Packit Service |
d40955 |
* not been started.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer
|
|
Packit Service |
d40955 |
* @param loadConfig Load-time parameters for the VDO
|
|
Packit Service |
d40955 |
* @param reason The reason for any failure during this call
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @note redundant starts are silently ignored
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int preloadKernelLayer(KernelLayer *layer,
|
|
Packit Service |
d40955 |
const VDOLoadConfig *loadConfig,
|
|
Packit Service |
d40955 |
char **reason);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Start the kernel layer. This method finishes bringing a VDO online now that
|
|
Packit Service |
d40955 |
* a table is being resumed for the first time.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer
|
|
Packit Service |
d40955 |
* @param reason The reason for any failure during this call
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int startKernelLayer(KernelLayer *layer, char **reason);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Stop the kernel layer.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void stopKernelLayer(KernelLayer *layer);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Suspend the kernel layer.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int suspendKernelLayer(KernelLayer *layer);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Resume the kernel layer.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int resumeKernelLayer(KernelLayer *layer);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Get the kernel layer state.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return the instantaneously correct kernel layer state
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline KernelLayerState getKernelLayerState(const KernelLayer *layer)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return atomicLoad32(&layer->state);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Function call to begin processing a bio passed in from the block layer
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The physical layer
|
|
Packit Service |
d40955 |
* @param bio The bio from the block layer
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return value to return from the VDO map function. Either an error code
|
|
Packit Service |
d40955 |
* or DM_MAPIO_REMAPPED or DM_MAPPED_SUBMITTED (see vdoMapBio for
|
|
Packit Service |
d40955 |
* details).
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int kvdoMapBio(KernelLayer *layer, BIO *bio);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Convert a generic PhysicalLayer to a kernelLayer.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The PhysicalLayer to convert
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return The PhysicalLayer as a KernelLayer
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline KernelLayer *asKernelLayer(PhysicalLayer *layer)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return container_of(layer, KernelLayer, common);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Convert a block number (or count) to a (512-byte-)sector number.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* The argument type is sector_t to force conversion to the type we
|
|
Packit Service |
d40955 |
* want, although the actual values passed are of various integral
|
|
Packit Service |
d40955 |
* types. It's just too easy to forget and do the multiplication
|
|
Packit Service |
d40955 |
* without casting, resulting in 32-bit arithmetic that accidentally
|
|
Packit Service |
d40955 |
* produces wrong results in devices over 2TB (2**32 sectors).
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param [in] layer the physical layer
|
|
Packit Service |
d40955 |
* @param [in] blockNumber the block number/count
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return the sector number/count
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline sector_t blockToSector(KernelLayer *layer, sector_t blockNumber)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return (blockNumber * VDO_SECTORS_PER_BLOCK);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Convert a sector number (or count) to a block number. Does not
|
|
Packit Service |
d40955 |
* check to make sure the sector number is an integral number of
|
|
Packit Service |
d40955 |
* blocks.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param [in] layer the physical layer
|
|
Packit Service |
d40955 |
* @param [in] sectorNumber the sector number/count
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return the block number/count
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline sector_t sectorToBlock(KernelLayer *layer, sector_t sectorNumber)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return (sectorNumber / VDO_SECTORS_PER_BLOCK);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Convert a sector number to an offset within a block.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param [in] layer the physical layer
|
|
Packit Service |
d40955 |
* @param [in] sectorNumber the sector number
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return the offset within the block
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline BlockSize sectorToBlockOffset(KernelLayer *layer,
|
|
Packit Service |
d40955 |
sector_t sectorNumber)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
unsigned int sectorsPerBlockMask = VDO_SECTORS_PER_BLOCK - 1;
|
|
Packit Service |
d40955 |
return to_bytes(sectorNumber & sectorsPerBlockMask);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Get the block device object currently underlying a kernel layer.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer in question
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return The block device object under the layer
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
struct block_device *getKernelLayerBdev(const KernelLayer *layer)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Set the layer's active config.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer in question
|
|
Packit Service |
d40955 |
* @param config The config in question
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void setKernelLayerActiveConfig(KernelLayer *layer,
|
|
Packit Service |
d40955 |
DeviceConfig *config)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
layer->deviceConfig = config;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Given an error code, return a value we can return to the OS. The
|
|
Packit Service |
d40955 |
* input error code may be a system-generated value (such as -EIO), an
|
|
Packit Service |
d40955 |
* errno macro used in our code (such as EIO), or a UDS or VDO status
|
|
Packit Service |
d40955 |
* code; the result must be something the rest of the OS can consume
|
|
Packit Service |
d40955 |
* (negative errno values such as -EIO, in the case of the kernel).
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param error the error code to convert
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return a system error code value
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int mapToSystemError(int error);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Record and eventually report that some number of dedupe requests
|
|
Packit Service |
d40955 |
* reached their expiration time without getting an answer, so we
|
|
Packit Service |
d40955 |
* timed out on them.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* This is called in a timer context, so it shouldn't do the reporting
|
|
Packit Service |
d40955 |
* directly.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer for the device
|
|
Packit Service |
d40955 |
* @param expiredCount The number of expired requests we timed out on
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void kvdoReportDedupeTimeout(KernelLayer *layer, unsigned int expiredCount);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Wait until there are no requests in progress.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer for the device
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void waitForNoRequestsActive(KernelLayer *layer);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Enqueues an item on our internal "cpu queues". Since there is more than
|
|
Packit Service |
d40955 |
* one, we rotate through them in hopes of creating some general balance.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer
|
|
Packit Service |
d40955 |
* @param item The work item to enqueue
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
static inline void enqueueCPUWorkQueue(KernelLayer *layer, KvdoWorkItem *item)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
enqueueWorkQueue(layer->cpuQueue, item);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Adjust parameters to prepare to use a larger physical space.
|
|
Packit Service |
d40955 |
* The size must be larger than the current size.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer the kernel layer
|
|
Packit Service |
d40955 |
* @param physicalCount the new physical size in blocks
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
int prepareToResizePhysical(KernelLayer *layer, BlockCount physicalCount);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Adjusts parameters to reflect resizing the underlying device.
|
|
Packit Service |
d40955 |
* The size must be larger than the current size.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer the kernel layer
|
|
Packit Service |
d40955 |
* @param physicalCount the new physical count in blocks
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
int resizePhysical(KernelLayer *layer, BlockCount physicalCount);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Adjust parameters to prepare to present a larger logical space.
|
|
Packit Service |
d40955 |
* The size must be larger than the current size.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer the kernel layer
|
|
Packit Service |
d40955 |
* @param logicalCount the new logical size in blocks
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
int prepareToResizeLogical(KernelLayer *layer, BlockCount logicalCount);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Adjust parameters to present a larger logical space.
|
|
Packit Service |
d40955 |
* The size must be larger than the current size.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer the kernel layer
|
|
Packit Service |
d40955 |
* @param logicalCount the new logical size in blocks
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
int resizeLogical(KernelLayer *layer, BlockCount logicalCount);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Indicate whether the kernel layer is configured to use a separate
|
|
Packit Service |
d40955 |
* work queue for acknowledging received and processed bios.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* Note that this directly controls handling of write operations, but
|
|
Packit Service |
d40955 |
* the compile-time flag USE_BIO_ACK_QUEUE_FOR_READ is also checked
|
|
Packit Service |
d40955 |
* for read operations.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return Whether a bio-acknowledgement work queue is in use
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool useBioAckQueue(KernelLayer *layer)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return layer->deviceConfig->threadCounts.bioAckThreads > 0;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Update bookkeeping for the completion of some number of requests, so that
|
|
Packit Service |
d40955 |
* more incoming requests can be accepted.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param layer The kernel layer
|
|
Packit Service |
d40955 |
* @param count The number of completed requests
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void completeManyRequests(KernelLayer *layer, uint32_t count);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#endif /* KERNELLAYER_H */
|