|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
310c69 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
310c69 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
310c69 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
310c69 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
310c69 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
310c69 |
* GNU General Public License for more details.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
310c69 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
310c69 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
310c69 |
* 02110-1301, USA.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/hashZone.c#3 $
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "hashZone.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "logger.h"
|
|
Packit Service |
310c69 |
#include "memoryAlloc.h"
|
|
Packit Service |
310c69 |
#include "numeric.h"
|
|
Packit Service |
310c69 |
#include "permassert.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "constants.h"
|
|
Packit Service |
310c69 |
#include "dataVIO.h"
|
|
Packit Service |
310c69 |
#include "hashLock.h"
|
|
Packit Service |
310c69 |
#include "hashLockInternals.h"
|
|
Packit Service |
310c69 |
#include "pointerMap.h"
|
|
Packit Service |
310c69 |
#include "ringNode.h"
|
|
Packit Service |
310c69 |
#include "statistics.h"
|
|
Packit Service |
310c69 |
#include "threadConfig.h"
|
|
Packit Service |
310c69 |
#include "types.h"
|
|
Packit Service |
310c69 |
#include "vdoInternal.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
enum {
|
|
Packit Service |
310c69 |
LOCK_POOL_CAPACITY = MAXIMUM_USER_VIOS,
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* These fields are only modified by the locks sharing the hash zone thread,
|
|
Packit Service |
310c69 |
* but are queried by other threads.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
typedef struct atomicHashLockStatistics {
|
|
Packit Service |
310c69 |
/** Number of times the UDS advice proved correct */
|
|
Packit Service |
310c69 |
Atomic64 dedupeAdviceValid;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** Number of times the UDS advice proved incorrect */
|
|
Packit Service |
310c69 |
Atomic64 dedupeAdviceStale;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** Number of writes with the same data as another in-flight write */
|
|
Packit Service |
310c69 |
Atomic64 concurrentDataMatches;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** Number of writes whose hash collided with an in-flight write */
|
|
Packit Service |
310c69 |
Atomic64 concurrentHashCollisions;
|
|
Packit Service |
310c69 |
} AtomicHashLockStatistics;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
struct hashZone {
|
|
Packit Service |
310c69 |
/** Which hash zone this is */
|
|
Packit Service |
310c69 |
ZoneCount zoneNumber;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** The thread ID for this zone */
|
|
Packit Service |
310c69 |
ThreadID threadID;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** Mapping from chunkName fields to HashLocks */
|
|
Packit Service |
310c69 |
PointerMap *hashLockMap;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** Ring containing all unused HashLocks */
|
|
Packit Service |
310c69 |
RingNode lockPool;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** Statistics shared by all hash locks in this zone */
|
|
Packit Service |
310c69 |
AtomicHashLockStatistics statistics;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** Array of all HashLocks */
|
|
Packit Service |
310c69 |
HashLock *lockArray;
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Implements PointerKeyComparator.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static bool compareKeys(const void *thisKey, const void *thatKey)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Null keys are not supported.
|
|
Packit Service |
310c69 |
return (memcmp(thisKey, thatKey, sizeof(UdsChunkName)) == 0);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Implements PointerKeyComparator.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static uint32_t hashKey(const void *key)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
const UdsChunkName *name = key;
|
|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Use a fragment of the chunk name as a hash code. It must not overlap with
|
|
Packit Service |
310c69 |
* fragments used elsewhere to ensure uniform distributions.
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
// XXX pick an offset in the chunk name that isn't used elsewhere
|
|
Packit Service |
310c69 |
return getUInt32LE(&name->name[4]);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
static inline HashLock *asHashLock(RingNode *poolNode)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
STATIC_ASSERT(offsetof(HashLock, poolNode) == 0);
|
|
Packit Service |
310c69 |
return (HashLock *) poolNode;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int makeHashZone(VDO *vdo, ZoneCount zoneNumber, HashZone **zonePtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
HashZone *zone;
|
|
Packit Service |
310c69 |
int result = ALLOCATE(1, HashZone, __func__, &zone);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = makePointerMap(LOCK_MAP_CAPACITY, 0, compareKeys, hashKey,
|
|
Packit Service |
310c69 |
&zone->hashLockMap);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeHashZone(&zone);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
zone->zoneNumber = zoneNumber;
|
|
Packit Service |
310c69 |
zone->threadID = getHashZoneThread(getThreadConfig(vdo), zoneNumber);
|
|
Packit Service |
310c69 |
initializeRing(&zone->lockPool);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = ALLOCATE(LOCK_POOL_CAPACITY, HashLock, "HashLock array",
|
|
Packit Service |
310c69 |
&zone->lockArray);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
freeHashZone(&zone);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
for (VIOCount i = 0; i < LOCK_POOL_CAPACITY; i++) {
|
|
Packit Service |
310c69 |
HashLock *lock = &zone->lockArray[i];
|
|
Packit Service |
310c69 |
initializeHashLock(lock);
|
|
Packit Service |
310c69 |
pushRingNode(&zone->lockPool, &lock->poolNode);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*zonePtr = zone;
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void freeHashZone(HashZone **zonePtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (*zonePtr == NULL) {
|
|
Packit Service |
310c69 |
return;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
HashZone *zone = *zonePtr;
|
|
Packit Service |
310c69 |
freePointerMap(&zone->hashLockMap);
|
|
Packit Service |
310c69 |
FREE(zone->lockArray);
|
|
Packit Service |
310c69 |
FREE(zone);
|
|
Packit Service |
310c69 |
*zonePtr = NULL;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
ZoneCount getHashZoneNumber(const HashZone *zone)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return zone->zoneNumber;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
ThreadID getHashZoneThreadID(const HashZone *zone)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return zone->threadID;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
HashLockStatistics getHashZoneStatistics(const HashZone *zone)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
const AtomicHashLockStatistics *atoms = &zone->statistics;
|
|
Packit Service |
310c69 |
return (HashLockStatistics) {
|
|
Packit Service |
310c69 |
.dedupeAdviceValid = relaxedLoad64(&atoms->dedupeAdviceValid),
|
|
Packit Service |
310c69 |
.dedupeAdviceStale = relaxedLoad64(&atoms->dedupeAdviceStale),
|
|
Packit Service |
310c69 |
.concurrentDataMatches = relaxedLoad64(&atoms->concurrentDataMatches),
|
|
Packit Service |
310c69 |
.concurrentHashCollisions
|
|
Packit Service |
310c69 |
= relaxedLoad64(&atoms->concurrentHashCollisions),
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Return a hash lock to the zone's pool and null out the reference to it.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param [in] zone The zone from which the lock was borrowed
|
|
Packit Service |
310c69 |
* @param [in,out] lockPtr The last reference to the lock being returned
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static void returnHashLockToPool(HashZone *zone, HashLock **lockPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
HashLock *lock = *lockPtr;
|
|
Packit Service |
310c69 |
*lockPtr = NULL;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
memset(lock, 0, sizeof(*lock));
|
|
Packit Service |
310c69 |
initializeHashLock(lock);
|
|
Packit Service |
310c69 |
pushRingNode(&zone->lockPool, &lock->poolNode);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int acquireHashLockFromZone(HashZone *zone,
|
|
Packit Service |
310c69 |
const UdsChunkName *hash,
|
|
Packit Service |
310c69 |
HashLock *replaceLock,
|
|
Packit Service |
310c69 |
HashLock **lockPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Borrow and prepare a lock from the pool so we don't have to do two
|
|
Packit Service |
310c69 |
// PointerMap accesses in the common case of no lock contention.
|
|
Packit Service |
310c69 |
HashLock *newLock = asHashLock(popRingNode(&zone->lockPool));
|
|
Packit Service |
310c69 |
int result = ASSERT(newLock != NULL,
|
|
Packit Service |
310c69 |
"never need to wait for a free hash lock");
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Fill in the hash of the new lock so we can map it, since we have to use
|
|
Packit Service |
310c69 |
// the hash as the map key.
|
|
Packit Service |
310c69 |
newLock->hash = *hash;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
HashLock *lock;
|
|
Packit Service |
310c69 |
result = pointerMapPut(zone->hashLockMap, &newLock->hash, newLock,
|
|
Packit Service |
310c69 |
(replaceLock != NULL), (void **) &lock);
|
|
Packit Service |
310c69 |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
310c69 |
returnHashLockToPool(zone, &newLock);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (replaceLock != NULL) {
|
|
Packit Service |
310c69 |
// XXX on mismatch put the old lock back and return a severe error
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(lock == replaceLock,
|
|
Packit Service |
310c69 |
"old lock must have been in the lock map");
|
|
Packit Service |
310c69 |
// XXX check earlier and bail out?
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(replaceLock->registered,
|
|
Packit Service |
310c69 |
"old lock must have been marked registered");
|
|
Packit Service |
310c69 |
replaceLock->registered = false;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (lock == replaceLock) {
|
|
Packit Service |
310c69 |
lock = newLock;
|
|
Packit Service |
310c69 |
lock->registered = true;
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
// There's already a lock for the hash, so we don't need the borrowed lock.
|
|
Packit Service |
310c69 |
returnHashLockToPool(zone, &newLock);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*lockPtr = lock;
|
|
Packit Service |
310c69 |
return VDO_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void returnHashLockToZone(HashZone *zone, HashLock **lockPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
HashLock *lock = *lockPtr;
|
|
Packit Service |
310c69 |
*lockPtr = NULL;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (lock->registered) {
|
|
Packit Service |
310c69 |
HashLock *removed = pointerMapRemove(zone->hashLockMap, &lock->hash);
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(lock == removed,
|
|
Packit Service |
310c69 |
"hash lock being released must have been mapped");
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(lock != pointerMapGet(zone->hashLockMap, &lock->hash),
|
|
Packit Service |
310c69 |
"unregistered hash lock must not be in the lock map");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(!hasWaiters(&lock->waiters),
|
|
Packit Service |
310c69 |
"hash lock returned to zone must have no waiters");
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((lock->duplicateLock == NULL),
|
|
Packit Service |
310c69 |
"hash lock returned to zone must not reference a PBN lock");
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((lock->state == HASH_LOCK_DESTROYING),
|
|
Packit Service |
310c69 |
"returned hash lock must not be in use with state %s",
|
|
Packit Service |
310c69 |
getHashLockStateName(lock->state));
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(isRingEmpty(&lock->poolNode),
|
|
Packit Service |
310c69 |
"hash lock returned to zone must not be in a pool ring");
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(isRingEmpty(&lock->duplicateRing),
|
|
Packit Service |
310c69 |
"hash lock returned to zone must not reference DataVIOs");
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
returnHashLockToPool(zone, &lock);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Dump a compact description of HashLock to the log if the lock is not on the
|
|
Packit Service |
310c69 |
* free list.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param lock The hash lock to dump
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static void dumpHashLock(const HashLock *lock)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (!isRingEmpty(&lock->poolNode)) {
|
|
Packit Service |
310c69 |
// This lock is on the free list.
|
|
Packit Service |
310c69 |
return;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Necessarily cryptic since we can log a lot of these. First three chars of
|
|
Packit Service |
310c69 |
// state is unambiguous. 'U' indicates a lock not registered in the map.
|
|
Packit Service |
310c69 |
const char *state = getHashLockStateName(lock->state);
|
|
Packit Service |
310c69 |
logInfo(" hl %" PRIptr ": %3.3s %c%llu/%u rc=%u wc=%zu agt=%" PRIptr,
|
|
Packit Service |
310c69 |
(const void *) lock,
|
|
Packit Service |
310c69 |
state,
|
|
Packit Service |
310c69 |
(lock->registered ? 'D' : 'U'),
|
|
Packit Service |
310c69 |
lock->duplicate.pbn,
|
|
Packit Service |
310c69 |
lock->duplicate.state,
|
|
Packit Service |
310c69 |
lock->referenceCount,
|
|
Packit Service |
310c69 |
countWaiters(&lock->waiters),
|
|
Packit Service |
310c69 |
(void *) lock->agent);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void bumpHashZoneValidAdviceCount(HashZone *zone)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Must only be mutated on the hash zone thread.
|
|
Packit Service |
310c69 |
relaxedAdd64(&zone->statistics.dedupeAdviceValid, 1);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void bumpHashZoneStaleAdviceCount(HashZone *zone)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Must only be mutated on the hash zone thread.
|
|
Packit Service |
310c69 |
relaxedAdd64(&zone->statistics.dedupeAdviceStale, 1);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void bumpHashZoneDataMatchCount(HashZone *zone)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Must only be mutated on the hash zone thread.
|
|
Packit Service |
310c69 |
relaxedAdd64(&zone->statistics.concurrentDataMatches, 1);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void bumpHashZoneCollisionCount(HashZone *zone)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Must only be mutated on the hash zone thread.
|
|
Packit Service |
310c69 |
relaxedAdd64(&zone->statistics.concurrentHashCollisions, 1);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void dumpHashZone(const HashZone *zone)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (zone->hashLockMap == NULL) {
|
|
Packit Service |
310c69 |
logInfo("HashZone %u: NULL map", zone->zoneNumber);
|
|
Packit Service |
310c69 |
return;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
logInfo("HashZone %u: mapSize=%zu",
|
|
Packit Service |
310c69 |
zone->zoneNumber, pointerMapSize(zone->hashLockMap));
|
|
Packit Service |
310c69 |
for (VIOCount i = 0; i < LOCK_POOL_CAPACITY; i++) {
|
|
Packit Service |
310c69 |
dumpHashLock(&zone->lockArray[i]);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|