diff mbox series

[2/2,V2] handlers: ubiswap: may swap several ubi volume

Message ID 1560867883-3726-3-git-send-email-philippe.reynes@softathome.com
State Changes Requested
Headers show
Series add a new handler ubiswap to swap several ubi volume | expand

Commit Message

Philippe REYNES June 18, 2019, 2:24 p.m. UTC
This new handler ubiswap swap the name of several ubi volume
in atomic way after all images were flashed. This handler is
seen as a script by swupdate, and all the date are provided
by the sw-description file.

Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com>
---
 doc/source/handlers.rst   |  20 ++++++++++
 handlers/ubivol_handler.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 120 insertions(+)

Comments

Stefano Babic June 18, 2019, 3:10 p.m. UTC | #1
Hi Philippe,

On 18/06/19 16:24, Philippe Reynes wrote:
> This new handler ubiswap swap the name of several ubi volume
> in atomic way after all images were flashed. This handler is
> seen as a script by swupdate, and all the date are provided
> by the sw-description file.
> 
> Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com>
> ---
>  doc/source/handlers.rst   |  20 ++++++++++
>  handlers/ubivol_handler.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 120 insertions(+)
> 
> diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
> index 03c0a69..65339b1 100644
> --- a/doc/source/handlers.rst
> +++ b/doc/source/handlers.rst
> @@ -163,6 +163,26 @@ However, please note the following limitations:
>  - Atomic renames are only possible and permitted for volumes residing
>    on the same UBI device.
>  
> +There is a handler ubiswap that allow to do an atomic swap for several
> +ubi volume after all the images were flashed. This handler is a script
> +for the point of view of swudate, so the node that provide it the data
> +should be added in the section scripts.
> +
> +::
> +
> +	scripts: (
> +		{
> +			type = "ubiswap";
> +			properties: {
> +				num-swap = 2;
> +				swap-first-name-0 = "boot";
> +				swap-second-name-0 = "boot_r";
> +				swap-first-name-1 = "kernel";
> +				swap-second-name-1 = "kernel_r";
> +			},
> +		},
> +	);
> +

This looks quite hard-coded and redundant. Why a user should both set
all names and provide num-swap ? (Apart that it is easier, of course !)
Why cannot be found by the handler ?

The general code is able to handle multiple properties in an array and
put them in a list (check swu_forward for example). That is you can also
do in tis way:

	properties: {
		swap-0 = ["boot", "boot_r"];
		swap-1 = ["kernel", "kernel_r"];
	}

