Created
January 23, 2019 20:43
-
-
Save rhawalsh/5ef42b2dbf4084f4f8baa1761fe0d60a to your computer and use it in GitHub Desktop.
Patch to remove variable-length-arrays from kmod-kvdo version 6.2.0.293 for kernel 4.20
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 0a71f792b381ddab6785557fe896deadbbcff14f Mon Sep 17 00:00:00 2001 | |
From: Michael Sclafani <sclafani@redhat.com> | |
Date: Wed, 23 Jan 2019 11:53:31 +0000 | |
Subject: [PATCH] Removed variable-length-arrays | |
--- | |
uds/deltaIndex.c | 23 +++++++++++++++-------- | |
uds/indexLayoutParser.c | 18 ++++++------------ | |
uds/indexLayoutParser.h | 5 ++--- | |
uds/masterIndexOps.c | 10 ++++++++-- | |
uds/openChapter.c | 4 ++-- | |
uds/pageCache.c | 2 +- | |
uds/searchList.c | 33 +++++++++++++++++++-------------- | |
uds/util/pathBuffer.c | 6 ++++-- | |
uds/volumeInternals.c | 4 ++-- | |
uds/volumeInternals.h | 2 +- | |
vdo/base/blockAllocator.c | 16 ++++++++++++++-- | |
vdo/base/blockMapRecovery.c | 16 ++++++++++++++-- | |
vdo/base/heap.c | 16 ++++------------ | |
vdo/base/heap.h | 12 ++++++++++++ | |
14 files changed, 104 insertions(+), 63 deletions(-) | |
diff --git a/uds/deltaIndex.c b/uds/deltaIndex.c | |
index 833004a..84e5802 100644 | |
--- a/uds/deltaIndex.c | |
+++ b/uds/deltaIndex.c | |
@@ -843,7 +843,7 @@ static int readDeltaIndexHeader(BufferedReader *reader, | |
struct di_header *header) | |
{ | |
Buffer *buffer; | |
- | |
+ | |
int result = makeBuffer(sizeof(*header), &buffer); | |
if (result != UDS_SUCCESS) { | |
return result; | |
@@ -866,8 +866,9 @@ static int readDeltaIndexHeader(BufferedReader *reader, | |
} | |
/**********************************************************************/ | |
-int startRestoringDeltaIndex(const DeltaIndex *deltaIndex, | |
- BufferedReader **bufferedReaders, int numReaders) | |
+int startRestoringDeltaIndex(const DeltaIndex *deltaIndex, | |
+ BufferedReader **bufferedReaders, | |
+ int numReaders) | |
{ | |
if (!deltaIndex->isMutable) { | |
return logErrorWithStringError(UDS_BAD_STATE, | |
@@ -878,13 +879,19 @@ int startRestoringDeltaIndex(const DeltaIndex *deltaIndex, | |
"No delta index files"); | |
} | |
+ unsigned int numZones = numReaders; | |
+ if (numZones > MAX_ZONES) { | |
+ return logErrorWithStringError(UDS_INVALID_ARGUMENT, | |
+ "zone count %u must not exceed MAX_ZONES", | |
+ numZones); | |
+ } | |
+ | |
unsigned long recordCount = 0; | |
unsigned long collisionCount = 0; | |
- unsigned int numZones = numReaders; | |
- unsigned int firstList[numZones], numLists[numZones]; | |
- BufferedReader *reader[numZones]; | |
- bool zoneFlags[numZones]; | |
- memset(zoneFlags, false, numZones); | |
+ unsigned int firstList[MAX_ZONES]; | |
+ unsigned int numLists[MAX_ZONES]; | |
+ BufferedReader *reader[MAX_ZONES]; | |
+ bool zoneFlags[MAX_ZONES] = { false, }; | |
// Read the header from each file, and make sure we have a matching set | |
for (unsigned int z = 0; z < numZones; z++) { | |
diff --git a/uds/indexLayoutParser.c b/uds/indexLayoutParser.c | |
index e01df1d..3028dc9 100644 | |
--- a/uds/indexLayoutParser.c | |
+++ b/uds/indexLayoutParser.c | |
@@ -30,8 +30,7 @@ | |
/*****************************************************************************/ | |
__attribute__((warn_unused_result)) | |
-static int setParameterValue(const LayoutParameter *lp, | |
- char *data) | |
+static int setParameterValue(LayoutParameter *lp, char *data) | |
{ | |
if ((lp->type & LP_TYPE_MASK) == LP_UINT64) { | |
int result = parseUint64(data, lp->value.num); | |
@@ -50,12 +49,10 @@ static int setParameterValue(const LayoutParameter *lp, | |
} | |
/*****************************************************************************/ | |
-int parseLayoutString(char *info, | |
- const LayoutParameter *params, | |
- size_t count) | |
+int parseLayoutString(char *info, LayoutParameter *params, size_t count) | |
{ | |
if (!strchr(info, '=')) { | |
- for (const LayoutParameter *lp = params; lp < params + count; ++lp) { | |
+ for (LayoutParameter *lp = params; lp < params + count; ++lp) { | |
if (lp->type & LP_DEFAULT) { | |
int result = setParameterValue(lp, info); | |
if (result != UDS_SUCCESS) { | |
@@ -65,15 +62,12 @@ int parseLayoutString(char *info, | |
} | |
} | |
} else { | |
- bool seen[count]; | |
- memset(seen, 0, sizeof(seen)); | |
- | |
for (char *data = NULL, *token = nextToken(info, " ", &data); | |
token; | |
token = nextToken(NULL, " ", &data)) | |
{ | |
char *equal = strchr(token, '='); | |
- const LayoutParameter *lp = NULL; | |
+ LayoutParameter *lp; | |
for (lp = params; lp < params + count; ++lp) { | |
if (!equal && (lp->type & LP_DEFAULT)) { | |
break; | |
@@ -87,16 +81,16 @@ int parseLayoutString(char *info, | |
"unkown index parameter %s", | |
token); | |
} | |
- if (seen[lp - params]) { | |
+ if (lp->seen) { | |
return logErrorWithStringError(UDS_INDEX_NAME_REQUIRED, | |
"duplicate index parameter %s", | |
token); | |
} | |
+ lp->seen = true; | |
int result = setParameterValue(lp, equal ? equal + 1 : token); | |
if (result != UDS_SUCCESS) { | |
return result; | |
} | |
- seen[lp - params] = true; | |
} | |
} | |
return UDS_SUCCESS; | |
diff --git a/uds/indexLayoutParser.h b/uds/indexLayoutParser.h | |
index 53fea08..8431ee5 100644 | |
--- a/uds/indexLayoutParser.h | |
+++ b/uds/indexLayoutParser.h | |
@@ -38,6 +38,7 @@ typedef struct layoutParameter { | |
char **str; | |
uint64_t *num; | |
} value; | |
+ bool seen; | |
} LayoutParameter; | |
/** | |
@@ -64,9 +65,7 @@ typedef struct layoutParameter { | |
* @return UDS_SUCCESS or an error code, particularly | |
* UDS_INDEX_NAME_REQUIRED for all parsing errors. | |
**/ | |
-int parseLayoutString(char *info, | |
- const LayoutParameter *params, | |
- size_t count) | |
+int parseLayoutString(char *info, LayoutParameter *params, size_t count) | |
__attribute__((warn_unused_result)); | |
#endif // INDEX_LAYOUT_PARSER_H | |
diff --git a/uds/masterIndexOps.c b/uds/masterIndexOps.c | |
index 57800a3..f82c262 100644 | |
--- a/uds/masterIndexOps.c | |
+++ b/uds/masterIndexOps.c | |
@@ -84,9 +84,15 @@ int computeMasterIndexSaveBlocks(const Configuration *config, | |
/**********************************************************************/ | |
static int readMasterIndex(ReadPortal *portal) | |
{ | |
- unsigned int numZones = countPartsForPortal(portal); | |
MasterIndex *masterIndex = componentContextForPortal(portal); | |
- BufferedReader *readers[numZones]; | |
+ unsigned int numZones = countPartsForPortal(portal); | |
+ if (numZones > MAX_ZONES) { | |
+ return logErrorWithStringError(UDS_BAD_STATE, | |
+ "zone count %u must not exceed MAX_ZONES", | |
+ numZones); | |
+ } | |
+ | |
+ BufferedReader *readers[MAX_ZONES]; | |
for (unsigned int z = 0; z < numZones; ++z) { | |
int result = getBufferedReaderForPortal(portal, z, &readers[z]); | |
if (result != UDS_SUCCESS) { | |
diff --git a/uds/openChapter.c b/uds/openChapter.c | |
index aed327f..f3c5d41 100644 | |
--- a/uds/openChapter.c | |
+++ b/uds/openChapter.c | |
@@ -25,6 +25,7 @@ | |
#include "logger.h" | |
#include "memoryAlloc.h" | |
#include "numeric.h" | |
+#include "zone.h" | |
static int readOpenChapters(ReadPortal *portal); | |
static int writeOpenChapters(IndexComponent *component, | |
@@ -265,8 +266,7 @@ static int loadVersion20(Index *index, BufferedReader *reader) | |
uint32_t numRecords = getUInt32LE(numRecordsData); | |
// Keep track of which zones cannot accept any more records. | |
- bool fullFlags[index->zoneCount]; | |
- memset(fullFlags, 0, (index->zoneCount * sizeof(bool))); | |
+ bool fullFlags[MAX_ZONES] = { false, }; | |
// Assign records to the correct zones. | |
UdsChunkRecord record; | |
diff --git a/uds/pageCache.c b/uds/pageCache.c | |
index 5abd18b..542d7c8 100644 | |
--- a/uds/pageCache.c | |
+++ b/uds/pageCache.c | |
@@ -144,7 +144,7 @@ static void waitForPendingSearches(PageCache *cache, unsigned int physicalPage) | |
*/ | |
smp_mb(); | |
- InvalidateCounter initialCounters[cache->zoneCount]; | |
+ InvalidateCounter initialCounters[MAX_ZONES]; | |
for (unsigned int i = 0; i < cache->zoneCount; i++) { | |
initialCounters[i] = getInvalidateCounter(cache, i); | |
} | |
diff --git a/uds/searchList.c b/uds/searchList.c | |
index 229da00..6b568c4 100644 | |
--- a/uds/searchList.c | |
+++ b/uds/searchList.c | |
@@ -38,7 +38,9 @@ int makeSearchList(unsigned int capacity, | |
"search list capacity must fit in 8 bits"); | |
} | |
- unsigned int bytes = (sizeof(SearchList) + (capacity * sizeof(uint8_t))); | |
+ // We need three temporary entry arrays for purgeSearchList(). Allocate them | |
+ // contiguously with the main array. | |
+ unsigned int bytes = (sizeof(SearchList) + (4 * capacity * sizeof(uint8_t))); | |
SearchList *list; | |
int result = allocateCacheAligned(bytes, "search list", &list); | |
if (result != UDS_SUCCESS) { | |
@@ -75,17 +77,21 @@ void purgeSearchList(SearchList *searchList, | |
return; | |
} | |
- // Partition the previously-alive entries in the list into three temporary | |
- // lists, keeping the current LRU search order within each list. | |
- uint8_t alive[searchList->firstDeadEntry]; | |
- uint8_t skipped[searchList->firstDeadEntry]; | |
- uint8_t dead[searchList->firstDeadEntry]; | |
+ /* | |
+ * Partition the previously-alive entries in the list into three temporary | |
+ * lists, keeping the current LRU search order within each list. The element | |
+ * array was allocated with enough space for all four lists. | |
+ */ | |
+ uint8_t *entries = &searchList->entries[0]; | |
+ uint8_t *alive = &entries[searchList->capacity]; | |
+ uint8_t *skipped = &alive[searchList->capacity]; | |
+ uint8_t *dead = &skipped[searchList->capacity]; | |
unsigned int nextAlive = 0; | |
unsigned int nextSkipped = 0; | |
unsigned int nextDead = 0; | |
for (int i = 0; i < searchList->firstDeadEntry; i++) { | |
- uint8_t entry = searchList->entries[i]; | |
+ uint8_t entry = entries[i]; | |
const CachedChapterIndex *chapter = &chapters[entry]; | |
if ((chapter->virtualChapter < oldestVirtualChapter) | |
|| (chapter->virtualChapter == UINT64_MAX)) { | |
@@ -99,14 +105,13 @@ void purgeSearchList(SearchList *searchList, | |
// Copy the temporary lists back to the search list so we wind up with | |
// [ alive, alive, skippable, new-dead, new-dead, old-dead, old-dead ] | |
- unsigned int size = 0; | |
- memcpy(&searchList->entries[size], alive, nextAlive); | |
- size += nextAlive; | |
+ memcpy(entries, alive, nextAlive); | |
+ entries += nextAlive; | |
- memcpy(&searchList->entries[size], skipped, nextSkipped); | |
- size += nextSkipped; | |
+ memcpy(entries, skipped, nextSkipped); | |
+ entries += nextSkipped; | |
- memcpy(&searchList->entries[size], dead, nextDead); | |
+ memcpy(entries, dead, nextDead); | |
// The first dead entry is now the start of the copied dead list. | |
- searchList->firstDeadEntry = size; | |
+ searchList->firstDeadEntry = (nextAlive + nextSkipped); | |
} | |
diff --git a/uds/util/pathBuffer.c b/uds/util/pathBuffer.c | |
index be52b30..b19c324 100644 | |
--- a/uds/util/pathBuffer.c | |
+++ b/uds/util/pathBuffer.c | |
@@ -28,8 +28,10 @@ | |
#include "stringUtils.h" | |
#include "uds.h" | |
-static const size_t DEFAULT_PATH_BUFFER_SIZE = 128; | |
-static const size_t PATH_BUFFER_QUANTUM = 64; | |
+enum { | |
+ DEFAULT_PATH_BUFFER_SIZE = 128, | |
+ PATH_BUFFER_QUANTUM = 64, | |
+}; | |
/******************************************************************************/ | |
void zeroPathBuffer(PathBuffer *pb) | |
diff --git a/uds/volumeInternals.c b/uds/volumeInternals.c | |
index c28f9a2..a5383de 100644 | |
--- a/uds/volumeInternals.c | |
+++ b/uds/volumeInternals.c | |
@@ -27,6 +27,7 @@ | |
#include "indexConfig.h" | |
#include "logger.h" | |
#include "memoryAlloc.h" | |
+#include "permassert.h" | |
#include "recordPage.h" | |
#include "stringUtils.h" | |
#include "volume.h" | |
@@ -38,7 +39,6 @@ const byte VOLUME_VERSION_V4_10[] = "04.10"; | |
static const byte VOLUME_VERSION_V4[] = "04.00"; | |
static const byte VOLUME_VERSION_V3[] = "00227"; | |
const unsigned int VOLUME_MAGIC_LENGTH = sizeof(VOLUME_MAGIC_NUMBER) - 1; | |
-const unsigned int VOLUME_VERSION_LENGTH = sizeof(VOLUME_VERSION) - 1; | |
const bool READ_ONLY_VOLUME = true; | |
@@ -52,6 +52,7 @@ size_t encodeVolumeFormat(byte *volumeFormat, const Geometry *geometry) | |
memcpy(volumeFormat, VOLUME_MAGIC_NUMBER, VOLUME_MAGIC_LENGTH); | |
size += VOLUME_MAGIC_LENGTH; | |
+ STATIC_ASSERT(VOLUME_VERSION_LENGTH == (sizeof(VOLUME_VERSION) - 1)); | |
memcpy(volumeFormat + size, VOLUME_VERSION, VOLUME_VERSION_LENGTH); | |
size += VOLUME_VERSION_LENGTH; | |
@@ -77,7 +78,6 @@ static int readGeometry(BufferedReader *reader, Volume *volume) | |
if (result != UDS_SUCCESS) { | |
return result; | |
} | |
- memset(volume->geometry, 0, sizeof(Geometry)); | |
return readFromBufferedReader(reader, volume->geometry, sizeof(Geometry)); | |
} | |
diff --git a/uds/volumeInternals.h b/uds/volumeInternals.h | |
index c47a4c5..aedc2e9 100644 | |
--- a/uds/volumeInternals.h | |
+++ b/uds/volumeInternals.h | |
@@ -29,7 +29,7 @@ extern const byte VOLUME_MAGIC_NUMBER[]; | |
extern const byte VOLUME_VERSION[]; | |
extern const unsigned int VOLUME_MAGIC_LENGTH; | |
-extern const unsigned int VOLUME_VERSION_LENGTH; | |
+enum { VOLUME_VERSION_LENGTH = 5 }; | |
extern const bool READ_ONLY_VOLUME; | |
diff --git a/vdo/base/blockAllocator.c b/vdo/base/blockAllocator.c | |
index 1727a90..eac80f0 100644 | |
--- a/vdo/base/blockAllocator.c | |
+++ b/vdo/base/blockAllocator.c | |
@@ -488,6 +488,18 @@ static int compareSlabStatuses(const void *item1, const void *item2) | |
return ((info1->slabNumber < info2->slabNumber) ? 1 : -1); | |
} | |
+/** | |
+ * Swap two SlabStatus structures. Implements HeapSwapper. | |
+ **/ | |
+static void swapSlabStatuses(void *item1, void *item2) | |
+{ | |
+ SlabStatus *info1 = item1; | |
+ SlabStatus *info2 = item2; | |
+ SlabStatus temp = *info1; | |
+ *info1 = *info2; | |
+ *info2 = temp; | |
+} | |
+ | |
/**********************************************************************/ | |
int prepareSlabsForAllocation(BlockAllocator *allocator) | |
{ | |
@@ -507,8 +519,8 @@ int prepareSlabsForAllocation(BlockAllocator *allocator) | |
// Sort the slabs by cleanliness, then by emptiness hint. | |
Heap heap; | |
- initializeHeap(&heap, compareSlabStatuses, slabStatuses, slabCount, | |
- sizeof(SlabStatus)); | |
+ initializeHeap(&heap, compareSlabStatuses, swapSlabStatuses, | |
+ slabStatuses, slabCount, sizeof(SlabStatus)); | |
buildHeap(&heap, slabCount); | |
SlabStatus currentSlabStatus; | |
diff --git a/vdo/base/blockMapRecovery.c b/vdo/base/blockMapRecovery.c | |
index 3009990..212b392 100644 | |
--- a/vdo/base/blockMapRecovery.c | |
+++ b/vdo/base/blockMapRecovery.c | |
@@ -114,6 +114,18 @@ static int compareMappings(const void *item1, const void *item2) | |
return 0; | |
} | |
+/** | |
+ * Swap two NumberedBlockMapping structures. Implements HeapSwapper. | |
+ **/ | |
+static void swapMappings(void *item1, void *item2) | |
+{ | |
+ NumberedBlockMapping *mapping1 = item1; | |
+ NumberedBlockMapping *mapping2 = item2; | |
+ NumberedBlockMapping temp = *mapping1; | |
+ *mapping1 = *mapping2; | |
+ *mapping2 = temp; | |
+} | |
+ | |
/** | |
* Convert a VDOCompletion to a BlockMapRecoveryCompletion. | |
* | |
@@ -210,8 +222,8 @@ static int makeRecoveryCompletion(VDO *vdo, | |
// Organize the journal entries into a binary heap so we can iterate over | |
// them in sorted order incrementally, avoiding an expensive sort call. | |
- initializeHeap(&recovery->replayHeap, compareMappings, journalEntries, | |
- entryCount, sizeof(NumberedBlockMapping)); | |
+ initializeHeap(&recovery->replayHeap, compareMappings, swapMappings, | |
+ journalEntries, entryCount, sizeof(NumberedBlockMapping)); | |
buildHeap(&recovery->replayHeap, entryCount); | |
ASSERT_LOG_ONLY((getCallbackThreadID() == recovery->logicalThreadID), | |
diff --git a/vdo/base/heap.c b/vdo/base/heap.c | |
index d077664..7ff91b6 100644 | |
--- a/vdo/base/heap.c | |
+++ b/vdo/base/heap.c | |
@@ -30,12 +30,14 @@ | |
/**********************************************************************/ | |
void initializeHeap(Heap *heap, | |
HeapComparator *comparator, | |
+ HeapSwapper *swapper, | |
void *array, | |
size_t capacity, | |
size_t elementSize) | |
{ | |
*heap = (Heap) { | |
.comparator = comparator, | |
+ .swapper = swapper, | |
.capacity = capacity, | |
.elementSize = elementSize, | |
}; | |
@@ -46,16 +48,6 @@ void initializeHeap(Heap *heap, | |
} | |
} | |
-/**********************************************************************/ | |
-static inline void swapElements(Heap *heap, size_t node1, size_t node2) | |
-{ | |
- byte temp[heap->elementSize]; | |
- | |
- memcpy(temp, &heap->array[node1], heap->elementSize); | |
- memcpy(&heap->array[node1], &heap->array[node2], heap->elementSize); | |
- memcpy(&heap->array[node2], temp, heap->elementSize); | |
-} | |
- | |
/**********************************************************************/ | |
static void siftHeapDown(Heap *heap, size_t topNode, size_t lastNode) | |
{ | |
@@ -79,7 +71,7 @@ static void siftHeapDown(Heap *heap, size_t topNode, size_t lastNode) | |
} | |
// Swap the element we've been sifting down with the larger child. | |
- swapElements(heap, topNode, swapNode); | |
+ heap->swapper(&heap->array[topNode], &heap->array[swapNode]); | |
// Descend into the sub-heap rooted at that child, going around the loop | |
// again in place of a tail-recursive call to siftHeapDown(). | |
@@ -162,7 +154,7 @@ static inline size_t siftAndSort(Heap *heap, size_t rootNode, size_t lastNode) | |
* right-most leaf node in the heap, moving it to its sorted position in | |
* the array. | |
*/ | |
- swapElements(heap, rootNode, lastNode); | |
+ heap->swapper(&heap->array[rootNode], &heap->array[lastNode]); | |
// The sorted list is now one element larger and valid. The heap is | |
// one element smaller, and invalid. | |
lastNode -= heap->elementSize; | |
diff --git a/vdo/base/heap.h b/vdo/base/heap.h | |
index 5c9e6ae..bda85c7 100644 | |
--- a/vdo/base/heap.h | |
+++ b/vdo/base/heap.h | |
@@ -38,6 +38,14 @@ | |
**/ | |
typedef int HeapComparator(const void *item1, const void *item2); | |
+/** | |
+ * Prototype for functions which swap two array elements. | |
+ * | |
+ * @param item1 The first element to swap | |
+ * @param item2 The second element to swap | |
+ **/ | |
+typedef void HeapSwapper(void *item1, void *item2); | |
+ | |
/** | |
* A heap array can be any array of fixed-length elements in which the heap | |
* invariant can be established. In a max-heap, every child of a node must be | |
@@ -50,6 +58,8 @@ typedef struct heap { | |
byte *array; | |
/** the function to use to compare two elements */ | |
HeapComparator *comparator; | |
+ /** the function to use to swap two elements */ | |
+ HeapSwapper *swapper; | |
/** the maximum number of elements that can be stored */ | |
size_t capacity; | |
/** the size of every element (in bytes) */ | |
@@ -66,12 +76,14 @@ typedef struct heap { | |
* | |
* @param heap The heap to initialize | |
* @param comparator The function to use to compare two heap elements | |
+ * @param swapper The function to use to swap two heap elements | |
* @param array The array of elements (not modified by this call) | |
* @param capacity The maximum number of elements which fit in the array | |
* @param elementSize The size of every array element, in bytes | |
**/ | |
void initializeHeap(Heap *heap, | |
HeapComparator *comparator, | |
+ HeapSwapper *swapper, | |
void *array, | |
size_t capacity, | |
size_t elementSize); | |
-- | |
2.20.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment