From d7bb03dfb6098786d5121e9d8bc68d9d908fbd48 Mon Sep 17 00:00:00 2001 From: = Date: Thu, 20 Jul 2023 19:32:20 +0200 Subject: [PATCH] feat:Use pre-shuffled PSI array --- dm-sflc/Kbuild | 2 +- dm-sflc/device/device.c | 46 ++++++++++++++++++++++++++++++++++++++--- dm-sflc/device/device.h | 18 +++++++++------- dm-sflc/device/rmap.c | 38 +++++++++++++--------------------- dm-sflc/volume/fmap.c | 30 +++++++++++++-------------- 5 files changed, 83 insertions(+), 51 deletions(-) diff --git a/dm-sflc/Kbuild b/dm-sflc/Kbuild index 9176e0d..a86d8b9 100644 --- a/dm-sflc/Kbuild +++ b/dm-sflc/Kbuild @@ -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 diff --git a/dm-sflc/device/device.c b/dm-sflc/device/device.c index 6970ce3..4356626 100644 --- a/dm-sflc/device/device.c +++ b/dm-sflc/device/device.c @@ -31,6 +31,7 @@ #include "device.h" #include "sysfs/sysfs.h" +#include "utils/vector.h" #include "log/log.h" #include @@ -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); +} + diff --git a/dm-sflc/device/device.h b/dm-sflc/device/device.h index b9f5d5c..cc8b0a0 100644 --- a/dm-sflc/device/device.h +++ b/dm-sflc/device/device.h @@ -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. diff --git a/dm-sflc/device/rmap.c b/dm-sflc/device/rmap.c index fad48f5..e309211 100644 --- a/dm-sflc/device/rmap.c +++ b/dm-sflc/device/rmap.c @@ -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); diff --git a/dm-sflc/volume/fmap.c b/dm-sflc/volume/fmap.c index a4bd0e0..980173a 100644 --- a/dm-sflc/volume/fmap.c +++ b/dm-sflc/volume/fmap.c @@ -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;