and you can iterate all swap-%d until none is found. Something like:

 count = 0;

 while (1) {
      snprintf(prop, sizeof(prop), "swap-%d", count);
      volumes = dict_get_list(&img->properties, prop);

      and then you iterate the list to get first and second name.

>  
>  Lua Handlers
>  ------------
> diff --git a/handlers/ubivol_handler.c b/handlers/ubivol_handler.c
> index 60851e5..4f9bcf4 100644
> --- a/handlers/ubivol_handler.c
> +++ b/handlers/ubivol_handler.c
> @@ -373,6 +373,104 @@ static int adjust_volume(struct img_type *cfg,
>  	return 0;
>  }
>  
> +static int swap_volume(struct img_type *img,
> +		       void __attribute__ ((__unused__)) *data)
> +{
> +	struct flash_description *flash = get_flash_info();
> +	libubi_t libubi = flash->libubi;
> +	char *str_num_swap;
> +	int i, num_swap;
> +	char *first_name, *second_name;
> +	struct ubi_part *first_ubi_part, *second_ubi_part;
> +	int first_dev_num, second_dev_num, dev_num = -1;
> +	int first_vol_id, second_vol_id;
> +	char prop[SWUPDATE_GENERAL_STRING_SIZE];
> +	char masternode[UBI_MAX_VOLUME_NAME+1];
> +	struct ubi_rnvol_req rnvol;
> +	int ret = -1;
> +
> +	str_num_swap = dict_get_value(&img->properties, "num-swap");
> +	if (!str_num_swap) {
> +		ERROR("property num-swap is missing");
> +		goto out;
> +	}
> +
> +	num_swap = atoi(str_num_swap);
> +	if ((num_swap < 0) || (num_swap > (UBI_MAX_RNVOL / 2))) {
> +		ERROR("property num-swap (%d) is invalid", num_swap);
> +		goto out;
> +	}
> +
> +	for (i=0; i<num_swap; i++)

Nitpick : as codestyle (like kernel), blank is requested. The line becomes:

	for (i = 0; i < num_swap; i++)

Please fix this globally.

> +	{
> +		snprintf(prop, sizeof(prop), "swap-first-name-%d", i);
> +		first_name = dict_get_value(&img->properties, prop);


> +		if (!first_name) {
> +			ERROR("could not found property %s", prop);
> +			goto out;
> +		}
> +		first_ubi_part = search_volume_global(first_name);
> +		if (!first_ubi_part) {
> +			ERROR("could not found UBI volume %s", first_name);
> +			goto out;
> +		}
> +		first_dev_num = first_ubi_part->vol_info.dev_num;
> +		first_vol_id  = first_ubi_part->vol_info.vol_id;
> +
> +		snprintf(prop, sizeof(prop), "swap-second-name-%d", i);
> +		second_name = dict_get_value(&img->properties, prop);
> +		if (!second_name) {
> +			ERROR("could not found property %s", prop);
> +			goto out;
> +		}
> +		second_ubi_part = search_volume_global(second_name);
> +		if (!second_ubi_part) {
> +			ERROR("could not found UBI volume %s", first_name);
> +			goto out;
> +		}
> +		second_dev_num = second_ubi_part->vol_info.dev_num;
> +		second_vol_id  = second_ubi_part->vol_info.vol_id;
> +
> +		if (first_dev_num != second_dev_num) {
> +			ERROR("both device should be on the same UBI device");
> +			goto out;
> +		}
> +
> +		if (dev_num == -1) {
> +			dev_num = first_dev_num;
> +			snprintf(&masternode[0], sizeof(masternode),
> +				 "/dev/ubi%d", dev_num);
> +		} else {
> +			if (dev_num != first_dev_num) {
> +				ERROR("all devices should be on the"
> +				      "same UBI device");
> +				goto out;
> +			}
> +		}
> +
> +		TRACE("swap UBI volume %s <-> %s", first_name, second_name);
> +
> +		/* swap first -> second */
> +		rnvol.ents[2*i + 0].vol_id = first_vol_id;
> +		rnvol.ents[2*i + 0].name_len = strlen(second_name);
> +		strcpy(rnvol.ents[2*i + 0].name, second_name);
> +
> +		/* swap second -> first */
> +		rnvol.ents[2*i + 1].vol_id = second_vol_id;
> +		rnvol.ents[2*i + 1].name_len = strlen(first_name);
> +		strcpy(rnvol.ents[2*i + 1].name, first_name);
> +
> +		rnvol.count = 2*i + 2;
> +	}
> +
> +	ret = ubi_rnvols(libubi, masternode, &rnvol);
> +	if (ret)
> +		ERROR("cannot swap UBI volume");
> +
> + out:
> +	return ret;
> +}
> +
>  __attribute__((constructor))
>  void ubi_handler(void)
>  {
> @@ -380,4 +478,6 @@ void ubi_handler(void)
>  				IMAGE_HANDLER, NULL);
>  	register_handler("ubipartition", adjust_volume,
>  				PARTITION_HANDLER, NULL);
> +	register_handler("ubiswap", swap_volume,
> +				SCRIPT_HANDLER, NULL);
>  }
> 

Best regards,
Stefano Babic
diff mbox series

Patch

diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
index 03c0a69..65339b1 100644
--- a/doc/source/handlers.rst
+++ b/doc/source/handlers.rst
@@ -163,6 +163,26 @@  However, please note the following limitations:
 - Atomic renames are only possible and permitted for volumes residing
   on the same UBI device.
 
+There is a handler ubiswap that allow to do an atomic swap for several
+ubi volume after all the images were flashed. This handler is a script
+for the point of view of swudate, so the node that provide it the data
+should be added in the section scripts.
+
+::
+
+	scripts: (
+		{
+			type = "ubiswap";
+			properties: {
+				num-swap = 2;
+				swap-first-name-0 = "boot";
+				swap-second-name-0 = "boot_r";
+				swap-first-name-1 = "kernel";
+				swap-second-name-1 = "kernel_r";
+			},
+		},
+	);
+
 
 Lua Handlers
 ------------
