mirror of
https://codeberg.org/shufflecake/shufflecake-c.git
synced 2026-01-08 03:55:49 -05:00
Add support for args struct in top level
This commit is contained in:
parent
d9e3745a33
commit
6206dd4898
4 changed files with 127 additions and 68 deletions
|
|
@ -25,24 +25,78 @@
|
|||
#include "legacy/sflc_legacy.h"
|
||||
|
||||
|
||||
/* Init a sflc_device_base */
|
||||
int sflc_dev_base_init(struct sflc_device_base *sd_base, struct dm_target *ti,
|
||||
int argc, char **argv)
|
||||
/*
|
||||
*----------------------------
|
||||
* Public functions
|
||||
*----------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Arguments:
|
||||
* argv[0]: Shufflecake mode: legacy/lite
|
||||
* argv[1]: Shufflecake-unique device ID
|
||||
* argv[2]: path to underlying physical device
|
||||
* argv[3]: volume index within the device
|
||||
* argv[4:]: mode-specific parameters
|
||||
*/
|
||||
int sflc_ctor_args_base_init(struct sflc_ctor_args_base *args_base,
|
||||
int argc, char **argv)
|
||||
{
|
||||
u32 dev_id;
|
||||
dev_t devt;
|
||||
int err;
|
||||
|
||||
/* Parse arguments */
|
||||
sscanf(argv[1], "%u", &dev_id);
|
||||
err = lookup_bdev(argv[2], &devt);
|
||||
if (err)
|
||||
/* At least 4 arguments */
|
||||
if (argc < 4) {
|
||||
DMERR("Invalid argument count");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Parse the "generic" arguments */
|
||||
if (sscanf(argv[0], "%u", &args_base->mode) != 1) {
|
||||
DMERR("Could not decode mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (sscanf(argv[1], "%u", &args_base->dev_id) != 1) {
|
||||
DMERR("Could not decode device ID");
|
||||
return -EINVAL;
|
||||
}
|
||||
err = lookup_bdev(argv[2], &args_base->bdev_devt);
|
||||
if (err) {
|
||||
DMERR("Could not lookup bdev");
|
||||
return err;
|
||||
}
|
||||
if (sscanf(argv[3], "%u", &args_base->vol_idx) != 1) {
|
||||
DMERR("Could not decode volume index");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Sanity checks */
|
||||
if (args_base->mode >= SFLC_NR_MODES) {
|
||||
DMERR("Mode out of bounds");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (args_base->dev_id >= SFLC_MAX_DEVS) {
|
||||
DMERR("Device ID out of bounds");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (args_base->vol_idx >= SFLC_DEV_MAX_VOLUMES) {
|
||||
DMERR("Volume index out of bounds");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Init a sflc_device_base */
|
||||
int sflc_dev_base_init(struct sflc_device_base *sd_base, struct dm_target *ti,
|
||||
struct sflc_ctor_args_base *args_base)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Assign fields */
|
||||
sd_base->dev_id = dev_id;
|
||||
sd_base->dev_id = args_base->dev_id;
|
||||
sd_base->nr_volumes = 0;
|
||||
format_dev_t(sd_base->name, devt);
|
||||
format_dev_t(sd_base->name, args_base->bdev_devt);
|
||||
/* Fields `mode` and `ops` will be set by the derived constructor */
|
||||
|
||||
/* Register with sysfs */
|
||||
|
|
@ -54,25 +108,23 @@ int sflc_dev_base_init(struct sflc_device_base *sd_base, struct dm_target *ti,
|
|||
}
|
||||
|
||||
|
||||
/* Just unregister from sysfs */
|
||||
void sflc_dev_base_exit(struct sflc_device_base *sd_base)
|
||||
{
|
||||
sflc_sysfs_unregister_device_base(sd_base);
|
||||
}
|
||||
|
||||
|
||||
/* 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_ctor_args_base *args_base)
|
||||
{
|
||||
u32 vol_idx;
|
||||
int err;
|
||||
|
||||
/* Parse arguments */
|
||||
sscanf(argv[3], "%u", &vol_idx);
|
||||
|
||||
/* Assign fields */
|
||||
sv_base->vol_idx = vol_idx;
|
||||
sprintf(sv_base->name, "sflc_%u_%u", sd_base->dev_id, vol_idx);
|
||||
sv_base->vol_idx = args_base->vol_idx;
|
||||
sprintf(sv_base->name, "sflc_%u_%u", sd_base->dev_id, args_base->vol_idx);
|
||||
sv_base->sd_base = sd_base;
|
||||
/* Field `ops` will be set by the derived constructor */
|
||||
|
||||
|
|
@ -84,6 +136,9 @@ int sflc_vol_base_init(struct sflc_volume_base *sv_base,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Just unregister from sysfs */
|
||||
|
||||
void sflc_vol_base_exit(struct sflc_volume_base *sv_base)
|
||||
{
|
||||
sflc_sysfs_unregister_volume_base(sv_base);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,11 @@
|
|||
#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] = {
|
||||
|
|
@ -43,8 +47,16 @@ struct sflc_mode_ops *sflc_all_mode_ops[SFLC_NR_MODES] = {
|
|||
// Global array of base device objects
|
||||
DEFINE_MUTEX(sflc_alldevs_lock);
|
||||
struct sflc_device_base **sflc_alldevs = NULL;
|
||||
u32 sflc_free_devid = 0; /* The lowest free devID */
|
||||
|
||||
/* The lowest free devID */
|
||||
u32 sflc_free_devid = 0;
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------
|
||||
* Helper functions
|
||||
*----------------------------
|
||||
*/
|
||||
|
||||
/* Add a device to the global array, and advance next_dev_id */
|
||||
static int sflc_add_device_global(u32 dev_id, struct sflc_device_base *sd_base)
|
||||
|
|
@ -83,67 +95,48 @@ static void sflc_remove_device_global(u32 dev_id)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------
|
||||
* Devmapper functions
|
||||
*----------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create volume and, if not existent, the underlying device.
|
||||
* Arguments:
|
||||
* argv[0]: Shufflecake mode: legacy/lite
|
||||
* argv[1]: Shufflecake-unique device ID
|
||||
* argv[2]: path to underlying physical device
|
||||
* argv[3]: volume index within the device
|
||||
* argv[4:]: mode-specific parameters
|
||||
*/
|
||||
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_ctor_args_base *args;
|
||||
struct sflc_device_base *sd_base;
|
||||
struct sflc_volume_base *sv_base;
|
||||
int err;
|
||||
|
||||
/* Parse arguments */
|
||||
if (argc < 4) {
|
||||
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;
|
||||
}
|
||||
if (sscanf(argv[3], "%u", &vol_idx) != 1) {
|
||||
ti->error = "Could not decode volume index";
|
||||
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;
|
||||
}
|
||||
if (vol_idx >= SFLC_DEV_MAX_VOLUMES) {
|
||||
ti->error = "Volume index out of bounds";
|
||||
|
||||
/* Only parse the mode argument (this is duplicated) */
|
||||
if ((argc < 1) || (sscanf(argv[0], "%u", &mode) != 1)) {
|
||||
DMERR("Could not decode mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Grab the correct mode */
|
||||
mode_ops = sflc_all_mode_ops[mode];
|
||||
/* Parse the rest of the arguments */
|
||||
args = mode_ops->parse_args(argc, argv);
|
||||
if (IS_ERR(args)) {
|
||||
DMERR("Could parse arguments");
|
||||
return PTR_ERR(args);
|
||||
}
|
||||
|
||||
/* Create device, if this is the first volume, otherwise retrieve it */
|
||||
if (vol_idx == 0) {
|
||||
sd_base = mode_ops->dev_ctr(ti, argc, argv);
|
||||
if (args->vol_idx == 0) {
|
||||
sd_base = mode_ops->dev_ctr(ti, args);
|
||||
if (IS_ERR(sd_base)) {
|
||||
ti->error = "Could not instantiate device";
|
||||
return PTR_ERR(sd_base);
|
||||
}
|
||||
/* Insert in global array */
|
||||
err = sflc_add_device_global(dev_id, sd_base);
|
||||
err = sflc_add_device_global(args->dev_id, sd_base);
|
||||
if (err) {
|
||||
ti->error = "Could not add device to global array";
|
||||
goto bad_dev_global;
|
||||
|
|
@ -151,7 +144,7 @@ static int sflc_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|||
} else {
|
||||
if (mutex_lock_interruptible(&sflc_alldevs_lock))
|
||||
return -ERESTARTSYS;
|
||||
sd_base = sflc_alldevs[dev_id];
|
||||
sd_base = sflc_alldevs[args->dev_id]; //TODO is locking redundant?
|
||||
mutex_unlock(&sflc_alldevs_lock);
|
||||
|
||||
if (!sd_base) {
|
||||
|
|
@ -161,7 +154,7 @@ static int sflc_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|||
}
|
||||
|
||||
/* Create volume */
|
||||
sv_base = mode_ops->vol_ctr(sd_base, ti, argc, argv);
|
||||
sv_base = mode_ops->vol_ctr(sd_base, ti, args);
|
||||
if (IS_ERR(sv_base)) {
|
||||
ti->error = "Could not instantiate volume";
|
||||
err = PTR_ERR(sv_base);
|
||||
|
|
@ -176,8 +169,8 @@ static int sflc_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|||
|
||||
|
||||
bad_vol_create:
|
||||
if (vol_idx == 0) {
|
||||
sflc_remove_device_global(dev_id);
|
||||
if (args->vol_idx == 0) {
|
||||
sflc_remove_device_global(args->dev_id);
|
||||
bad_dev_global:
|
||||
mode_ops->dev_dtr(sd_base);
|
||||
}
|
||||
|
|
@ -214,7 +207,6 @@ static void sflc_io_hints(struct dm_target *ti, struct queue_limits *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)
|
||||
|
|
|
|||
|
|
@ -53,15 +53,19 @@ extern u32 sflc_free_devid; /* The lowest free devID */
|
|||
*----------------------------
|
||||
*/
|
||||
|
||||
/* Ctor args base */
|
||||
int sflc_ctor_args_base_init(struct sflc_ctor_args_base *args_base,
|
||||
int argc, char **argv);
|
||||
|
||||
/* Device base */
|
||||
int sflc_dev_base_init(struct sflc_device_base *sd_base, struct dm_target *ti,
|
||||
int argc, char **argv);
|
||||
struct sflc_ctor_args_base *args_base);
|
||||
void sflc_dev_base_exit(struct sflc_device_base *sd_base);
|
||||
|
||||
/* 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_device_base *sd_base, struct dm_target *ti,
|
||||
struct sflc_ctor_args_base *args_base);
|
||||
void sflc_vol_base_exit(struct sflc_volume_base *sv_base);
|
||||
|
||||
/* Sysfs */
|
||||
|
|
|
|||
|
|
@ -144,6 +144,12 @@ struct sflc_ctor_args_base
|
|||
*----------------------------
|
||||
*/
|
||||
|
||||
/* Argument parser */
|
||||
typedef struct sflc_ctor_args_base* (*sflc_mode_arg_parse_fn)(
|
||||
int argc, char ** argv);
|
||||
/* A bit overkill, but we need it just to free the kmalloc'ed args TODO improve */
|
||||
typedef void (*sflc_mode_arg_free_fn) (struct sflc_ctor_args_base *args_base);
|
||||
|
||||
/* Device constructor */
|
||||
typedef struct sflc_device_base* (*sflc_mode_dev_ctr_fn) (
|
||||
struct dm_target *ti, struct sflc_ctor_args_base *args_base);
|
||||
|
|
@ -159,10 +165,12 @@ 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.
|
||||
* as well as devmapper-related methods. Also an argument-parsing function.
|
||||
*/
|
||||
struct sflc_mode_ops
|
||||
{
|
||||
sflc_mode_arg_parse_fn parse_args;
|
||||
sflc_mode_arg_free_fn free_args;
|
||||
sflc_mode_dev_ctr_fn dev_ctr;
|
||||
sflc_mode_dev_dtr_fn dev_dtr;
|
||||
sflc_mode_vol_ctr_fn vol_ctr;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue