Commit db6b0a7f authored by Bruce Johnston's avatar Bruce Johnston Committed by Mike Snitzer

dm vdo dedupe: switch to using int-map instead of pointer-map

Use get_unaligned_le64() on the hash lock's record name to serve as
the key to use with the int hash-map.

Switching to using int hash-map removes the only consumer of pointer
hash-map, as such it is removed.
Reviewed-by: default avatarMatthew Sakai <msakai@redhat.com>
Signed-off-by: default avatarBruce Johnston <bjohnsto@redhat.com>
Signed-off-by: default avatarMatthew Sakai <msakai@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@kernel.org>
parent a4bba246
......@@ -133,10 +133,10 @@
#include "completion.h"
#include "constants.h"
#include "data-vio.h"
#include "int-map.h"
#include "io-submitter.h"
#include "packer.h"
#include "physical-zone.h"
#include "pointer-map.h"
#include "slab-depot.h"
#include "statistics.h"
#include "types.h"
......@@ -370,6 +370,17 @@ struct pbn_lock *vdo_get_duplicate_lock(struct data_vio *data_vio)
return data_vio->hash_lock->duplicate_lock;
}
/**
* hash_lock_key() - Return hash_lock's record name as a hash code.
* @lock: The hash lock.
*
* Return: The key to use for the int map.
*/
static inline u64 hash_lock_key(struct hash_lock *lock)
{
return get_unaligned_le64(&lock->hash.name);
}
/**
* get_hash_lock_state_name() - Get the string representation of a hash lock state.
* @state: The hash lock state.
......@@ -865,7 +876,7 @@ static int __must_check acquire_lock(struct hash_zone *zone,
int result;
/*
* Borrow and prepare a lock from the pool so we don't have to do two pointer_map accesses
* Borrow and prepare a lock from the pool so we don't have to do two int_map accesses
* in the common case of no lock contention.
*/
result = ASSERT(!list_empty(&zone->lock_pool),
......@@ -882,8 +893,8 @@ static int __must_check acquire_lock(struct hash_zone *zone,
*/
new_lock->hash = *hash;
result = vdo_pointer_map_put(zone->hash_lock_map, &new_lock->hash, new_lock,
(replace_lock != NULL), (void **) &lock);
result = vdo_int_map_put(zone->hash_lock_map, hash_lock_key(new_lock),
new_lock, (replace_lock != NULL), (void **) &lock);
if (result != VDO_SUCCESS) {
return_hash_lock_to_pool(zone, uds_forget(new_lock));
return result;
......@@ -1904,6 +1915,7 @@ void vdo_acquire_hash_lock(struct vdo_completion *completion)
*/
void vdo_release_hash_lock(struct data_vio *data_vio)
{
u64 lock_key;
struct hash_lock *lock = data_vio->hash_lock;
struct hash_zone *zone = data_vio->hash_zone;
......@@ -1917,14 +1929,15 @@ void vdo_release_hash_lock(struct data_vio *data_vio)
return;
}
lock_key = hash_lock_key(lock);
if (lock->registered) {
struct hash_lock *removed;
removed = vdo_pointer_map_remove(zone->hash_lock_map, &lock->hash);
removed = vdo_int_map_remove(zone->hash_lock_map, lock_key);
ASSERT_LOG_ONLY(lock == removed,
"hash lock being released must have been mapped");
} else {
ASSERT_LOG_ONLY(lock != vdo_pointer_map_get(zone->hash_lock_map, &lock->hash),
ASSERT_LOG_ONLY(lock != vdo_int_map_get(zone->hash_lock_map, lock_key),
"unregistered hash lock must not be in the lock map");
}
......@@ -2011,22 +2024,6 @@ void vdo_share_compressed_write_lock(struct data_vio *data_vio,
ASSERT_LOG_ONLY(claimed, "impossible to fail to claim an initial increment");
}
/** compare_keys() - Implements pointer_key_comparator_fn. */
static bool compare_keys(const void *this_key, const void *that_key)
{
/* Null keys are not supported. */
return (memcmp(this_key, that_key, sizeof(struct uds_record_name)) == 0);
}
/** hash_key() - Implements pointer_key_comparator_fn. */
static u32 hash_key(const void *key)
{
const struct uds_record_name *name = key;
/* Use a fragment of the record name as a hash code. */
return get_unaligned_le32(&name->name[4]);
}
static void dedupe_kobj_release(struct kobject *directory)
{
uds_free(container_of(directory, struct hash_zones, dedupe_directory));
......@@ -2407,8 +2404,7 @@ static int __must_check initialize_zone(struct vdo *vdo, struct hash_zones *zone
data_vio_count_t i;
struct hash_zone *zone = &zones->zones[zone_number];
result = vdo_make_pointer_map(VDO_LOCK_MAP_CAPACITY, 0, compare_keys,
hash_key, &zone->hash_lock_map);
result = vdo_make_int_map(VDO_LOCK_MAP_CAPACITY, 0, &zone->hash_lock_map);
if (result != VDO_SUCCESS)
return result;
......@@ -2532,7 +2528,7 @@ void vdo_free_hash_zones(struct hash_zones *zones)
struct hash_zone *zone = &zones->zones[i];
uds_free_funnel_queue(uds_forget(zone->timed_out_complete));
vdo_free_pointer_map(uds_forget(zone->hash_lock_map));
vdo_free_int_map(uds_forget(zone->hash_lock_map));
uds_free(uds_forget(zone->lock_array));
}
......@@ -2847,7 +2843,7 @@ static void dump_hash_zone(const struct hash_zone *zone)
}
uds_log_info("struct hash_zone %u: mapSize=%zu",
zone->zone_number, vdo_pointer_map_size(zone->hash_lock_map));
zone->zone_number, vdo_int_map_size(zone->hash_lock_map));
for (i = 0; i < LOCK_POOL_CAPACITY; i++)
dump_hash_lock(&zone->lock_array[i]);
}
......
......@@ -40,7 +40,7 @@ struct hash_zone {
thread_id_t thread_id;
/* Mapping from record name fields to hash_locks */
struct pointer_map *hash_lock_map;
struct int_map *hash_lock_map;
/* List containing all unused hash_locks */
struct list_head lock_pool;
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2023 Red Hat
*/
#ifndef VDO_POINTER_MAP_H
#define VDO_POINTER_MAP_H
#include <linux/compiler.h>
#include <linux/types.h>
/*
* A pointer_map associates pointer values (<code>void *</code>) with the data referenced by
* pointer keys (<code>void *</code>). <code>NULL</code> pointer values are not supported. A
* <code>NULL</code> key value is supported when the instance's key comparator and hasher functions
* support it.
*
* The map is implemented as hash table, which should provide constant-time insert, query, and
* remove operations, although the insert may occasionally grow the table, which is linear in the
* number of entries in the map. The table will grow as needed to hold new entries, but will not
* shrink as entries are removed.
*
* The key and value pointers passed to the map are retained and used by the map, but are not owned
* by the map. Freeing the map does not attempt to free the pointers. The client is entirely
* responsible for the memory management of the keys and values. The current interface and
* implementation assume that keys will be properties of the values, or that keys will not be
* memory managed, or that keys will not need to be freed as a result of being replaced when a key
* is re-mapped.
*/
struct pointer_map;
/**
* typedef pointer_key_comparator - The prototype of functions that compare the referents of two
* pointer keys for equality.
* @this_key: The first element to compare.
* @that_key: The second element to compare.
*
* If two keys are equal, then both keys must have the same the hash code associated with them by
* the hasher function defined below.
*
* Return: true if and only if the referents of the two key pointers are to be treated as the same
* key by the map.
*/
typedef bool pointer_key_comparator(const void *this_key, const void *that_key);
/**
* typedef pointer_key_hasher - The prototype of functions that get or calculate a hash code
* associated with the referent of pointer key.
* @key: The pointer key to hash.
*
* The hash code must be uniformly distributed over all u32 values. The hash code associated
* with a given key must not change while the key is in the map. If the comparator function says
* two keys are equal, then this function must return the same hash code for both keys. This
* function may be called many times for a key while an entry is stored for it in the map.
*
* Return: The hash code for the key.
*/
typedef u32 pointer_key_hasher(const void *key);
int __must_check vdo_make_pointer_map(size_t initial_capacity,
unsigned int initial_load,
pointer_key_comparator comparator,
pointer_key_hasher hasher,
struct pointer_map **map_ptr);
void vdo_free_pointer_map(struct pointer_map *map);
size_t vdo_pointer_map_size(const struct pointer_map *map);
void *vdo_pointer_map_get(struct pointer_map *map, const void *key);
int __must_check vdo_pointer_map_put(struct pointer_map *map,
const void *key,
void *new_value,
bool update,
void **old_value_ptr);
void *vdo_pointer_map_remove(struct pointer_map *map, const void *key);
#endif /* VDO_POINTER_MAP_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment