Add support for args struct in top level

This commit is contained in:
toninov 2025-07-22 22:35:27 +02:00
parent d9e3745a33
commit 6206dd4898
No known key found for this signature in database
4 changed files with 127 additions and 68 deletions

View file

@ -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);

View file

@ -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)

View file

@ -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 */

View file

@ -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;