diff --git a/handlers/ubivol_handler.c b/handlers/ubivol_handler.c
index 60851e5..4f9bcf4 100644
--- a/handlers/ubivol_handler.c
+++ b/handlers/ubivol_handler.c
@@ -373,6 +373,104 @@  static int adjust_volume(struct img_type *cfg,
 	return 0;
 }
 
+static int swap_volume(struct img_type *img,
+		       void __attribute__ ((__unused__)) *data)
+{
+	struct flash_description *flash = get_flash_info();
+	libubi_t libubi = flash->libubi;
+	char *str_num_swap;
+	int i, num_swap;
+	char *first_name, *second_name;
+	struct ubi_part *first_ubi_part, *second_ubi_part;
+	int first_dev_num, second_dev_num, dev_num = -1;
+	int first_vol_id, second_vol_id;
+	char prop[SWUPDATE_GENERAL_STRING_SIZE];
+	char masternode[UBI_MAX_VOLUME_NAME+1];
+	struct ubi_rnvol_req rnvol;
+	int ret = -1;
+
+	str_num_swap = dict_get_value(&img->properties, "num-swap");
+	if (!str_num_swap) {
+		ERROR("property num-swap is missing");
+		goto out;
+	}
+
+	num_swap = atoi(str_num_swap);
+	if ((num_swap < 0) || (num_swap > (UBI_MAX_RNVOL / 2))) {
+		ERROR("property num-swap (%d) is invalid", num_swap);
+		goto out;
+	}
+
+	for (i=0; i<num_swap; i++)
+	{
+		snprintf(prop, sizeof(prop), "swap-first-name-%d", i);
+		first_name = dict_get_value(&img->properties, prop);
+		if (!first_name) {
+			ERROR("could not found property %s", prop);
+			goto out;
+		}
+		first_ubi_part = search_volume_global(first_name);
+		if (!first_ubi_part) {
+			ERROR("could not found UBI volume %s", first_name);
+			goto out;
+		}
+		first_dev_num = first_ubi_part->vol_info.dev_num;
+		first_vol_id  = first_ubi_part->vol_info.vol_id;
+
+		snprintf(prop, sizeof(prop), "swap-second-name-%d", i);
+		second_name = dict_get_value(&img->properties, prop);
+		if (!second_name) {
+			ERROR("could not found property %s", prop);
+			goto out;
+		}
+		second_ubi_part = search_volume_global(second_name);
+		if (!second_ubi_part) {
+			ERROR("could not found UBI volume %s", first_name);
+			goto out;
+		}
+		second_dev_num = second_ubi_part->vol_info.dev_num;
+		second_vol_id  = second_ubi_part->vol_info.vol_id;
+
+		if (first_dev_num != second_dev_num) {
+			ERROR("both device should be on the same UBI device");
+			goto out;
+		}
+
+		if (dev_num == -1) {
+			dev_num = first_dev_num;
+			snprintf(&masternode[0], sizeof(masternode),
+				 "/dev/ubi%d", dev_num);
+		} else {
+			if (dev_num != first_dev_num) {
+				ERROR("all devices should be on the"
+				      "same UBI device");
+				goto out;
+			}
+		}
+
+		TRACE("swap UBI volume %s <-> %s", first_name, second_name);
+
+		/* swap first -> second */
+		rnvol.ents[2*i + 0].vol_id = first_vol_id;
+		rnvol.ents[2*i + 0].name_len = strlen(second_name);
+		strcpy(rnvol.ents[2*i + 0].name, second_name);
+
+		/* swap second -> first */
+		rnvol.ents[2*i + 1].vol_id = second_vol_id;
+		rnvol.ents[2*i + 1].name_len = strlen(first_name);
+		strcpy(rnvol.ents[2*i + 1].name, first_name);
+
+		rnvol.count = 2*i + 2;
+	}
+
+	ret = ubi_rnvols(libubi, masternode, &rnvol);
+	if (ret)
+		ERROR("cannot swap UBI volume");
+
+ out:
+	return ret;
+}
+
 __attribute__((constructor))
 void ubi_handler(void)
 {
@@ -380,4 +478,6 @@  void ubi_handler(void)
 				IMAGE_HANDLER, NULL);
 	register_handler("ubipartition", adjust_volume,
 				PARTITION_HANDLER, NULL);
+	register_handler("ubiswap", swap_volume,
+				SCRIPT_HANDLER, NULL);
 }