mirror of
https://codeberg.org/shufflecake/shufflecake-c.git
synced 2026-01-03 01:25:38 -05:00
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:
commit
c54777659d
26 changed files with 485 additions and 512 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
|
@ -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
|
||||
|
|
|
|||
37
README.md
37
README.md
|
|
@ -1,5 +1,5 @@
|
|||
[](https://codeberg.org/shufflecake/shufflecake-c)
|
||||
[](https://codeberg.org/shufflecake/shufflecake-c/releases/tag/v0.5.0)
|
||||
[](https://codeberg.org/shufflecake/shufflecake-c/releases/tag/v0.5.1)
|
||||
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||
[](https://eprint.iacr.org/2023/1529)
|
||||
[](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
1
dm-sflc/bin/sflc_types.h
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../src/sflc_types.h
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
155
dm-sflc/src/sflc_types.h
Normal 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 */
|
||||
|
|
@ -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 |
BIN
resources/images/badges/badge_version_0.5.1.png
Normal file
BIN
resources/images/badges/badge_version_0.5.1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
|
|
@ -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 |
Loading…
Add table
Add a link
Reference in a new issue