""" Copyright (c) 2018 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. """ from Field import * from StatStruct import * from VDOReleaseVersions import * class BlockAllocatorStatistics(StatStruct): def __init__(self, name="BlockAllocatorStatistics", **kwargs): super(BlockAllocatorStatistics, self).__init__(name, [ # The total number of slabs from which blocks may be allocated Uint64Field("slabCount"), # The total number of slabs from which blocks have ever been allocated Uint64Field("slabsOpened"), # The number of times since loading that a slab has been re-opened Uint64Field("slabsReopened"), ], procRoot="vdo", **kwargs) # Counters for tracking the number of items written (blocks, requests, etc.) # that keep track of totals at steps in the write pipeline. Three counters # allow the number of buffered, in-memory items and the number of in-flight, # unacknowledged writes to be derived, while still tracking totals for # reporting purposes class CommitStatistics(StatStruct): def __init__(self, name="CommitStatistics", **kwargs): super(CommitStatistics, self).__init__(name, [ Uint64Field("batching", derived = "$started - $written"), # The total number of items on which processing has started Uint64Field("started"), Uint64Field("writing", derived = "$written - $committed"), # The total number of items for which a write operation has been issued Uint64Field("written"), # The total number of items for which a write operation has completed Uint64Field("committed"), ], procRoot="vdo", **kwargs) # Counters for events in the recovery journal class RecoveryJournalStatistics(StatStruct): def __init__(self, name="RecoveryJournalStatistics", **kwargs): super(RecoveryJournalStatistics, self).__init__(name, [ # Number of times the on-disk journal was full Uint64Field("diskFull", label = "disk full count"), # Number of times the recovery journal requested slab journal commits. Uint64Field("slabJournalCommitsRequested", label = "commits requested count"), # Write/Commit totals for individual journal entries CommitStatistics("entries", labelPrefix = "entries"), # Write/Commit totals for journal blocks CommitStatistics("blocks", labelPrefix = "blocks"), ], labelPrefix="journal", procRoot="vdo", **kwargs) # The statistics for the compressed block packer. class PackerStatistics(StatStruct): def __init__(self, name="PackerStatistics", **kwargs): super(PackerStatistics, self).__init__(name, [ # Number of compressed data items written since startup Uint64Field("compressedFragmentsWritten"), # Number of blocks containing compressed items written since startup Uint64Field("compressedBlocksWritten"), # Number of VIOs that are pending in the packer Uint64Field("compressedFragmentsInPacker"), ], procRoot="vdo", **kwargs) # The statistics for the slab journals. class SlabJournalStatistics(StatStruct): def __init__(self, name="SlabJournalStatistics", **kwargs): super(SlabJournalStatistics, self).__init__(name, [ # Number of times the on-disk journal was full Uint64Field("diskFullCount"), # Number of times an entry was added over the flush threshold Uint64Field("flushCount"), # Number of times an entry was added over the block threshold Uint64Field("blockedCount"), # Number of times a tail block was written Uint64Field("blocksWritten"), # Number of times we had to wait for the tail to write Uint64Field("tailBusyCount"), ], labelPrefix="slab journal", procRoot="vdo", **kwargs) # The statistics for the slab summary. class SlabSummaryStatistics(StatStruct): def __init__(self, name="SlabSummaryStatistics", **kwargs): super(SlabSummaryStatistics, self).__init__(name, [ # Number of blocks written Uint64Field("blocksWritten"), ], labelPrefix="slab summary", procRoot="vdo", **kwargs) # The statistics for the reference counts. class RefCountsStatistics(StatStruct): def __init__(self, name="RefCountsStatistics", **kwargs): super(RefCountsStatistics, self).__init__(name, [ # Number of reference blocks written Uint64Field("blocksWritten"), ], labelPrefix="reference", procRoot="vdo", **kwargs) # The statistics for the block map. class BlockMapStatistics(StatStruct): def __init__(self, name="BlockMapStatistics", **kwargs): super(BlockMapStatistics, self).__init__(name, [ # number of dirty (resident) pages Uint32Field("dirtyPages"), # number of clean (resident) pages Uint32Field("cleanPages"), # number of free pages Uint32Field("freePages"), # number of pages in failed state Uint32Field("failedPages"), # number of pages incoming Uint32Field("incomingPages"), # number of pages outgoing Uint32Field("outgoingPages"), # how many times free page not avail Uint32Field("cachePressure"), # number of getVDOPageAsync() for read Uint64Field("readCount"), # number or getVDOPageAsync() for write Uint64Field("writeCount"), # number of times pages failed to read Uint64Field("failedReads"), # number of times pages failed to write Uint64Field("failedWrites"), # number of gets that are reclaimed Uint64Field("reclaimed"), # number of gets for outgoing pages Uint64Field("readOutgoing"), # number of gets that were already there Uint64Field("foundInCache"), # number of gets requiring discard Uint64Field("discardRequired"), # number of gets enqueued for their page Uint64Field("waitForPage"), # number of gets that have to fetch Uint64Field("fetchRequired"), # number of page fetches Uint64Field("pagesLoaded"), # number of page saves Uint64Field("pagesSaved"), # the number of flushes issued Uint64Field("flushCount"), ], labelPrefix="block map", procRoot="vdo", **kwargs) # The dedupe statistics from hash locks class HashLockStatistics(StatStruct): def __init__(self, name="HashLockStatistics", **kwargs): super(HashLockStatistics, self).__init__(name, [ # Number of times the UDS advice proved correct Uint64Field("dedupeAdviceValid"), # Number of times the UDS advice proved incorrect Uint64Field("dedupeAdviceStale"), # Number of writes with the same data as another in-flight write Uint64Field("concurrentDataMatches"), # Number of writes whose hash collided with an in-flight write Uint64Field("concurrentHashCollisions"), ], procRoot="vdo", **kwargs) # Counts of error conditions in VDO. class ErrorStatistics(StatStruct): def __init__(self, name="ErrorStatistics", **kwargs): super(ErrorStatistics, self).__init__(name, [ # number of times VDO got an invalid dedupe advice PBN from UDS Uint64Field("invalidAdvicePBNCount"), # number of times a VIO completed with a VDO_NO_SPACE error Uint64Field("noSpaceErrorCount"), # number of times a VIO completed with a VDO_READ_ONLY error Uint64Field("readOnlyErrorCount"), ], procRoot="vdo", **kwargs) # The statistics of the vdo service. class VDOStatistics(StatStruct): def __init__(self, name="VDOStatistics", **kwargs): super(VDOStatistics, self).__init__(name, [ Uint32Field("version"), Uint32Field("releaseVersion"), # Number of blocks used for data Uint64Field("dataBlocksUsed", available = "((not $inRecoveryMode) and ($mode != 'read-only'))"), # Number of blocks used for VDO metadata Uint64Field("overheadBlocksUsed", available = "not $inRecoveryMode"), # Number of logical blocks that are currently mapped to physical blocks Uint64Field("logicalBlocksUsed", available = "not $inRecoveryMode"), # number of physical blocks Uint64Field("physicalBlocks"), # number of logical blocks Uint64Field("logicalBlocks"), Uint64Field("oneKBlocks", label = "1K-blocks", derived = "$physicalBlocks * $blockSize / 1024"), Uint64Field("oneKBlocksUsed", label = "1K-blocks used", derived = "($dataBlocksUsed + $overheadBlocksUsed) * $blockSize / 1024", available = "not $inRecoveryMode"), Uint64Field("oneKBlocksAvailable", label = "1K-blocks available", derived = "($physicalBlocks - $dataBlocksUsed - $overheadBlocksUsed) * $blockSize / 1024", available = "not $inRecoveryMode"), Uint8Field("usedPercent", derived = "int((100 * ($dataBlocksUsed + $overheadBlocksUsed) / $physicalBlocks) + 0.5)", available = "((not $inRecoveryMode) and ($mode != 'read-only'))"), Uint8Field("savings", display = False, derived = "int(100 * ($logicalBlocksUsed - $dataBlocksUsed) / $logicalBlocksUsed) if ($logicalBlocksUsed > 0) else -1", available = "not $inRecoveryMode"), Uint8Field("savingPercent", derived = "$savings if ($savings >= 0) else NotAvailable()", available = "((not $inRecoveryMode) and ($mode != 'read-only'))"), # Size of the block map page cache, in bytes Uint64Field("blockMapCacheSize"), # String describing the active write policy of the VDO StringField("writePolicy", length = 15), # The physical block size Uint64Field("blockSize"), # Number of times the VDO has successfully recovered Uint64Field("completeRecoveries", label = "completed recovery count"), # Number of times the VDO has recovered from read-only mode Uint64Field("readOnlyRecoveries", label = "read-only recovery count"), # String describing the operating mode of the VDO StringField("mode", length = 15, label = "operating mode"), # Whether the VDO is in recovery mode BoolField("inRecoveryMode", display = False), # What percentage of recovery mode work has been completed Uint8Field("recoveryPercentage", label = "recovery progress (%)", available = "$inRecoveryMode"), # The statistics for the compressed block packer PackerStatistics("packer"), # Counters for events in the block allocator BlockAllocatorStatistics("allocator"), # Counters for events in the recovery journal RecoveryJournalStatistics("journal"), # The statistics for the slab journals SlabJournalStatistics("slabJournal"), # The statistics for the slab summary SlabSummaryStatistics("slabSummary"), # The statistics for the reference counts RefCountsStatistics("refCounts"), # The statistics for the block map BlockMapStatistics("blockMap"), # The dedupe statistics from hash locks HashLockStatistics("hashLock"), # Counts of error conditions ErrorStatistics("errors"), ], procFile="dedupe_stats", procRoot="vdo", **kwargs) statisticsVersion = 28 def sample(self, device): sample = super(VDOStatistics, self).sample(device) if ((sample.getStat("version") != VDOStatistics.statisticsVersion) or (sample.getStat("releaseVersion") != CURRENT_RELEASE_VERSION_NUMBER)): raise Exception("VDOStatistics version mismatch") return sample