/* * 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/base/vdoInternal.h#11 $ */ #ifndef VDO_INTERNAL_H #define VDO_INTERNAL_H #include "vdo.h" #include "adminCompletion.h" #include "adminState.h" #include "atomic.h" #include "header.h" #include "packer.h" #include "statistics.h" #include "superBlock.h" #include "readOnlyNotifier.h" #include "types.h" #include "uds.h" #include "vdoLayout.h" #include "vdoState.h" /** * Error counters are atomic since updates can arrive concurrently from * arbitrary threads. **/ typedef struct atomicErrorStatistics { // Dedupe path error stats Atomic64 invalidAdvicePBNCount; Atomic64 noSpaceErrorCount; Atomic64 readOnlyErrorCount; } AtomicErrorStatistics; struct vdo { /* The state of this VDO */ VDOState state; /* The read-only notifier */ ReadOnlyNotifier *readOnlyNotifier; /* The number of times this VDO has recovered from a dirty state */ uint64_t completeRecoveries; /* The number of times this VDO has recovered from a read-only state */ uint64_t readOnlyRecoveries; /* The format-time configuration of this VDO */ VDOConfig config; /* The load-time configuration of this VDO */ VDOLoadConfig loadConfig; /* The nonce for this VDO */ Nonce nonce; /* The super block */ SuperBlock *superBlock; /* The physical storage below us */ PhysicalLayer *layer; /* Our partitioning of the physical layer's storage */ VDOLayout *layout; /* The block map */ BlockMap *blockMap; /* The journal for block map recovery */ RecoveryJournal *recoveryJournal; /* The slab depot */ SlabDepot *depot; /* The compressed-block packer */ Packer *packer; /* Whether incoming data should be compressed */ AtomicBool compressing; /* The handler for flush requests */ Flusher *flusher; /* The master version of the VDO when loaded (for upgrading) */ VersionNumber loadVersion; /* The state the VDO was in when loaded (primarily for unit tests) */ VDOState loadState; /* Whether VIO tracing is enabled */ bool vioTraceRecording; /* The logical zones of this VDO */ LogicalZones *logicalZones; /* The physical zones of this VDO */ PhysicalZone **physicalZones; /* The hash lock zones of this VDO */ HashZone **hashZones; /* The completion for administrative operations */ AdminCompletion adminCompletion; /* The administrative state of the VDO */ AdminState adminState; /* Whether a close is required */ bool closeRequired; /* Atomic global counts of error events */ AtomicErrorStatistics errorStats; }; /** * Get the component data size of a VDO. * * @param vdo The VDO whose component data size is desired * * @return the component data size of the VDO **/ size_t getComponentDataSize(VDO *vdo) __attribute__((warn_unused_result)); /** * Encode the VDO and save the super block synchronously. * * @param vdo The VDO whose state is being saved * * @return VDO_SUCCESS or an error **/ int saveVDOComponents(VDO *vdo) __attribute__((warn_unused_result)); /** * Encode the VDO and save the super block asynchronously. All non-user mode * super block savers should use this bottle neck instead of calling * saveSuperBlockAsync() directly. * * @param vdo The VDO whose state is being saved * @param parent The completion to notify when the save is complete **/ void saveVDOComponentsAsync(VDO *vdo, VDOCompletion *parent); /** * Re-encode the VDO component after a reconfiguration and save the super * block synchronously. This function avoids the need to decode and re-encode * the other components by simply copying their previous encoding. * * @param vdo The VDO which was reconfigured * * @return VDO_SUCCESS or an error code **/ int saveReconfiguredVDO(VDO *vdo) __attribute__((warn_unused_result)); /** * Decode the VDO master version from the component data buffer in the super * block and store it in the VDO's loadVersion field. **/ int decodeVDOVersion(VDO *vdo) __attribute__((warn_unused_result)); /** * Loads the VDO master version into the VDO and checks that the version * can be understood by VDO. * * @param vdo The VDO to validate * * @return VDO_SUCCESS or an error if the loaded version is not supported **/ int validateVDOVersion(VDO *vdo) __attribute__((warn_unused_result)); /** * Decode the component data for the VDO itself from the component data buffer * in the super block. * * @param vdo The VDO to decode * * @return VDO_SUCCESS or an error **/ int decodeVDOComponent(VDO *vdo) __attribute__((warn_unused_result)); /** * Validate constraints on VDO config. * * @param config The VDO config * @param blockCount The block count of the VDO * @param requireLogical Set to true if the number logical blocks * must be configured (otherwise, it may be zero) * * @return a success or error code **/ int validateVDOConfig(const VDOConfig *config, BlockCount blockCount, bool requireLogical) __attribute__((warn_unused_result)); /** * Enable a VDO to enter read-only mode on errors. * * @param vdo The VDO to enable * * @return VDO_SUCCESS or an error **/ int enableReadOnlyEntry(VDO *vdo); /** * Get the block map. * * @param vdo The VDO whose block map is desired * * @return the block map from the VDO **/ BlockMap *getBlockMap(const VDO *vdo) __attribute__((warn_unused_result)); /** * Get the slab depot from a VDO. * * @param vdo The VDO whose slab depot is desired * * @return the slab depot from the VDO **/ SlabDepot *getSlabDepot(VDO *vdo) __attribute__((warn_unused_result)); /** * Get the recovery journal from a VDO. * * @param vdo The VDO whose recovery journal is desired * * @return the recovery journal from the VDO **/ RecoveryJournal *getRecoveryJournal(VDO *vdo) __attribute__((warn_unused_result)); /** * Check whether a VDO is in read-only mode. * * @param vdo The VDO to query * * @return true if the VDO is in read-only mode **/ bool inReadOnlyMode(const VDO *vdo) __attribute__((warn_unused_result)); /** * Check whether the VDO is in a clean state. * * @param vdo The VDO to query * * @return true if the VDO is clean **/ bool isClean(const VDO *vdo) __attribute__((warn_unused_result)); /** * Check whether the VDO was in a clean state when it was loaded. * * @param vdo The VDO to query * * @return true if the VDO was clean **/ bool wasClean(const VDO *vdo) __attribute__((warn_unused_result)); /** * Check whether the VDO requires a read-only mode rebuild. * * @param vdo The VDO to query * * @return true if the VDO requires a read-only rebuild **/ bool requiresReadOnlyRebuild(const VDO *vdo) __attribute__((warn_unused_result)); /** * Check whether a VDO requires rebuilding. * * @param vdo The VDO to query * * @return true if the VDO must be rebuilt **/ bool requiresRebuild(const VDO *vdo) __attribute__((warn_unused_result)); /** * Check whether a VDO should enter recovery mode. * * @param vdo The VDO to query * * @return true if the VDO requires recovery **/ bool requiresRecovery(const VDO *vdo) __attribute__((warn_unused_result)); /** * Check whether a VDO was replaying the recovery journal into the block map * when it crashed. * * @param vdo The VDO to query * * @return true if the VDO crashed while reconstructing the * block map **/ bool isReplaying(const VDO *vdo) __attribute__((warn_unused_result)); /** * Check whether the VDO is in recovery mode. * * @param vdo The VDO to query * * @return true if the VDO is in recovery mode **/ bool inRecoveryMode(const VDO *vdo) __attribute__((warn_unused_result)); /** * Put the VDO into recovery mode * * @param vdo The VDO **/ void enterRecoveryMode(VDO *vdo); /** * Leave recovery mode if slab scrubbing has actually finished. * * @param vdo The VDO **/ void leaveRecoveryMode(VDO *vdo); /** * Assert that we are running on the admin thread. * * @param vdo The VDO * @param name The name of the function which should be running on the admin * thread (for logging). **/ void assertOnAdminThread(VDO *vdo, const char *name); /** * Assert that this function was called on the specified logical zone thread. * * @param vdo The VDO * @param logicalZone The number of the logical zone * @param name The name of the calling function **/ void assertOnLogicalZoneThread(const VDO *vdo, ZoneCount logicalZone, const char *name); /** * Assert that this function was called on the specified physical zone thread. * * @param vdo The VDO * @param physicalZone The number of the physical zone * @param name The name of the calling function **/ void assertOnPhysicalZoneThread(const VDO *vdo, ZoneCount physicalZone, const char *name); /** * Select the hash zone responsible for locking a given chunk name. * * @param vdo The VDO containing the hash zones * @param name The chunk name * * @return The hash zone responsible for the chunk name **/ HashZone *selectHashZone(const VDO *vdo, const UdsChunkName *name) __attribute__((warn_unused_result)); /** * Get the physical zone responsible for a given physical block number of a * data block in this VDO instance, or of the zero block (for which a NULL * zone is returned). For any other block number that is not in the range of * valid data block numbers in any slab, an error will be returned. This * function is safe to call on invalid block numbers; it will not put the VDO * into read-only mode. * * @param [in] vdo The VDO containing the physical zones * @param [in] pbn The PBN of the data block * @param [out] zonePtr A pointer to return the physical zone * * @return VDO_SUCCESS or VDO_OUT_OF_RANGE if the block number is invalid * or an error code for any other failure **/ int getPhysicalZone(const VDO *vdo, PhysicalBlockNumber pbn, PhysicalZone **zonePtr) __attribute__((warn_unused_result)); /**********************************************************************/ // Asynchronous callback to share a duplicate block. This is only public so // test code may compare it against the current callback in the completion. void shareBlock(VDOCompletion *completion); #endif /* VDO_INTERNAL_H */