/* * Copyright (c) 2020 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/kvio.h#3 $ */ #ifndef KVIO_H #define KVIO_H #include "allocatingVIO.h" #include "vio.h" #include "kernelLayer.h" /** * A specific (semi-opaque) encapsulation of a single block **/ struct kvio { KvdoEnqueueable enqueueable; VIO *vio; KernelLayer *layer; BIO *bio; /** * A bio pointer used in enqueueBioMap (used via submitBio etc), to * pass information -- which bio to submit to the storage device -- * across a thread switch. This may match another bio pointer in * this structure, or could point somewhere else. **/ BIO *bioToSubmit; /** * A list of enqueued bios with consecutive block numbers, stored by * enqueueBioMap under the first-enqueued KVIO. The other KVIOs are * found via their bio entries in this list, and are not added to * the work queue as separate work items. **/ struct bio_list biosMerged; /** A slot for an arbitrary bit of data, for use by systemtap. */ long debugSlot; }; typedef struct { KVIO kvio; VIO vio; } MetadataKVIO; typedef struct { KVIO kvio; AllocatingVIO allocatingVIO; } CompressedWriteKVIO; /** * Determine whether a KVIO is a data VIO or not * * @param kvio The KVIO to check * * @return true if a data KVIO */ static inline bool isData(KVIO *kvio) { return isDataVIO(kvio->vio); } /** * Determine whether a KVIO is a compressed block write VIO or not * * @param kvio The KVIO to check * * @return true if a compressed block writer */ static inline bool isCompressedWriter(KVIO *kvio) { return isCompressedWriteVIO(kvio->vio); } /** * Determine whether a KVIO is a metadata VIO or not * * @param kvio The KVIO to check * * @return true if a metadata KVIO */ static inline bool isMetadata(KVIO *kvio) { return isMetadataVIO(kvio->vio); } /** * Convert a VIO to a MetadataKVIO. * * @param vio The VIO to convert * * @return the VIO as a KVIO **/ static inline MetadataKVIO *vioAsMetadataKVIO(VIO *vio) { ASSERT_LOG_ONLY(isMetadataVIO(vio), "VIO is a metadata VIO"); return container_of(vio, MetadataKVIO, vio); } /** * Convert a MetadataKVIO to a KVIO. * * @param metadataKVIO The MetadataKVIO to convert * * @return The MetadataKVIO as a KVIO **/ static inline KVIO *metadataKVIOAsKVIO(MetadataKVIO *metadataKVIO) { return &metadataKVIO->kvio; } /** * Returns a pointer to the CompressedWriteKVIO wrapping an AllocatingVIO. * * @param allocatingVIO The AllocatingVIO to convert * * @return the CompressedWriteKVIO **/ static inline CompressedWriteKVIO * allocatingVIOAsCompressedWriteKVIO(AllocatingVIO *allocatingVIO) { ASSERT_LOG_ONLY(isCompressedWriteAllocatingVIO(allocatingVIO), "AllocatingVIO is a compressed write"); return container_of(allocatingVIO, CompressedWriteKVIO, allocatingVIO); } /** * Convert a CompressedWriteKVIO to a KVIO. * * @param compressedWriteKVIO The CompressedWriteKVIO to convert * * @return The CompressedWriteKVIO as a KVIO **/ static inline KVIO *compressedWriteKVIOAsKVIO(CompressedWriteKVIO *compressedWriteKVIO) { return &compressedWriteKVIO->kvio; } /** * Returns a pointer to the KVIO wrapping a work item * * @param item the work item * * @return the KVIO **/ static inline KVIO *workItemAsKVIO(KvdoWorkItem *item) { return container_of(item, KVIO, enqueueable.workItem); } /** * Enqueue a KVIO on a work queue. * * @param queue The queue * @param kvio The KVIO **/ static inline void enqueueKVIOWork(KvdoWorkQueue *queue, KVIO *kvio) { enqueueWorkQueue(queue, &kvio->enqueueable.workItem); } /** * Add a trace record for the current source location. * * @param kvio The KVIO structure to be updated * @param location The source-location descriptor to be recorded **/ static inline void kvioAddTraceRecord(KVIO *kvio, TraceLocation location) { vioAddTraceRecord(kvio->vio, location); } /** * Set up the work item for a KVIO. * * @param kvio The KVIO to set up * @param work The function pointer to execute * @param statsFunction A function pointer to record for stats, or NULL * @param action Action code, mapping to a relative priority **/ static inline void setupKVIOWork(KVIO *kvio, KvdoWorkFunction work, void *statsFunction, unsigned int action) { setupWorkItem(&kvio->enqueueable.workItem, work, statsFunction, action); } /** * Set up and enqueue a KVIO. * * @param kvio The KVIO to set up * @param work The function pointer to execute * @param statsFunction A function pointer to record for stats, or NULL * @param action Action code, mapping to a relative priority * @param queue The queue on which to enqueue the KVIO **/ static inline void launchKVIO(KVIO *kvio, KvdoWorkFunction work, void *statsFunction, unsigned int action, KvdoWorkQueue *queue) { setupKVIOWork(kvio, work, statsFunction, action); enqueueKVIOWork(queue, kvio); } /** * Move a KVIO back to the base threads. * * @param kvio The KVIO to enqueue **/ void kvdoEnqueueVIOCallback(KVIO *kvio); /** * Handles kvio-related I/O post-processing. * * @param kvio The kvio to finalize * @param error Possible error **/ void kvdoContinueKvio(KVIO *kvio, int error); /** * Initialize a KVIO. * * @param kvio The KVIO to initialize * @param layer The physical layer * @param vioType The type of VIO to create * @param priority The relative priority to assign to the KVIO * @param parent The parent of the KVIO completion * @param bio The bio to associate with this KVIO **/ void initializeKVIO(KVIO *kvio, KernelLayer *layer, VIOType vioType, VIOPriority priority, void *parent, BIO *bio); /** * Destroy a MetadataKVIO and NULL out the pointer to it. * * @param metadataKVIOPtr A pointer to the MetadataKVIO to destroy **/ void freeMetadataKVIO(MetadataKVIO **metadataKVIOPtr); /** * Destroy a CompressedWriteKVIO and NULL out the pointer to it. * * @param compressedWriteKVIOPtr A pointer to the CompressedWriteKVIO to * destroy **/ void freeCompressedWriteKVIO(CompressedWriteKVIO **compressedWriteKVIOPtr); /** * Create a new VIO (and its enclosing KVIO) for metadata operations. * *

Implements MetadataVIOCreator. * * @param [in] layer The physical layer * @param [in] vioType The type of VIO to create * @param [in] priority The relative priority to assign to the VIO * @param [in] parent The parent to assign to the VIO's completion * @param [in] data The buffer * @param [out] vioPtr A pointer to hold new VIO * * @return VDO_SUCCESS or an error **/ int kvdoCreateMetadataVIO(PhysicalLayer *layer, VIOType vioType, VIOPriority priority, void *parent, char *data, VIO **vioPtr) __attribute__((warn_unused_result)); /** * Create a new AllocatingVIO (and its enclosing KVIO) for compressed writes. * *

Implements CompressedWriteVIOCreator. * * @param [in] layer The physical layer * @param [in] parent The parent to assign to the AllocatingVIO's * completion * @param [in] data The buffer * @param [out] allocatingVIOPtr A pointer to hold new AllocatingVIO * * @return VDO_SUCCESS or an error **/ int kvdoCreateCompressedWriteVIO(PhysicalLayer *layer, void *parent, char *data, AllocatingVIO **allocatingVIOPtr) __attribute__((warn_unused_result)); /** * Submit a compressed block write. * *

Implements CompressedWriter. * * @param allocatingVIO The AllocatingVIO for the compressed write **/ void kvdoWriteCompressedBlock(AllocatingVIO *allocatingVIO); /** * Read or write a single metadata VIO. * *

Implements MetadataReader and MetadataWriter * * @param vio The VIO to read or write **/ void kvdoSubmitMetadataVIO(VIO *vio); /** * Issue an empty flush to the lower layer using the BIO in a metadata VIO. * *

Implements MetadataWriter. * * @param vio The VIO to flush **/ void kvdoFlushVIO(VIO *vio); #endif /* KVIO_H */