From 6206dd4898e67308fd885eaba112da8589ccbf0d Mon Sep 17 00:00:00 2001 From: toninov Date: Tue, 22 Jul 2025 22:35:27 +0200 Subject: [PATCH] Add support for args struct in top level --- dm-sflc/src/dev_vol.c | 91 ++++++++++++++++++++++++++++++++-------- dm-sflc/src/sflc.c | 84 +++++++++++++++++-------------------- dm-sflc/src/sflc.h | 10 +++-- dm-sflc/src/sflc_types.h | 10 ++++- 4 files changed, 127 insertions(+), 68 deletions(-) diff --git a/dm-sflc/src/dev_vol.c b/dm-sflc/src/dev_vol.c index 2195a73..ab04e4e 100644 --- a/dm-sflc/src/dev_vol.c +++ b/dm-sflc/src/dev_vol.c @@ -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); diff --git a/dm-sflc/src/sflc.c b/dm-sflc/src/sflc.c index 76b0f0e..f970760 100644 --- a/dm-sflc/src/sflc.c +++ b/dm-sflc/src/sflc.c @@ -32,7 +32,11 @@ #include -/* 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) diff --git a/dm-sflc/src/sflc.h b/dm-sflc/src/sflc.h index a3459ca..4b6510d 100644 --- a/dm-sflc/src/sflc.h +++ b/dm-sflc/src/sflc.h @@ -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 */ diff --git a/dm-sflc/src/sflc_types.h b/dm-sflc/src/sflc_types.h index 250178b..4a2f229 100644 --- a/dm-sflc/src/sflc_types.h +++ b/dm-sflc/src/sflc_types.h @@ -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;