Merge pull request 'chore:Release v0.5.1' (#102) from dev into main

Reviewed-on: https://codeberg.org/shufflecake/shufflecake-c/pulls/102
This commit is contained in:
Tommaso Gagliardoni 2024-10-13 10:25:38 +00:00
commit c54777659d
26 changed files with 485 additions and 512 deletions

View file

@ -14,6 +14,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Global constants fully shared among components through `sflc_constants.h`.
## [0.5.1] - 2024-10-13
### Refactored
- Reorganized interface between dispatcher and dm-legacy through pointers to functions.
### Fixed
- Fixed debug error message when reading unallocated slices on dm-legacy.
## [0.5.0] - 2024-09-01
### Added
@ -37,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Changed all occurrences of "Shufflecake Old" to "Shufflecake Legacy", including code paths and variables.
- Reordered entries in CHANGELOG.md with sections following the order Added -> Changed -> Fixed -> Refactored -> Removed.
## [0.4.5] - 2024-06-03
### Changed

View file

@ -1,5 +1,5 @@
[![Status](resources/images/badges/badge_status_active.png)](https://codeberg.org/shufflecake/shufflecake-c) 
[![Version](resources/images/badges/badge_version_0.5.0.png)](https://codeberg.org/shufflecake/shufflecake-c/releases/tag/v0.5.0) 
[![Version](resources/images/badges/badge_version_0.5.1.png)](https://codeberg.org/shufflecake/shufflecake-c/releases/tag/v0.5.1) 
[![License](resources/images/badges/badge_license_gplv2plus.png)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) 
[![Docs researchpaper](resources/images/badges/badge_docs_researchpaper.png)](https://eprint.iacr.org/2023/1529) 
[![Website](resources/images/badges/badge_web_shufflecakedotnet.png)](https://shufflecake.net/) 
@ -12,7 +12,7 @@
# Shufflecake - Full C Implementation - v0.5.0
# Shufflecake - Full C Implementation - v0.5.1
_Shufflecake_ is a plausible deniability (hidden storage) layer for Linux. You can consider Shufflecake a spiritual successor of tools like TrueCrypt and VeraCrypt, but vastly improved, both in terms of security and functionality. Official website: <https://www.shufflecake.net>.
@ -265,6 +265,11 @@ Both methods works with the `init` action, and we do not have current plans to c
Please see the file `CHANGELOG.md` for a detailed history of changes.
### [0.5.1] - 2024-10-13
- Reorganized interface between dispatcher and dm-legacy through pointers to functions.
- Fixed debug error message when reading unallocated slices on dm-legacy.
### [0.5.0] - 2024-09-01
- BREAKING CHANGE: major rewrite, bugfixes, introduced Shufflecake "Lite" as a default mode of operation.
@ -273,34 +278,6 @@ Please see the file `CHANGELOG.md` for a detailed history of changes.
- Fixed a compile error on some versions of LTS kernels.
- Fixed segmentation fault when opening an already opened device.
### [0.4.4] - 2023-12-31
- Fixed a memory allocation error on large devices.
### [0.4.3] - 2023-11-29
- Fixed compile error on recent kernel versions.
### [0.4.2] - 2023-11-28
- Fixed persistent slice allocation ambiguity after a volume corruption by allocating fresh slices for the corrupted volume. This is done in order to help external recovery tools (e.g. RAID).
- Various bugfixes.
### [0.4.1] - 2023-07-30
- Fixed and improved benchmark scripts.
- Fixed mistake in drawing of header layout in `doc`.
### [0.4.0] - 2023-07-24
- BREAKING CHANGE: slightly modified header field format, removing redundant data and making it adherent to documentation.
- Implemented reference slice allocation algorithm with much faster performance.
- Added actions `checkpwd` and `changepwd`.
- Password is now read in a secure shell during `open`.
- Added benchmark suite.
- Fixed bugs in action `close` and option `--skip-randfill`.
- Added `doc` (currently includes figure of Shufflecake headers structure).

1
dm-sflc/bin/sflc_types.h Symbolic link
View file

@ -0,0 +1 @@
../src/sflc_types.h

View file

@ -27,183 +27,67 @@
#include "legacy/sflc_legacy.h"
/* Create a sflc_device containing the appropriate mode-specific struct */
struct sflc_device *sflc_dev_create(struct dm_target *ti, int argc, char **argv)
/* Init a sflc_device_base */
int sflc_dev_base_init(struct sflc_device_base *sd_base, struct dm_target *ti,
int argc, char **argv)
{
struct sflc_device *sdev;
u32 dev_id;
dev_t devt;
int mode;
int err;
sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
if (!sdev) {
DMERR("Could not allocate device");
return ERR_PTR(-ENOMEM);
}
/* Parse arguments */
if (sscanf(argv[0], "%d", &mode) != 1) {
err = -EINVAL;
goto bad_parse;
}
sscanf(argv[1], "%u", &dev_id);
err = lookup_bdev(argv[2], &devt);
if (err) {
DMERR("Could not look up block device");
goto bad_parse;
}
if (err)
return err;
/* Assign fields */
sdev->dev_id = dev_id;
sdev->nr_volumes = 0;
sdev->mode = mode;
format_dev_t(sdev->name, devt);
sd_base->dev_id = dev_id;
sd_base->nr_volumes = 0;
format_dev_t(sd_base->name, devt);
/* Fields `mode` and `ops` will be set by the derived constructor */
/* Register with sysfs */
err = sflc_sysfs_register_device(sdev);
err = sflc_sysfs_register_device_base(sd_base);
if (err)
goto bad_sysfs;
return err;
/* Instantiate inner device. Sysfs has to be inited by now */
switch (mode)
{
case SFLC_MODE_LEGACY:
sdev->sflegc_dev = sflegc_dev_create(ti, argc, argv, &sdev->kobj);
if (IS_ERR(sdev->sflegc_dev)) {
err = PTR_ERR(sdev->sflegc_dev);
goto bad_inner;
}
break;
case SFLC_MODE_LITE:
sdev->sflite_dev = sflite_dev_create(ti, argc, argv, &sdev->kobj);
if (IS_ERR(sdev->sflite_dev)) {
err = PTR_ERR(sdev->sflite_dev);
goto bad_inner;
}
break;
default:
DMERR("Invalid Shufflecake mode %d", mode);
err = -EINVAL;
goto bad_mode;
}
return sdev;
bad_mode:
bad_inner:
sflc_sysfs_unregister_device(sdev);
bad_sysfs:
bad_parse:
kfree(sdev);
return ERR_PTR(err);
return 0;
}
void sflc_dev_destroy(struct sflc_device *sdev)
void sflc_dev_base_exit(struct sflc_device_base *sd_base)
{
switch (sdev->mode)
{
case SFLC_MODE_LEGACY:
sflegc_dev_destroy(sdev->sflegc_dev);
break;
case SFLC_MODE_LITE:
sflite_dev_destroy(sdev->sflite_dev);
break;
default:
DMCRIT("Destroying device with invalid Shufflecake mode %d", sdev->mode);
return;
}
sflc_sysfs_unregister_device(sdev);
kfree(sdev);
sflc_sysfs_unregister_device_base(sd_base);
}
/* Create a sflc_volume containing the appropriate mode-specific struct */
struct sflc_volume *sflc_vol_create(struct sflc_device *sdev, struct dm_target *ti,
int argc, char **argv)
/* Init a sflc_volume_base */
int sflc_vol_base_init(struct sflc_volume_base *sv_base,
struct sflc_device_base *sd_base, struct dm_target *ti,
int argc, char **argv)
{
struct sflc_volume *svol;
u32 vol_idx;
int mode;
int err;
svol = kzalloc(sizeof(*svol), GFP_KERNEL);
if (!svol) {
DMERR("Could not allocate volume");
return ERR_PTR(-ENOMEM);
}
/* Parse arguments */
if (sscanf(argv[0], "%d", &mode) != 1) {
err = -EINVAL;
goto bad_parse;
}
sscanf(argv[3], "%u", &vol_idx);
/* Assign fields */
svol->mode = mode;
sprintf(svol->name, "sflc_%u_%u", sdev->dev_id, vol_idx);
svol->sdev = sdev;
sv_base->vol_idx = vol_idx;
sprintf(sv_base->name, "sflc_%u_%u", sd_base->dev_id, vol_idx);
sv_base->sd_base = sd_base;
/* Field `ops` will be set by the derived constructor */
/* Register with sysfs */
err = sflc_sysfs_register_volume(svol);
err = sflc_sysfs_register_volume_base(sv_base);
if (err)
goto bad_sysfs;
return err;
/* Instantiate inner volume. Sysfs has to be inited by now */
switch (mode)
{
case SFLC_MODE_LEGACY:
svol->sflegc_vol = sflegc_vol_create(ti, sdev->sflegc_dev, argc, argv, &svol->kobj);
if (IS_ERR(svol->sflegc_vol)) {
err = PTR_ERR(svol->sflegc_vol);
goto bad_inner;
}
svol->tt = &sflegc_target_type;
break;
case SFLC_MODE_LITE:
svol->sflite_vol = sflite_vol_create(ti, sdev->sflite_dev, argc, argv, &svol->kobj);
if (IS_ERR(svol->sflite_vol)) {
err = PTR_ERR(svol->sflite_vol);
goto bad_inner;
}
svol->tt = &sflite_target_type;
break;
default:
DMERR("Invalid Shufflecake mode %d", mode);
err = -EINVAL;
goto bad_mode;
}
return svol;
bad_mode:
bad_inner:
sflc_sysfs_unregister_volume(svol);
bad_sysfs:
bad_parse:
kfree(svol);
return ERR_PTR(err);
return 0;
}
void sflc_vol_destroy(struct sflc_volume *svol)
void sflc_vol_base_exit(struct sflc_volume_base *sv_base)
{
switch (svol->mode)
{
case SFLC_MODE_LEGACY:
sflegc_vol_destroy(svol->sflegc_vol);
break;
case SFLC_MODE_LITE:
sflite_vol_destroy(svol->sflite_vol);
break;
default:
DMCRIT("Destroying volume with invalid Shufflecake mode %d", svol->mode);
return;
}
sflc_sysfs_unregister_volume(svol);
kfree(svol);
sflc_sysfs_unregister_volume_base(sv_base);
}

View file

@ -33,6 +33,7 @@
#include "legacy/device/device.h"
#include "legacy/utils/vector.h"
#include "legacy/log/log.h"
#include "sflc.h"
#include <linux/vmalloc.h>
@ -63,11 +64,10 @@ static int sflegc_dev_initAndShufflePsiArray(u32 *psi_array, u32 len);
* argv[4]: number of 1 MB slices in the underlying device
* argv[5]: 32-byte encryption key (hex-encoded)
*/
sflegc_Device *sflegc_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj)
struct sflc_device_base *sflegc_dev_ctr(struct dm_target *ti, int argc, char **argv)
{
sflegc_Device * dev;
u32 tot_slices;
u32 dev_id;
int err;
int i;
@ -79,25 +79,25 @@ sflegc_Device *sflegc_dev_create(struct dm_target *ti, int argc, char **argv, st
goto err_alloc_dev;
}
/* Init base part */
err = sflc_dev_base_init(&dev->sd_base, ti, argc, argv);
if (err)
goto bad_base;
dev->sd_base.mode = SFLC_MODE_LEGACY;
dev->sd_base.ops = &sflc_legacy_ops;
/* Parse args */
if (argc != 6) {
pr_err("Wrong argument count");
err = -EINVAL;
goto err_parse;
}
sscanf(argv[1], "%u", &dev_id);
if (sscanf(argv[4], "%u", &tot_slices) != 1) {
pr_err("Could not decode tot_slices\n");
err = -EINVAL;
goto err_parse;
}
/* Init list node here, so it's always safe to list_del() */
INIT_LIST_HEAD(&dev->list_node);
/* Set device ID */
dev->dev_id = dev_id;
/* Set backing real device */
err = dm_get_device(ti, argv[2], dm_table_get_mode(ti->table), &dev->bdev);
if (err) {
@ -105,14 +105,6 @@ sflegc_Device *sflegc_dev_create(struct dm_target *ti, int argc, char **argv, st
goto err_dm_get_dev;
}
dev->ti = ti;
/* And its path */
dev->bdev_path = kmalloc(strlen(argv[2]) + 1, GFP_KERNEL);
if (!dev->bdev_path) {
pr_err("Could not allocate %lu bytes for dev->real_dev_path\n", strlen(argv[2]) + 1);
err = -ENOMEM;
goto err_alloc_real_dev_path;
}
strcpy(dev->bdev_path, argv[2]);
/* Init volumes */
for (i = 0; i < SFLEGC_DEV_MAX_VOLUMES; ++i) {
@ -173,14 +165,13 @@ sflegc_Device *sflegc_dev_create(struct dm_target *ti, int argc, char **argv, st
INIT_LIST_HEAD(&dev->iv_lru_list);
/* Add to sysfs */
dev->kobj_parent = kobj;
err = sflegc_sysfs_add_device(dev);
if (err) {
pr_err("Could not add device to sysfs; error %d\n", err);
goto err_sysfs;
}
return dev;
return &dev->sd_base;
err_sysfs:
@ -191,35 +182,33 @@ err_initshuffle_psi_array:
err_alloc_psi_array:
vfree(dev->rmap);
err_alloc_rmap:
kfree(dev->bdev_path);
err_alloc_real_dev_path:
dm_put_device(ti, dev->bdev);
err_dm_get_dev:
err_parse:
sflc_dev_base_exit(&dev->sd_base);
bad_base:
kfree(dev);
err_alloc_dev:
return ERR_PTR(err);
}
/* Returns false if still busy (not all volumes have been removed). Frees the Device. */
bool sflegc_dev_destroy(sflegc_Device * dev)
void sflegc_dev_dtr(struct sflc_device_base *sd_base)
{
sflegc_Device *dev = container_of(sd_base, sflegc_Device, sd_base);
/* Check if we actually have to put this device */
if (!dev) {
return false;
return;
}
if (dev->vol_cnt > 0) {
pr_warn("Called while still holding %d volumes\n", dev->vol_cnt);
return false;
return;
}
/* Flush all IVs */
sflegc_dev_flushIvs(dev);
/* List */
list_del(&dev->list_node);
/* Sysfs */
sflegc_sysfs_remove_device(dev);
@ -234,12 +223,14 @@ bool sflegc_dev_destroy(sflegc_Device * dev)
/* Backing device */
dm_put_device(dev->ti, dev->bdev);
kfree(dev->bdev_path);
/* Base part */
sflc_dev_base_exit(&dev->sd_base);
/* Free the device itself */
kfree(dev);
return true;
return;
}

View file

@ -50,6 +50,7 @@ typedef struct sflegc_dev_iv_cache_entry_s sflegc_dev_IvCacheEntry;
#include <linux/device-mapper.h>
#include "sflc_types.h"
#include "legacy/sflc_legacy.h"
#include "legacy/volume/volume.h"
#include "legacy/crypto/symkey/symkey.h"
@ -101,13 +102,13 @@ struct sflegc_dev_iv_cache_entry_s
struct sflegc_device_s
{
/* Base device object */
struct sflc_device_base sd_base;
/* Underlying block device */
struct dm_dev * bdev;
char * bdev_path;
/* Target instance that owns the bdev reference */
struct dm_target *ti;
/* Shufflecake-unique numeric ID of this device */
u32 dev_id;
/* All volumes linked to this device */
sflegc_Volume * vol[SFLEGC_DEV_MAX_VOLUMES];
@ -130,18 +131,12 @@ struct sflegc_device_s
u32 vol_header_size;
u32 dev_header_size;
/* Parent sysfs directory */
struct kobject *kobj_parent;
/* LRU cache of IV blocks */
struct mutex iv_cache_lock;
wait_queue_head_t iv_cache_waitqueue;
sflegc_dev_IvCacheEntry ** iv_cache;
u32 iv_cache_nr_entries;
struct list_head iv_lru_list;
/* We keep all devices in a list */
struct list_head list_node;
};
@ -149,17 +144,9 @@ struct sflegc_device_s
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/*
* None of these functions acquire the big device lock: it must be held
* by the caller.
*/
/* Creates Device and adds it to the list. Returns an ERR_PTR() if unsuccessful. */
sflegc_Device * sflegc_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj);
/* Returns false if still busy (not all volumes have been removed) Frees the Device. */
bool sflegc_dev_destroy(sflegc_Device * dev);
struct sflc_device_base *sflegc_dev_ctr(struct dm_target *ti, int argc, char **argv);
void sflegc_dev_dtr(struct sflc_device_base *sd_base);
/* Returns false if volume index was already occupied. */
bool sflegc_dev_addVolume(sflegc_Device * dev, sflegc_Volume * vol, int vol_idx);

View file

@ -31,7 +31,7 @@
#include "legacy/volume/volume.h"
extern struct target_type sflegc_target_type;
extern struct sflc_mode_ops sflc_legacy_ops;
int sflegc_init(void);

View file

@ -43,13 +43,10 @@
/* Show the total number of slices in a device */
static ssize_t tot_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *top_dev;
sflegc_Device * dev;
struct sflc_device_base *sd_base = container_of(kobj, struct sflc_device_base, kobj);
sflegc_Device * dev = container_of(sd_base, sflegc_Device, sd_base);
ssize_t ret;
top_dev = container_of(kobj, struct sflc_device, kobj);
dev = top_dev->sflegc_dev;
/* Write the tot_slices */
ret = sysfs_emit(buf, "%u\n", dev->tot_slices);
@ -59,13 +56,10 @@ static ssize_t tot_slices_show(struct kobject *kobj, struct kobj_attribute *katt
/* Show the number of free slices in a device */
static ssize_t free_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *top_dev;
sflegc_Device * dev;
struct sflc_device_base *sd_base = container_of(kobj, struct sflc_device_base, kobj);
sflegc_Device * dev = container_of(sd_base, sflegc_Device, sd_base);
ssize_t ret;
top_dev = container_of(kobj, struct sflc_device, kobj);
dev = top_dev->sflegc_dev;
/* Write the free_slices */
if (mutex_lock_interruptible(&dev->slices_lock))
return -ERESTARTSYS;
@ -88,12 +82,12 @@ static const struct attribute_group sflegc_device_attr_group = {
int sflegc_sysfs_add_device(sflegc_Device *dev)
{
return sysfs_create_group(dev->kobj_parent, &sflegc_device_attr_group);
return sysfs_create_group(&dev->sd_base.kobj, &sflegc_device_attr_group);
}
void sflegc_sysfs_remove_device(sflegc_Device *dev)
{
sysfs_remove_group(dev->kobj_parent, &sflegc_device_attr_group);
sysfs_remove_group(&dev->sd_base.kobj, &sflegc_device_attr_group);
}
@ -106,13 +100,10 @@ void sflegc_sysfs_remove_device(sflegc_Device *dev)
/* Show the number of mapped slices in a volume */
static ssize_t mapped_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_volume *top_vol;
sflegc_Volume * vol;
struct sflc_volume_base *sv_base = container_of(kobj, struct sflc_volume_base, kobj);
sflegc_Volume * vol = container_of(sv_base, sflegc_Volume, sv_base);
ssize_t ret;
top_vol = container_of(kobj, struct sflc_volume, kobj);
vol = top_vol->sflegc_vol;
/* Write the free_slices */
if (mutex_lock_interruptible(&vol->fmap_lock))
return -ERESTARTSYS;
@ -133,10 +124,10 @@ static const struct attribute_group sflegc_volume_attr_group = {
int sflegc_sysfs_add_volume(sflegc_Volume *vol)
{
return sysfs_create_group(vol->kobj_parent, &sflegc_volume_attr_group);
return sysfs_create_group(&vol->sv_base.kobj, &sflegc_volume_attr_group);
}
void sflegc_sysfs_remove_volume(sflegc_Volume *vol)
{
sysfs_remove_group(vol->kobj_parent, &sflegc_volume_attr_group);
sysfs_remove_group(&vol->sv_base.kobj, &sflegc_volume_attr_group);
}

View file

@ -55,10 +55,14 @@ static int sflegc_tgt_iterateDevices(struct dm_target *ti, iterate_devices_callo
* PUBLIC VARIABLES DEFINITIONS *
*****************************************************/
struct target_type sflegc_target_type = {
.map = sflegc_tgt_map,
.io_hints = sflegc_tgt_ioHints,
.iterate_devices = sflegc_tgt_iterateDevices,
struct sflc_mode_ops sflc_legacy_ops = {
.dev_ctr = sflegc_dev_ctr,
.dev_dtr = sflegc_dev_dtr,
.vol_ctr = sflegc_vol_ctr,
.vol_dtr = sflegc_vol_dtr,
.map = sflegc_tgt_map,
.io_hints = sflegc_tgt_ioHints,
.iterate_devices = sflegc_tgt_iterateDevices,
};
/*****************************************************
@ -70,20 +74,22 @@ struct target_type sflegc_target_type = {
static int sflegc_tgt_map(struct dm_target *ti, struct bio *bio)
{
int err;
struct sflc_volume *top_vol = ti->private;
sflegc_Volume *vol = top_vol->sflegc_vol;
struct sflc_volume_base *sv_base = ti->private;
sflegc_Volume *vol = container_of(sv_base, sflegc_Volume, sv_base);
/* If no data, just quickly remap the sector and the block device (no crypto) */
/* TODO: this is dangerous for deniability, will need more filtering */
if (unlikely(!bio_has_data(bio))) {
pr_debug("No-data bio: bio_op = %d", bio_op(bio));
err = sflegc_vol_remapBioFast(vol, bio);
if (err) {
pr_err("Could not remap bio; error %d\n", err);
/* Copied from sflc_lite */
if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
/* Has to be empty though */
if (bio_sectors(bio)) {
DMWARN("Non-empty flush request!");
//msleep(3000);
return DM_MAPIO_KILL;
}
return DM_MAPIO_REMAPPED;
}
// DMWARN("REQ_PREFLUSH empty (phew), sector: %llu", bio->bi_iter.bi_sector);
// msleep(100);
bio_set_dev(bio, vol->dev->bdev->bdev);
return DM_MAPIO_REMAPPED;
}
/* At this point, the bio has data. Do a few sanity checks */
/* TODO: I think we can get rid of all of them */
@ -117,11 +123,6 @@ static int sflegc_tgt_map(struct dm_target *ti, struct bio *bio)
/* Callback executed to inform the DM about our 4096-byte sector size */
static void sflegc_tgt_ioHints(struct dm_target *ti, struct queue_limits *limits)
{
struct sflc_volume *top_vol = ti->private;
sflegc_Volume *vol = top_vol->sflegc_vol;
pr_info("Called io_hints on volume \"%s\"\n", vol->vol_name);
limits->logical_block_size = SFLEGC_DEV_SECTOR_SIZE;
limits->physical_block_size = SFLEGC_DEV_SECTOR_SIZE;
@ -135,11 +136,10 @@ static void sflegc_tgt_ioHints(struct dm_target *ti, struct queue_limits *limits
static int sflegc_tgt_iterateDevices(struct dm_target *ti, iterate_devices_callout_fn fn,
void *data)
{
struct sflc_volume *top_vol = ti->private;
sflegc_Volume *vol = top_vol->sflegc_vol;
struct sflc_volume_base *sv_base = ti->private;
sflegc_Volume *vol = container_of(sv_base, sflegc_Volume, sv_base);
sflegc_Device * dev = vol->dev;
pr_debug("Called iterate_devices on volume \"%s\"\n", vol->vol_name);
if (!fn) {
return -EINVAL;

View file

@ -137,7 +137,7 @@ int sflegc_vol_loadFmap(sflegc_Volume * vol)
}
/* Starting block of the position map (skip the DMB, the previous volume headers, and the VMB) */
sector = 1 + (vol->vol_idx * dev->vol_header_size) + 1;
sector = 1 + (vol->sv_base.vol_idx * dev->vol_header_size) + 1;
/* Starting LSI in the fmap */
lsi = 0;
@ -182,7 +182,7 @@ int sflegc_vol_loadFmap(sflegc_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 != SFLEGC_VOL_FMAP_INVALID_PSI) {
sflegc_dev_markPsiTaken(dev, psi, vol->vol_idx);
sflegc_dev_markPsiTaken(dev, psi, vol->sv_base.vol_idx);
vol->mapped_slices += 1;
}
@ -247,7 +247,7 @@ int sflegc_vol_storeFmap(sflegc_Volume * vol)
}
/* Starting block of the position map (skip the DMB, the previous volume headers, and the VMB) */
sector = 1 + (vol->vol_idx * dev->vol_header_size) + 1;
sector = 1 + (vol->sv_base.vol_idx * dev->vol_header_size) + 1;
/* Starting LSI in the fmap */
lsi = 0;
@ -366,7 +366,7 @@ static s32 sflegc_vol_mapSlice(sflegc_Volume * vol, u32 lsi, int op)
vol->fmap[lsi] = psi;
vol->mapped_slices += 1;
/* And in the device's rmap */
sflegc_dev_markPsiTaken(dev, psi, vol->vol_idx);
sflegc_dev_markPsiTaken(dev, psi, vol->sv_base.vol_idx);
/* Unlock both maps */
mutex_unlock(&dev->slices_lock);

View file

@ -32,6 +32,7 @@
#include "legacy/volume/volume.h"
#include "legacy/utils/string.h"
#include "legacy/log/log.h"
#include "sflc.h"
#include <linux/vmalloc.h>
@ -50,11 +51,12 @@
* argv[4]: number of 1 MB slices in the underlying device
* argv[5]: 32-byte encryption key (hex-encoded)
*/
sflegc_Volume * sflegc_vol_create(struct dm_target * ti, sflegc_Device* dev,
int argc, char **argv, struct kobject *kobj)
struct sflc_volume_base *sflegc_vol_ctr(struct sflc_device_base *sd_base,
struct dm_target *ti,
int argc, char **argv)
{
sflegc_Volume * vol;
int vol_idx;
sflegc_Device *dev = container_of(sd_base, sflegc_Device, sd_base);
u8 enckey[SFLEGC_SK_KEY_LEN];
int err;
@ -66,17 +68,18 @@ sflegc_Volume * sflegc_vol_create(struct dm_target * ti, sflegc_Device* dev,
goto err_alloc_vol;
}
/* Init base part */
err = sflc_vol_base_init(&vol->sv_base, sd_base, ti, argc, argv);
if (err)
goto bad_base;
vol->sv_base.ops = &sflc_legacy_ops;
/* Parse args */
if (argc != 6) {
pr_err("Wrong argument count");
err = -EINVAL;
goto err_parse;
}
if (sscanf(argv[3], "%u", &vol_idx) != 1) {
pr_err("Could not decode tot_slices\n");
err = -EINVAL;
goto err_parse;
}
/* Decode the encryption key */
if (strlen(argv[5]) != 2 * SFLEGC_SK_KEY_LEN) {
pr_err("Hexadecimal key (length %lu): %s\n", strlen(argv[5]), argv[5]);
@ -90,11 +93,7 @@ sflegc_Volume * sflegc_vol_create(struct dm_target * ti, sflegc_Device* dev,
goto err_parse;
}
/* Set volume name */
sprintf(vol->vol_name, "sflc_%u_%d", dev->dev_id, vol_idx);
/* Sysfs stuff */
vol->kobj_parent = kobj;
err = sflegc_sysfs_add_volume(vol);
if (err) {
pr_err("Could not add volume to sysfs; error %d\n", err);
@ -102,13 +101,12 @@ sflegc_Volume * sflegc_vol_create(struct dm_target * ti, sflegc_Device* dev,
}
/* Backing device */
if (!sflegc_dev_addVolume(dev, vol, vol_idx)) {
if (!sflegc_dev_addVolume(dev, vol, vol->sv_base.vol_idx)) {
pr_err("Could not add volume to device\n");
err = -EINVAL;
goto err_add_to_dev;
}
vol->dev = dev;
vol->vol_idx = vol_idx;
/* Crypto */
vol->skctx = sflegc_sk_createContext(enckey);
@ -131,13 +129,11 @@ sflegc_Volume * sflegc_vol_create(struct dm_target * ti, sflegc_Device* dev,
vol->mapped_slices = 0;
/* Initialise fmap */
pr_notice("Volume opening for volume %s: loading fmap from header\n", vol->vol_name);
err = sflegc_vol_loadFmap(vol);
if (err) {
pr_err("Could not load position map; error %d\n", err);
goto err_load_fmap;
}
pr_debug("Successfully loaded position map for volume %s\n", vol->vol_name);
/* Tell DM we want one SFLC sector at a time */
@ -152,7 +148,7 @@ sflegc_Volume * sflegc_vol_create(struct dm_target * ti, sflegc_Device* dev,
TODO: will need to support them to release slice mappings */
ti->num_discard_bios = 0;
return vol;
return &vol->sv_base;
err_load_fmap:
@ -160,28 +156,29 @@ err_load_fmap:
err_alloc_fmap:
sflegc_sk_destroyContext(vol->skctx);
err_create_skctx:
sflegc_dev_removeVolume(vol->dev, vol->vol_idx);
sflegc_dev_removeVolume(vol->dev, vol->sv_base.vol_idx);
err_add_to_dev:
sflegc_sysfs_remove_volume(vol);
err_sysfs:
err_parse:
sflc_vol_base_exit(&vol->sv_base);
bad_base:
kfree(vol);
err_alloc_vol:
return ERR_PTR(err);
}
/* Removes the volume from the device and frees it. */
void sflegc_vol_destroy(sflegc_Volume * vol)
void sflegc_vol_dtr(struct sflc_volume_base *sv_base)
{
sflegc_Volume *vol = container_of(sv_base, sflegc_Volume, sv_base);
int err;
/* Store fmap */
pr_notice("Going to store position map of volume %s\n", vol->vol_name);
err = sflegc_vol_storeFmap(vol);
if (err) {
pr_err("Could not store position map; error %d\n", err);
}
pr_debug("Successfully stored position map of volume %s\n", vol->vol_name);
/* Free it */
vfree(vol->fmap);
@ -189,11 +186,14 @@ void sflegc_vol_destroy(sflegc_Volume * vol)
sflegc_sk_destroyContext(vol->skctx);
/* Remove from device */
sflegc_dev_removeVolume(vol->dev, vol->vol_idx);
sflegc_dev_removeVolume(vol->dev, vol->sv_base.vol_idx);
/* Destroy sysfs entries */
sflegc_sysfs_remove_volume(vol);
/* Base part */
sflc_vol_base_exit(&vol->sv_base);
/* Free volume structure */
kfree(vol);

View file

@ -47,6 +47,7 @@ typedef struct sflegc_volume_s sflegc_Volume;
#include <linux/blk_types.h>
#include "sflc_types.h"
#include "legacy/sflc_legacy.h"
#include "legacy/device/device.h"
#include "legacy/crypto/symkey/symkey.h"
@ -103,13 +104,11 @@ struct sflegc_vol_decrypt_work_s
struct sflegc_volume_s
{
/* Name of the volume, sflc_<devID>_<volIdx>*/
char vol_name[SFLEGC_VOL_NAME_MAX_LEN + 1];
/* Base volume object */
struct sflc_volume_base sv_base;
/* Backing device */
sflegc_Device * dev;
/* Index of this volume within the device's volume array */
u32 vol_idx;
/* Forward position map */
struct mutex fmap_lock;
@ -117,8 +116,6 @@ struct sflegc_volume_s
/* Stats on the fmap */
u32 mapped_slices;
/* Parent sysfs directory */
struct kobject *kobj_parent;
/* Crypto */
sflegc_sk_Context * skctx;
@ -129,11 +126,10 @@ struct sflegc_volume_s
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/* Creates volume and adds it to the device. Returns an ERR_PTR() if unsuccessful */
sflegc_Volume * sflegc_vol_create(struct dm_target * ti, sflegc_Device* dev,
int argc, char **argv, struct kobject *kobj);
/* Removes the volume from the device and frees it. */
void sflegc_vol_destroy(sflegc_Volume * vol);
struct sflc_volume_base *sflegc_vol_ctr(struct sflc_device_base *sd_base,
struct dm_target *ti,
int argc, char **argv);
void sflegc_vol_dtr(struct sflc_volume_base *sv_base);
/* Remaps the underlying block device and the sector number */
int sflegc_vol_remapBioFast(sflegc_Volume * vol, struct bio * bio);

View file

@ -26,6 +26,7 @@
#include <linux/random.h>
#include <linux/minmax.h>
#include "sflc_lite.h"
#include "sflc.h"
@ -55,11 +56,9 @@ static void fisheryates_u32(u32 *v, u32 len)
* argv[4]: number of 1 MB slices in the underlying device
* argv[5]: 64-byte encryption key (hex-encoded)
*/
struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj)
struct sflc_device_base *sflite_dev_ctr(struct dm_target *ti, int argc, char **argv)
{
struct sflite_device *sdev;
dev_t devt;
u32 dev_id;
u32 tot_slices;
int i;
int err;
@ -70,29 +69,25 @@ struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **a
return ERR_PTR(-ENOMEM);
}
/* Init base part */
err = sflc_dev_base_init(&sdev->sd_base, ti, argc, argv);
if (err)
goto bad_base;
sdev->sd_base.mode = SFLC_MODE_LITE;
sdev->sd_base.ops = &sflc_lite_ops;
/* Parse args */
if (argc != 6) {
pr_err("Wrong argument count");
DMERR("Wrong argument count");
err = -EINVAL;
goto bad_parse;
}
sscanf(argv[1], "%u", &dev_id);
if (sscanf(argv[4], "%u", &tot_slices) != 1) {
pr_err("Could not decode tot_slices\n");
DMERR("Could not decode tot_slices");
err = -EINVAL;
goto bad_parse;
}
sdev->dev_id = dev_id;
/* Look up block device and set name */
err = lookup_bdev(argv[2], &devt);
if (err) {
DMERR("Could not look up block device");
goto bad_lookup;
}
format_dev_t(sdev->name, devt);
/* Compute sizes */
sdev->tot_slices = tot_slices;
sdev->nr_free_slices = tot_slices;
@ -143,7 +138,7 @@ struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **a
/* I/O workqueue */
sdev->io_queue = alloc_workqueue("sflite_%s_io",
WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE,
0, sdev->name);
0, sdev->sd_base.name);
if (!sdev->io_queue) {
err = -ENOMEM;
DMERR("Could not allocate I/O workqueue");
@ -152,7 +147,7 @@ struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **a
/* Decryption workqueue */
sdev->crypt_queue = alloc_workqueue("sflite_%s_crypt",
WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE,
0, sdev->name);
0, sdev->sd_base.name);
if (!sdev->crypt_queue) {
err = -ENOMEM;
DMERR("Could not allocate decryption workqueue");
@ -160,12 +155,11 @@ struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **a
}
/* Add to sysfs, once initialised */
sdev->kobj_parent = kobj;
err = sflite_sysfs_add_device(sdev);
if (err)
goto bad_sysfs;
return sdev;
return &sdev->sd_base;
bad_sysfs:
@ -181,15 +175,18 @@ bad_bioset:
bad_prmslices:
vfree(sdev->slices_ofld);
bad_ofld:
bad_lookup:
bad_parse:
sflc_dev_base_exit(&sdev->sd_base);
bad_base:
kfree(sdev);
return ERR_PTR(err);
}
void sflite_dev_destroy(struct sflite_device *sdev)
void sflite_dev_dtr(struct sflc_device_base *sd_base)
{
struct sflite_device *sdev = container_of(sd_base, struct sflite_device, sd_base);
sflite_sysfs_remove_device(sdev);
destroy_workqueue(sdev->crypt_queue);
destroy_workqueue(sdev->io_queue);
@ -197,6 +194,7 @@ void sflite_dev_destroy(struct sflite_device *sdev)
bioset_exit(&sdev->bioset);
vfree(sdev->prmslices);
vfree(sdev->slices_ofld);
sflc_dev_base_exit(&sdev->sd_base);
kfree(sdev);
return;

View file

@ -311,7 +311,7 @@ static int _deserialise_and_sanitise_posmap(struct sflite_volume *svol)
/* If PSI already taken, sample a new one */
if (sdev->slices_ofld[psi]) {
DMWARN("Corruption of volume %u: LSI %u was evicted from PSI %u",
svol->vol_idx, lsi, psi);
svol->sv_base.vol_idx, lsi, psi);
err = peek_next_free_psi(sdev, &psi);
if (err)
return err;

View file

@ -41,9 +41,9 @@
static int sflite_map(struct dm_target *ti, struct bio *bio)
{
struct sflc_volume_base *sv_base = ti->private;
struct sflite_volume *svol = container_of(sv_base, struct sflite_volume, sv_base);
struct sflite_io *sio = dm_per_bio_data(bio, sizeof(struct sflite_io));
struct sflc_volume *top_vol = ti->private;
struct sflite_volume *svol = top_vol->sflite_vol;
sector_t lblk_num = bio->bi_iter.bi_sector >> SFLITE_BLOCK_SHIFT;
if (unlikely(!bio_has_data(bio))) {
@ -116,8 +116,8 @@ static void sflite_io_hints(struct dm_target *ti, struct queue_limits *limits)
static int sflite_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
{
struct sflc_volume *top_vol = ti->private;
struct sflite_volume *svol = top_vol->sflite_vol;
struct sflc_volume_base *sv_base = ti->private;
struct sflite_volume *svol = container_of(sv_base, struct sflite_volume, sv_base);
struct sflite_device *sdev = svol->sdev;
if (!fn) {
@ -129,7 +129,11 @@ static int sflite_iterate_devices(struct dm_target *ti, iterate_devices_callout_
}
struct target_type sflite_target_type = {
struct sflc_mode_ops sflc_lite_ops = {
.dev_ctr = sflite_dev_ctr,
.dev_dtr = sflite_dev_dtr,
.vol_ctr = sflite_vol_ctr,
.vol_dtr = sflite_vol_dtr,
.map = sflite_map,
.io_hints = sflite_io_hints,
.iterate_devices = sflite_iterate_devices,

View file

@ -29,6 +29,7 @@
#include <linux/sysfs.h>
#include <crypto/skcipher.h>
#include "sflite_constants.h"
#include "sflc_types.h"
#include "sflc_constants.h"
@ -40,10 +41,8 @@
struct sflite_device
{
/* Shufflecake-unique device ID */
u32 dev_id;
/* <MAJOR>:<MINOR> */
char name[16];
/* Base device object */
struct sflc_device_base sd_base;
/* Logical size of each volume */
u32 tot_slices;
@ -58,9 +57,6 @@ struct sflite_device
bool *slices_ofld;
u32 nr_free_slices;
/* Parent sysfs directory */
struct kobject *kobj_parent;
/* Resource sharing */
struct bio_set bioset;
struct dm_io_client *io_client;
@ -70,6 +66,9 @@ struct sflite_device
struct sflite_volume
{
/* Base volume object */
struct sflc_volume_base sv_base;
/* Backing device */
struct sflite_device *sdev;
@ -78,24 +77,17 @@ struct sflite_volume
struct dm_dev *dm_dev;
struct dm_target *ti;
/* Volume index within the device */
u32 vol_idx;
/* Volume name: sflite_<devID>_<volIdx> */
char name[32];
/* Position map */
struct mutex posmap_lock;
u32 *posmap;
u32 nr_mapped_slices;
/* Parent sysfs directory */
struct kobject *kobj_parent;
/* Crypto */
u8 enckey[SFLITE_XTS_KEYLEN];
struct crypto_skcipher *tfm;
};
/* Per-bio data */
struct sflite_io
{
struct sflite_volume *svol;
@ -119,7 +111,7 @@ struct sflite_io
/* Starting sector of position map */
#define SFLITE_POSMAP_START_SECTOR(svol) \
(SFLITE_BLOCK_SCALE * (1 + SFLITE_DEV_MAX_VOLUMES) + \
(svol)->vol_idx * (svol)->sdev->posmap_size_sectors)
(svol)->sv_base.vol_idx * (svol)->sdev->posmap_size_sectors)
/* Physical sector of a remapped bio */
@ -136,7 +128,7 @@ struct sflite_io
*----------------------------
*/
extern struct target_type sflite_target_type;
extern struct sflc_mode_ops sflc_lite_ops;
/*
@ -150,13 +142,14 @@ int sflite_init(void);
void sflite_exit(void);
/* Device */
struct sflite_device *sflite_dev_create(struct dm_target *ti, int argc, char **argv, struct kobject *kobj);
void sflite_dev_destroy(struct sflite_device *sdev);
struct sflc_device_base *sflite_dev_ctr(struct dm_target *ti, int argc, char **argv);
void sflite_dev_dtr(struct sflc_device_base *sd_base);
/* Volume */
struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_device *sdev,
int argc, char **argv, struct kobject *kobj);
void sflite_vol_destroy(struct sflite_volume *svol);
struct sflc_volume_base *sflite_vol_ctr(struct sflc_device_base *sd_base,
struct dm_target *ti,
int argc, char **argv);
void sflite_vol_dtr(struct sflc_volume_base *sv_base);
/* Sysfs */
int sflite_sysfs_add_device(struct sflite_device *sdev);

View file

@ -34,16 +34,16 @@
static ssize_t tot_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *top_dev = container_of(kobj, struct sflc_device, kobj);
struct sflite_device *sdev = top_dev->sflite_dev;
struct sflc_device_base *sd_base = container_of(kobj, struct sflc_device_base, kobj);
struct sflite_device *sdev = container_of(sd_base, struct sflite_device, sd_base);
return sysfs_emit(buf, "%u\n", sdev->tot_slices);
}
static ssize_t free_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *top_dev = container_of(kobj, struct sflc_device, kobj);
struct sflite_device *sdev = top_dev->sflite_dev;
struct sflc_device_base *sd_base = container_of(kobj, struct sflc_device_base, kobj);
struct sflite_device *sdev = container_of(sd_base, struct sflite_device, sd_base);
int ret;
if (mutex_lock_interruptible(&sdev->slices_lock))
@ -67,12 +67,12 @@ static const struct attribute_group sflite_device_attr_group = {
int sflite_sysfs_add_device(struct sflite_device *sdev)
{
return sysfs_create_group(sdev->kobj_parent, &sflite_device_attr_group);
return sysfs_create_group(&sdev->sd_base.kobj, &sflite_device_attr_group);
}
void sflite_sysfs_remove_device(struct sflite_device *sdev)
{
sysfs_remove_group(sdev->kobj_parent, &sflite_device_attr_group);
sysfs_remove_group(&sdev->sd_base.kobj, &sflite_device_attr_group);
}
@ -84,8 +84,8 @@ void sflite_sysfs_remove_device(struct sflite_device *sdev)
static ssize_t mapped_slices_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_volume *top_vol = container_of(kobj, struct sflc_volume, kobj);
struct sflite_volume *svol = top_vol->sflite_vol;
struct sflc_volume_base *sv_base = container_of(kobj, struct sflc_volume_base, kobj);
struct sflite_volume *svol = container_of(sv_base, struct sflite_volume, sv_base);
int ret;
if (mutex_lock_interruptible(&svol->posmap_lock))
@ -107,10 +107,10 @@ static const struct attribute_group sflite_volume_attr_group = {
int sflite_sysfs_add_volume(struct sflite_volume *svol)
{
return sysfs_create_group(svol->kobj_parent, &sflite_volume_attr_group);
return sysfs_create_group(&svol->sv_base.kobj, &sflite_volume_attr_group);
}
void sflite_sysfs_remove_volume(struct sflite_volume *svol)
{
sysfs_remove_group(svol->kobj_parent, &sflite_volume_attr_group);
sysfs_remove_group(&svol->sv_base.kobj, &sflite_volume_attr_group);
}

View file

@ -23,6 +23,7 @@
#include <linux/vmalloc.h>
#include "sflc_lite.h"
#include "sflc.h"
/**
@ -34,11 +35,12 @@
* argv[4]: number of 1 MB slices in the underlying device
* argv[5]: 64-byte encryption key (hex-encoded)
*/
struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_device* sdev,
int argc, char **argv, struct kobject *kobj)
struct sflc_volume_base *sflite_vol_ctr(struct sflc_device_base *sd_base,
struct dm_target *ti,
int argc, char **argv)
{
struct sflite_volume *svol;
u32 vol_idx;
struct sflite_device *sdev = container_of(sd_base, struct sflite_device, sd_base);
int err;
svol = kzalloc(sizeof(*svol), GFP_KERNEL);
@ -47,17 +49,18 @@ struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_devi
return ERR_PTR(-ENOMEM);
}
/* Init base part */
err = sflc_vol_base_init(&svol->sv_base, sd_base, ti, argc, argv);
if (err)
goto bad_base;
svol->sv_base.ops = &sflc_lite_ops;
/* Parse arguments */
if (argc != 6) {
DMERR("Wrong argument count");
err = -EINVAL;
goto bad_parse;
}
if (sscanf(argv[3], "%u", &vol_idx) != 1) {
DMERR("Could not decode tot_slices\n");
err = -EINVAL;
goto bad_parse;
}
/* Decode the encryption key */
if (strlen(argv[5]) != 2 * SFLITE_XTS_KEYLEN) {
DMERR("Invalid key length");
@ -72,11 +75,9 @@ struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_devi
}
svol->sdev = sdev;
svol->vol_idx = vol_idx;
sprintf(svol->name, "sflc_%u_%u", sdev->dev_id, vol_idx);
svol->ti = ti;
err = dm_get_device(ti, sdev->name,
err = dm_get_device(ti, sdev->sd_base.name,
dm_table_get_mode(ti->table), &svol->dm_dev);
if (err) {
ti->error = "Device lookup failed";
@ -114,7 +115,6 @@ struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_devi
}
/* Add to sysfs, once initialised */
svol->kobj_parent = kobj;
err = sflite_sysfs_add_volume(svol);
if (err) {
DMERR("Could not register volume with sysfs; error %d", err);
@ -133,7 +133,7 @@ struct sflite_volume *sflite_vol_create(struct dm_target *ti, struct sflite_devi
ti->per_io_data_size = sizeof(struct sflite_io);
ti->private = svol;
return svol;
return &svol->sv_base;
bad_sysfs:
@ -146,17 +146,22 @@ bad_tfm_alloc:
dm_put_device(ti, svol->dm_dev);
bad_dm_dev:
bad_parse:
sflc_vol_base_exit(&svol->sv_base);
bad_base:
kfree(svol);
return ERR_PTR(err);
}
void sflite_vol_destroy(struct sflite_volume *svol)
void sflite_vol_dtr(struct sflc_volume_base *sv_base)
{
struct sflite_volume *svol = container_of(sv_base, struct sflite_volume, sv_base);
sflite_sysfs_remove_volume(svol);
vfree(svol->posmap);
crypto_free_skcipher(svol->tfm);
dm_put_device(svol->ti, svol->dm_dev);
sflc_vol_base_exit(&svol->sv_base);
kfree(svol);
return;

View file

@ -32,14 +32,22 @@
#include <linux/delay.h>
// Global variables
/* Global variables */
// A set of algorithms for each Shufflecake mode, in the same order as the modes.
struct sflc_mode_ops *sflc_all_mode_ops[SFLC_NR_MODES] = {
&sflc_legacy_ops,
&sflc_lite_ops
};
// Global array of base device objects
DEFINE_MUTEX(sflc_alldevs_lock);
struct sflc_device **sflc_alldevs = NULL;
struct sflc_device_base **sflc_alldevs = NULL;
u32 sflc_free_devid = 0; /* The lowest free devID */
/* Add a device to the global array, and advance next_dev_id */
static int sflc_add_device_global(u32 dev_id, struct sflc_device *sdev)
static int sflc_add_device_global(u32 dev_id, struct sflc_device_base *sd_base)
{
int i;
@ -54,7 +62,7 @@ static int sflc_add_device_global(u32 dev_id, struct sflc_device *sdev)
return -EINVAL;
}
// Add to the global array, and advance free_devid
sflc_alldevs[dev_id] = sdev;
sflc_alldevs[dev_id] = sd_base;
for (i = sflc_free_devid; i < SFLC_MAX_DEVS && sflc_alldevs[i]; i++);
sflc_free_devid = i;
@ -86,10 +94,12 @@ static void sflc_remove_device_global(u32 dev_id)
*/
static int sflc_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
u32 mode;
struct sflc_mode_ops *mode_ops;
u32 dev_id;
u32 vol_idx;
struct sflc_device *sdev;
struct sflc_volume *svol;
struct sflc_device_base *sd_base;
struct sflc_volume_base *sv_base;
int err;
/* Parse arguments */
@ -97,6 +107,10 @@ static int sflc_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ti->error = "Invalid argument count";
return -EINVAL;
}
if (sscanf(argv[0], "%u", &mode) != 1) {
ti->error = "Could not decode mode";
return -EINVAL;
}
if (sscanf(argv[1], "%u", &dev_id) != 1) {
ti->error = "Could not decode device ID";
return -EINVAL;
@ -106,6 +120,10 @@ static int sflc_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return -EINVAL;
}
/* Sanity checks */
if (mode >= SFLC_NR_MODES) {
ti->error = "Mode out of bounds";
return -EINVAL;
}
if (dev_id >= SFLC_MAX_DEVS) {
ti->error = "Device ID out of bounds";
return -EINVAL;
@ -114,16 +132,18 @@ static int sflc_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ti->error = "Volume index out of bounds";
return -EINVAL;
}
/* Grab the correct mode */
mode_ops = sflc_all_mode_ops[mode];
/* Create device, if this is the first volume, otherwise retrieve it */
if (vol_idx == 0) {
sdev = sflc_dev_create(ti, argc, argv);
if (IS_ERR(sdev)) {
sd_base = mode_ops->dev_ctr(ti, argc, argv);
if (IS_ERR(sd_base)) {
ti->error = "Could not instantiate device";
return PTR_ERR(sdev);
return PTR_ERR(sd_base);
}
/* Insert in global array */
err = sflc_add_device_global(dev_id, sdev);
err = sflc_add_device_global(dev_id, sd_base);
if (err) {
ti->error = "Could not add device to global array";
goto bad_dev_global;
@ -131,26 +151,26 @@ static int sflc_ctr(struct dm_target *ti, unsigned int argc, char **argv)
} else {
if (mutex_lock_interruptible(&sflc_alldevs_lock))
return -ERESTARTSYS;
sdev = sflc_alldevs[dev_id];
sd_base = sflc_alldevs[dev_id];
mutex_unlock(&sflc_alldevs_lock);
if (!sdev) {
if (!sd_base) {
ti->error = "Could not find device with specified ID";
return -EINVAL;
}
}
/* Create volume */
svol = sflc_vol_create(sdev, ti, argc, argv);
if (IS_ERR(svol)) {
sv_base = mode_ops->vol_ctr(sd_base, ti, argc, argv);
if (IS_ERR(sv_base)) {
ti->error = "Could not instantiate volume";
err = PTR_ERR(svol);
err = PTR_ERR(sv_base);
goto bad_vol_create;
}
/* We expect ->ctr() calls to be strictly sequential, so we don't need locking */
sdev->nr_volumes++;
sd_base->nr_volumes++;
ti->private = svol;
ti->private = sv_base;
return 0;
@ -159,7 +179,7 @@ bad_vol_create:
if (vol_idx == 0) {
sflc_remove_device_global(dev_id);
bad_dev_global:
sflc_dev_destroy(sdev);
mode_ops->dev_dtr(sd_base);
}
return err;
}
@ -168,16 +188,16 @@ bad_dev_global:
/* Destroy volume and, if needed, the underlying device */
static void sflc_dtr(struct dm_target *ti)
{
struct sflc_volume *svol = ti->private;
struct sflc_device *sdev = svol->sdev;
struct sflc_volume_base *sv_base = ti->private;
struct sflc_device_base *sd_base = sv_base->sd_base;
sflc_vol_destroy(svol);
sv_base->ops->vol_dtr(sv_base);
/* We expect ->dtr() calls to be strictly sequential, so we don't need locking */
sdev->nr_volumes--;
sd_base->nr_volumes--;
if (sdev->nr_volumes == 0) {
sflc_remove_device_global(sdev->dev_id);
sflc_dev_destroy(sdev);
if (sd_base->nr_volumes == 0) {
sflc_remove_device_global(sd_base->dev_id);
sd_base->ops->dev_dtr(sd_base);
}
return;
@ -186,21 +206,21 @@ static void sflc_dtr(struct dm_target *ti)
static int sflc_map(struct dm_target *ti, struct bio *bio)
{
struct sflc_volume *svol = ti->private;
return svol->tt->map(ti, bio);
struct sflc_volume_base *sv_base = ti->private;
return sv_base->ops->map(ti, bio);
}
static void sflc_io_hints(struct dm_target *ti, struct queue_limits *limits)
{
struct sflc_volume *svol = ti->private;
svol->tt->io_hints(ti, limits);
struct sflc_volume_base *sv_base = ti->private;
return sv_base->ops->io_hints(ti, limits);
return;
}
static int sflc_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
{
struct sflc_volume *svol = ti->private;
return svol->tt->iterate_devices(ti, fn, data);
struct sflc_volume_base *sv_base = ti->private;
return sv_base->ops->iterate_devices(ti, fn, data);
}

View file

@ -27,58 +27,8 @@
#include <linux/device-mapper.h>
#include "sflc_types.h"
#include "sflc_constants.h"
#include "legacy/sflc_legacy.h"
#include "lite/sflc_lite.h"
/*
*----------------------------
* Structs
*----------------------------
*/
struct sflc_device
{
/* Shufflecake-unique device ID */
u32 dev_id;
/* <MAJOR>:<MINOR> */
char name[16];
/* Number of volumes */
u32 nr_volumes;
/* Mode-specific device struct */
int mode;
union {
sflegc_Device *sflegc_dev;
struct sflite_device *sflite_dev;
};
/* Sysfs */
struct kobject kobj;
struct completion kobj_released;
};
struct sflc_volume
{
/* Backing device */
struct sflc_device *sdev;
/* Volume name: sflc_<devID>_<volIdx> */
char name[32];
/* Mode-specific volume struct */
int mode;
union {
sflegc_Volume *sflegc_vol;
struct sflite_volume *sflite_vol;
};
/* Pointers to concrete, mode-specific callbacks */
struct target_type *tt;
/* Sysfs */
struct kobject kobj;
struct completion kobj_released;
};
/*
@ -87,8 +37,12 @@ struct sflc_volume
*----------------------------
*/
/* Every mode provides a full set of algorithms */
extern struct sflc_mode_ops *sflc_all_mode_ops[SFLC_NR_MODES];
/* Array of all open devices */
extern struct mutex sflc_alldevs_lock;
extern struct sflc_device **sflc_alldevs;
extern struct sflc_device_base **sflc_alldevs;
/* Next free device id */
extern u32 sflc_free_devid; /* The lowest free devID */
@ -99,22 +53,24 @@ extern u32 sflc_free_devid; /* The lowest free devID */
*----------------------------
*/
/* Device */
struct sflc_device *sflc_dev_create(struct dm_target *ti, int argc, char **argv);
void sflc_dev_destroy(struct sflc_device *sdev);
/* Device base */
int sflc_dev_base_init(struct sflc_device_base *sd_base, struct dm_target *ti,
int argc, char **argv);
void sflc_dev_base_exit(struct sflc_device_base *sd_base);
/* Volume */
struct sflc_volume *sflc_vol_create(struct sflc_device *sdev, struct dm_target *ti,
int argc, char **argv);
void sflc_vol_destroy(struct sflc_volume *svol);
/* Volume base */
int sflc_vol_base_init(struct sflc_volume_base *sv_base,
struct sflc_device_base *sd_base, struct dm_target *ti,
int argc, char **argv);
void sflc_vol_base_exit(struct sflc_volume_base *sv_base);
/* Sysfs */
int sflc_sysfs_init(void);
void sflc_sysfs_exit(void);
int sflc_sysfs_register_device(struct sflc_device *sdev);
void sflc_sysfs_unregister_device(struct sflc_device *sdev);
int sflc_sysfs_register_volume(struct sflc_volume *svol);
void sflc_sysfs_unregister_volume(struct sflc_volume *svol);
int sflc_sysfs_register_device_base(struct sflc_device_base *sd_base);
void sflc_sysfs_unregister_device_base(struct sflc_device_base *sd_base);
int sflc_sysfs_register_volume_base(struct sflc_volume_base *sv_base);
void sflc_sysfs_unregister_volume_base(struct sflc_volume_base *sv_base);
#endif /* _SFLC_H */

View file

@ -33,8 +33,8 @@
#define SFLC_VER_MAJOR 0
#define SFLC_VER_MINOR 5
#define SFLC_VER_REVISION 0
#define SFLC_VER_SPECIAL "rc1"
#define SFLC_VER_REVISION 1
#define SFLC_VER_SPECIAL ""
#define STRINGIFY0(s) # s
#define STRINGIFY(s) STRINGIFY0(s)
@ -45,6 +45,7 @@
/* Each device can be formatted and used with a mode of choice, irrespective of the other devices */
#define SFLC_MODE_LEGACY 0
#define SFLC_MODE_LITE 1
#define SFLC_NR_MODES 2
/* Max number of volumes per device */

155
dm-sflc/src/sflc_types.h Normal file
View file

@ -0,0 +1,155 @@
/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 2 of the License, or (at your option)
* any later version. This program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the
* GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/
/**
* This kernel module implements Shufflecake as an in-kernel device driver,
* built on top of the device-mapper framework.
* Shufflecake supports several "modes" (currently Legacy and Lite). Each mode
* is a distinct set of algorithms which implements a specific flavour of the
* Shufflecake scheme; they are very different and largely incompatible with
* each other. For this reason, each mode has its own independent, complete
* implementation - located in a subdirectory of the root - and exposes a
* standardised interface to the top-level "dispatcher", which only takes care
* of the few bookkeeping tasks which are common to all modes, and displays a
* unified view to user space through the sysfs.
*
* In order to achieve an intuitive and maintainable separation between the
* dispatcher and the modes, a "lightweight" OOP-style coding convention is
* followed: not fully general, but just enough to allow for one-level class
* inheritance and type-checked method polymorphism.
* Base "classes" exist to represent devices and volumes (see Shufflecake docs
* to learn what these terms mean): they are structs containing the fields
* needed by the dispatcher for its bookkeeping. Derived "classes" exist to
* represent mode-specific devices and volumes: they are structs embedding a
* base-class struct "by-value", plus their own specific fields.
* Type-checked polymorphism is achieved by having device and volume methods
* take as argument a pointer to a base-class struct, instead of an opaque void
* pointer. The pointer is then "down-cast" in the mode-specific method.
*/
#ifndef _SFLC_TYPES_H
#define _SFLC_TYPES_H
#include <linux/device-mapper.h>
#include "sflc_constants.h"
/*
*----------------------------
* Structs
*----------------------------
*/
/**
* The virtual table.
* Contains all the concrete method pointers provided by a Shufflecake mode
* (devices + volumes + devmapper).
* It is a field in the base class, but will be set by the constructor of the
* derived class.
*/
struct sflc_mode_ops;
/**
* Base class for devices.
* It is inherited by derived classes for mode-specific devices.
*/
struct sflc_device_base
{
/* Shufflecake-unique device ID */
u32 dev_id;
/* <MAJOR>:<MINOR> */
char name[16];
/* Shufflecake mode: legacy/lite */
u32 mode;
/* Number of (open) volumes */
u32 nr_volumes;
/* Sysfs */
struct kobject kobj;
struct completion kobj_released;
/* Virtual table */
struct sflc_mode_ops *ops;
};
/**
* Base class for volumes.
* It is inherited by derived classes for mode-specific volumes.
*/
struct sflc_volume_base
{
/* Backing device */
struct sflc_device_base *sd_base;
/* Volume index within the device */
u32 vol_idx;
/* Volume name: sflc_<devID>_<volIdx> */
char name[32];
/* Sysfs */
struct kobject kobj;
struct completion kobj_released;
/* Virtual table */
struct sflc_mode_ops *ops;
};
/*
*----------------------------
* Methods
*----------------------------
*/
/* Device constructor */
typedef struct sflc_device_base* (*sflc_mode_dev_ctr_fn) (
struct dm_target *ti, int argc, char **argv);
/* Device destructor */
typedef void (*sflc_mode_dev_dtr_fn) (struct sflc_device_base* sd_base);
/* Volume constructor */
typedef struct sflc_volume_base* (*sflc_mode_vol_ctr_fn) (
struct sflc_device_base *sd_base, struct dm_target *ti,
int argc, char **argv);
/* Volume destructor */
typedef void (*sflc_mode_vol_dtr_fn) (struct sflc_volume_base* sv_base);
/**
* A Shufflecake mode must provide ctr() and dtr() for devices and volumes,
* as well as devmapper-related methods.
*/
struct sflc_mode_ops
{
sflc_mode_dev_ctr_fn dev_ctr;
sflc_mode_dev_dtr_fn dev_dtr;
sflc_mode_vol_ctr_fn vol_ctr;
sflc_mode_vol_dtr_fn vol_dtr;
dm_map_fn map;
dm_io_hints_fn io_hints;
dm_iterate_devices_fn iterate_devices;
};
#endif /* _SFLC_TYPES_H */

View file

@ -87,16 +87,16 @@ void sflc_sysfs_exit()
static ssize_t dev_id_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *sdev = container_of(kobj, struct sflc_device, kobj);
struct sflc_device_base *sd_base = container_of(kobj, struct sflc_device_base, kobj);
return sysfs_emit(buf, "%u\n", sdev->dev_id);
return sysfs_emit(buf, "%u\n", sd_base->dev_id);
}
static ssize_t volumes_show(struct kobject *kobj, struct kobj_attribute *kattr, char *buf)
{
struct sflc_device *sdev = container_of(kobj, struct sflc_device, kobj);
struct sflc_device_base *sd_base = container_of(kobj, struct sflc_device_base, kobj);
return sysfs_emit(buf, "%u\n", sdev->nr_volumes);
return sysfs_emit(buf, "%u\n", sd_base->nr_volumes);
}
@ -109,47 +109,47 @@ static struct attribute *sflc_device_default_attrs[] = {
};
ATTRIBUTE_GROUPS(sflc_device_default);
static void sflc_device_kobj_release(struct kobject *kobj)
static void sflc_device_base_kobj_release(struct kobject *kobj)
{
struct sflc_device *sdev = container_of(kobj, struct sflc_device, kobj);
complete(&sdev->kobj_released);
struct sflc_device_base *sd_base = container_of(kobj, struct sflc_device_base, kobj);
complete(&sd_base->kobj_released);
}
static struct kobj_type sflc_device_ktype = {
.release = sflc_device_kobj_release,
static struct kobj_type sflc_device_base_ktype = {
.release = sflc_device_base_kobj_release,
.sysfs_ops = &kobj_sysfs_ops,
.default_groups = sflc_device_default_groups
};
int sflc_sysfs_register_device(struct sflc_device *sdev)
int sflc_sysfs_register_device_base(struct sflc_device_base *sd_base)
{
int err;
/* Completion */
init_completion(&sdev->kobj_released);
init_completion(&sd_base->kobj_released);
/* Register directory <MAJOR>:<MINOR>/ under bdevs/ */
sdev->kobj.kset = bdevs_kset;
err = kobject_init_and_add(&sdev->kobj, &sflc_device_ktype, NULL,
"%s", sdev->name);
sd_base->kobj.kset = bdevs_kset;
err = kobject_init_and_add(&sd_base->kobj, &sflc_device_base_ktype, NULL,
"%s", sd_base->name);
if (err)
goto bad;
/* Emit uevent */
kobject_uevent(&sdev->kobj, KOBJ_ADD);
kobject_uevent(&sd_base->kobj, KOBJ_ADD);
return 0;
bad:
kobject_put(&sdev->kobj);
wait_for_completion(&sdev->kobj_released);
kobject_put(&sd_base->kobj);
wait_for_completion(&sd_base->kobj_released);
return err;
}
void sflc_sysfs_unregister_device(struct sflc_device *sdev)
void sflc_sysfs_unregister_device_base(struct sflc_device_base *sd_base)
{
kobject_put(&sdev->kobj);
wait_for_completion(&sdev->kobj_released);
kobject_put(&sd_base->kobj);
wait_for_completion(&sd_base->kobj_released);
}
@ -159,45 +159,47 @@ void sflc_sysfs_unregister_device(struct sflc_device *sdev)
*----------------------------
*/
static void sflc_volume_kobj_release(struct kobject *kobj)
static void sflc_volume_base_kobj_release(struct kobject *kobj)
{
struct sflc_volume *svol = container_of(kobj, struct sflc_volume, kobj);
struct sflc_volume_base *sv_base = container_of(kobj, struct sflc_volume_base, kobj);
complete(&svol->kobj_released);
complete(&sv_base->kobj_released);
}
static struct kobj_type sflc_volume_ktype = {
.release = sflc_volume_kobj_release,
static struct kobj_type sflc_volume_base_ktype = {
.release = sflc_volume_base_kobj_release,
.sysfs_ops = &kobj_sysfs_ops,
};
int sflc_sysfs_register_volume(struct sflc_volume *svol)
int sflc_sysfs_register_volume_base(struct sflc_volume_base *sv_base)
{
int err;
/* Completion */
init_completion(&svol->kobj_released);
init_completion(&sv_base->kobj_released);
/* Register directory <svol->name>/ under device directory */
err = kobject_init_and_add(&svol->kobj, &sflc_volume_ktype, &svol->sdev->kobj,
"%s", svol->name);
err = kobject_init_and_add(&sv_base->kobj, &sflc_volume_base_ktype,
&sv_base->sd_base->kobj,
"%s", sv_base->name);
if (err)
goto bad;
/* Emit uevent */
kobject_uevent(&svol->kobj, KOBJ_ADD);
kobject_uevent(&sv_base->kobj, KOBJ_ADD);
return 0;
bad:
kobject_put(&svol->kobj);
wait_for_completion(&svol->kobj_released);
kobject_put(&sv_base->kobj);
wait_for_completion(&sv_base->kobj_released);
return err;
}
void sflc_sysfs_unregister_volume(struct sflc_volume *svol)
void sflc_sysfs_unregister_volume_base(struct sflc_volume_base *sv_base)
{
kobject_put(&svol->kobj);
wait_for_completion(&svol->kobj_released);
kobject_put(&sv_base->kobj);
wait_for_completion(&sv_base->kobj_released);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -29,8 +29,8 @@
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="2.7438272"
inkscape:cx="234.16198"
inkscape:cy="198.26321"
inkscape:cx="234.52643"
inkscape:cy="227.41957"
inkscape:window-width="1920"
inkscape:window-height="975"
inkscape:window-x="0"
@ -333,7 +333,7 @@
height="5.2916675"
x="61.548569"
y="79.569435"
inkscape:export-filename="badge_version_0.5.0.png"
inkscape:export-filename="badge_version_0.5.1.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96" />
<text
@ -364,7 +364,7 @@
id="tspan462"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.183262"
x="79.882088"
y="83.4077">0.5.0</tspan></text>
y="83.4077">0.5.1</tspan></text>
<rect
style="fill:#951b89;fill-opacity:1;stroke:none;stroke-width:0.245683;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect358"

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before After
Before After