feat:Use pre-shuffled PSI array

This commit is contained in:
= 2023-07-20 19:32:20 +02:00
parent 46fde04ff5
commit d7bb03dfb6
5 changed files with 83 additions and 51 deletions

View file

@ -30,7 +30,7 @@ OBJ_LIST += sysfs/sysfs.o sysfs/devices.o sysfs/volumes.o
OBJ_LIST += target/target.o
OBJ_LIST += device/device.o device/volumes.o device/rawio.o device/rmap.o device/iv.o
OBJ_LIST += volume/volume.o volume/io.o volume/read.o volume/write.o volume/fmap.o
OBJ_LIST += utils/string.o utils/bio.o utils/pools.o utils/workqueues.o
OBJ_LIST += utils/string.o utils/bio.o utils/pools.o utils/workqueues.o utils/vector.o
OBJ_LIST += crypto/rand/rand.o crypto/rand/selftest.o
OBJ_LIST += crypto/symkey/symkey.o crypto/symkey/skreq_pool.o crypto/symkey/selftest.o

View file

@ -31,6 +31,7 @@
#include "device.h"
#include "sysfs/sysfs.h"
#include "utils/vector.h"
#include "log/log.h"
#include <linux/vmalloc.h>
@ -68,6 +69,9 @@ static bool sflc_dev_acquireId(size_t id);
/* Release device ID */
static void sflc_dev_releaseId(size_t id);
/* Initialises and pre-shuffles the PSI array */
static int sflc_dev_initAndShufflePsiArray(u32 *psi_array, u32 len);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
@ -153,8 +157,8 @@ sflc_Device * sflc_dev_create(struct dm_target * ti, char * real_dev_path, u32 t
dev->vol_header_size = 1 + nr_pmbs_per_vol + dev->vol_header_nr_iv_blocks;
dev->dev_header_size = 1 + (SFLC_DEV_MAX_VOLUMES * dev->vol_header_size);
/* Init rmap lock */
mutex_init(&dev->rmap_lock);
/* Init slices lock */
mutex_init(&dev->slices_lock);
/* Allocate reverse slice map */
dev->rmap = vmalloc(dev->tot_slices * sizeof(u8));
if (!dev->rmap) {
@ -164,6 +168,21 @@ sflc_Device * sflc_dev_create(struct dm_target * ti, char * real_dev_path, u32 t
}
/* Initialise it */
memset(dev->rmap, SFLC_DEV_RMAP_INVALID_VOL, dev->tot_slices * sizeof(u8));
/* Allocate PSI array */
dev->shuffled_psi_array = vmalloc(dev->tot_slices * sizeof(u32));
if (!dev->shuffled_psi_array) {
pr_err("Could not allocate PSI array\n");
err = -ENOMEM;
goto err_alloc_psi_array;
}
/* Initialise it and pre-shuffle it */
err = sflc_dev_initAndShufflePsiArray(dev->shuffled_psi_array, dev->tot_slices);
if (err) {
pr_err("Could not init-and-shuffle PSI array: error %d", err);
goto err_initshuffle_psi_array;
}
/* Init related counter */
dev->shuffled_psi_ctr = 0;
/* Init IV cache lock */
mutex_init(&dev->iv_cache_lock);
@ -198,6 +217,9 @@ sflc_Device * sflc_dev_create(struct dm_target * ti, char * real_dev_path, u32 t
err_sysfs:
kfree(dev->iv_cache);
err_alloc_iv_cache:
err_initshuffle_psi_array:
vfree(dev->shuffled_psi_array);
err_alloc_psi_array:
vfree(dev->rmap);
err_alloc_rmap:
kfree(dev->bdev_path);
@ -250,6 +272,9 @@ bool sflc_dev_destroy(struct dm_target * ti, sflc_Device * dev)
/* IV cache */
kfree(dev->iv_cache);
/* PSI array */
vfree(dev->shuffled_psi_array);
/* Reverse slice map */
vfree(dev->rmap);
@ -271,7 +296,7 @@ bool sflc_dev_destroy(struct dm_target * ti, sflc_Device * dev)
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/
/* Acquire devoce ID, returns false if not possible */
/* Acquire device ID, returns false if not possible */
static bool sflc_dev_acquireId(size_t id)
{
/* Sanity check */
@ -315,3 +340,18 @@ static void sflc_dev_releaseId(size_t id)
return;
}
/* Initialises and pre-shuffles the PSI array */
static int sflc_dev_initAndShufflePsiArray(u32 *psi_array, u32 len)
{
u32 i;
/* Init to the identity map */
for (i = 0; i < len; i++) {
psi_array[i] = i;
}
/* Permute */
return sflc_vec_u32shuffle(psi_array, len);
}

View file

@ -112,8 +112,12 @@ struct sflc_device_s
int vol_cnt;
/* Reverse slice map, associating PSIs to volume indices */
struct mutex rmap_lock;
u8 * rmap;
/* Shuffled array of PSIs, with advancement counter */
u32 *shuffled_psi_array;
u32 shuffled_psi_ctr;
/* Lock for all three of these objects */
struct mutex slices_lock;
/* Slices info */
u32 tot_slices;
@ -192,16 +196,14 @@ bool sflc_dev_removeVolume(sflc_Device * dev, int vol_idx);
int sflc_dev_rwSector(sflc_Device * dev, struct page * page, sector_t sector, int rw);
/* The caller needs to hold rmap_lock to call these functions */
/* The caller needs to hold slices_lock to call these functions */
/* Sets the PSI as owned by the given volume. Returns < 0 if already taken. */
int sflc_dev_setRmap(sflc_Device * dev, u32 psi, u8 vol_idx);
/* Sets the PSI as free. */
void sflc_dev_unsetRmap(sflc_Device * dev, u32 psi);
/* Sets the PSI as owned by the given volume (also decreases free_slices).
* Returns < 0 if already taken. */
int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx);
/* Returns a random free physical slice, or < 0 if error */
s32 sflc_dev_getRandomFreePsi(sflc_Device * dev);
s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev);
/* These functions provide concurrent-safe access to the entries of the IV cache.

View file

@ -41,8 +41,9 @@
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/* Sets the PSI as owned by the given volume. Returns < 0 if already taken. */
int sflc_dev_setRmap(sflc_Device * dev, u32 psi, u8 vol_idx)
/* Sets the PSI as owned by the given volume (also decreases free_slices).
* Returns < 0 if already taken. */
int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx)
{
u8 prev_vol_idx;
@ -66,38 +67,27 @@ int sflc_dev_setRmap(sflc_Device * dev, u32 psi, u8 vol_idx)
return 0;
}
/* Sets the PSI as free. */
void sflc_dev_unsetRmap(sflc_Device * dev, u32 psi)
{
/* Bounds check */
if (psi >= dev->tot_slices) {
pr_err("Requested to unset ownership for invalid PSI\n");
}
/* Just unset it */
dev->rmap[psi] = SFLC_DEV_RMAP_INVALID_VOL;
dev->free_slices += 1;
return;
}
/* Returns a random free physical slice, or < 0 if error */
s32 sflc_dev_getRandomFreePsi(sflc_Device * dev)
s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev)
{
s32 psi;
u32 psi;
/* Check that there are free slices */
if (!dev->free_slices) {
pr_crit("Whoah! No free PSIs on the device! Catastrophe!");
pr_crit("Whoah! No free PSIs on the device! Catastrophe!\n");
return -ENOSPC;
}
/* Repeatedly sample until you find a free one */
/* Repeatedly advance the counter in the shuffled array
* until you find a free one */
do {
psi = sflc_rand_uniform(dev->tot_slices);
if (psi < 0) {
pr_err("Could not sample random PSI\n");
return -EINVAL;
psi = dev->shuffled_psi_array[dev->shuffled_psi_ctr];
dev->shuffled_psi_ctr += 1;
if (dev->shuffled_psi_ctr >= dev->tot_slices) {
pr_err("Double catastrophe! No free PSIs on the device, and didn't catch it before!\n");
return -ENOSPC;
}
} while (dev->rmap[psi] != SFLC_DEV_RMAP_INVALID_VOL);

View file

@ -125,12 +125,12 @@ int sflc_vol_loadFmap(sflc_Volume * vol)
iv_ptr = kmap(iv_page);
data_ptr = kmap(data_page);
/* Lock both the forward and the reverse position maps */
/* Lock both the forward map and the slices structs */
if (mutex_lock_interruptible(&vol->fmap_lock)) {
pr_err("Interrupted while waiting to lock fmap\n");
return -EINTR;
}
if (mutex_lock_interruptible(&dev->rmap_lock)) {
if (mutex_lock_interruptible(&dev->slices_lock)) {
pr_err("Interrupted while waiting to lock rmap\n");
mutex_unlock(&vol->fmap_lock);
return -EINTR;
@ -182,7 +182,7 @@ int sflc_vol_loadFmap(sflc_Volume * vol)
vol->fmap[lsi] = psi;
/* Also add it to the device's rmap and to the count, if LSI is actually mapped */
if (psi != SFLC_VOL_FMAP_INVALID_PSI) {
sflc_dev_setRmap(dev, psi, vol->vol_idx);
sflc_dev_markPsiTaken(dev, psi, vol->vol_idx);
vol->mapped_slices += 1;
}
@ -195,8 +195,8 @@ int sflc_vol_loadFmap(sflc_Volume * vol)
err = 0;
out:
/* Unlock both maps */
mutex_unlock(&dev->rmap_lock);
/* Release both locks */
mutex_unlock(&dev->slices_lock);
mutex_unlock(&vol->fmap_lock);
/* Kunmap pages */
kunmap(iv_page);
@ -235,12 +235,12 @@ int sflc_vol_storeFmap(sflc_Volume * vol)
iv_ptr = kmap(iv_page);
data_ptr = kmap(data_page);
/* Lock both the forward and the reverse position maps */
/* Lock both the forward map and the slices objects */
if (mutex_lock_interruptible(&vol->fmap_lock)) {
pr_err("Interrupted while waiting to lock fmap\n");
return -EINTR;
}
if (mutex_lock_interruptible(&dev->rmap_lock)) {
if (mutex_lock_interruptible(&dev->slices_lock)) {
pr_err("Interrupted while waiting to lock rmap\n");
mutex_unlock(&vol->fmap_lock);
return -EINTR;
@ -304,8 +304,8 @@ int sflc_vol_storeFmap(sflc_Volume * vol)
err = 0;
out:
/* Unlock both maps */
mutex_unlock(&dev->rmap_lock);
/* Release both locks */
mutex_unlock(&dev->slices_lock);
mutex_unlock(&vol->fmap_lock);
/* Kunmap pages */
kunmap(iv_page);
@ -346,18 +346,18 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op)
/* Otherwise, create a new slice mapping */
/* Also lock the device's reverse map */
if (mutex_lock_interruptible(&dev->rmap_lock)) {
/* Also lock the device's slices objects */
if (mutex_lock_interruptible(&dev->slices_lock)) {
pr_err("Interrupted while waiting to lock the reverse position map\n");
mutex_unlock(&vol->fmap_lock);
return -EINTR;
}
/* Get a free physical slice */
psi = sflc_dev_getRandomFreePsi(dev);
psi = sflc_dev_getNextRandomFreePsi(dev);
if (psi < 0) {
pr_err("Could not get a random free physical slice; error %d\n", psi);
mutex_unlock(&dev->rmap_lock);
mutex_unlock(&dev->slices_lock);
mutex_unlock(&vol->fmap_lock);
return psi;
}
@ -366,10 +366,10 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op)
vol->fmap[lsi] = psi;
vol->mapped_slices += 1;
/* And in the device's rmap */
sflc_dev_setRmap(dev, psi, vol->vol_idx);
sflc_dev_markPsiTaken(dev, psi, vol->vol_idx);
/* Unlock both maps */
mutex_unlock(&dev->rmap_lock);
mutex_unlock(&dev->slices_lock);
mutex_unlock(&vol->fmap_lock);
return psi;