diff mbox series

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

Message ID 1560958859-15547-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 19, 2019, 3:40 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   |  18 +++++++
 handlers/ubivol_handler.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)

Comments

Stefano Babic June 20, 2019, 10:04 a.m. UTC | #1
Hi Philippe,

On 19/06/19 17:40, 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   |  18 +++++++
>  handlers/ubivol_handler.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 141 insertions(+)
> 
> diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
> index 03c0a69..f06a1d0 100644
> --- a/doc/source/handlers.rst
> +++ b/doc/source/handlers.rst
> @@ -163,6 +163,24 @@ 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: {
> +				swap-0 = [ "boot" , " boot_r" ];
> +				swap-1 = [ "kernel" , "kernel_r" ];
> +				swap-2 = [ "rootfs" , "rootfs_r" ];
> +			},
> +		},
> +	);
> +
>  
>  Lua Handlers
>  ------------
> diff --git a/handlers/ubivol_handler.c b/handlers/ubivol_handler.c
> index 60851e5..a1cdce5 100644
> --- a/handlers/ubivol_handler.c
> +++ b/handlers/ubivol_handler.c
> @@ -373,6 +373,127 @@ static int adjust_volume(struct img_type *cfg,
>  	return 0;
>  }
>  
> +static int ubi_volume_get_info(char *name, int *dev_num, int *vol_id)
> +{
> +	struct ubi_part *ubi_part;
> +
> +	ubi_part = search_volume_global(name);
> +	if (!ubi_part) {
> +		ERROR("could not found UBI volume %s", name);
> +		return -1;
> +	}
> +
> +	*dev_num = ubi_part->vol_info.dev_num;
> +	*vol_id  = ubi_part->vol_info.vol_id;
> +
> +	return 0;
> +}
> +
> +static int swap_volume(struct img_type *img, void *data)
> +{
> +	script_fn scriptfn;
> +	struct flash_description *flash = get_flash_info();
> +	libubi_t libubi = flash->libubi;
> +	int num, count = 0;
> +	struct dict_list *volumes;
> +	struct dict_list_elem *volume;
> +	char *name[2];
> +	int dev_num[2], vol_id[2], global_dev_num = -1;
> +	char prop[SWUPDATE_GENERAL_STRING_SIZE];
> +	char masternode[UBI_MAX_VOLUME_NAME+1];
> +	struct ubi_rnvol_req rnvol;
> +	int ret = -1;
> +
> +	if (!data)
> +		return -EINVAL;
> +
> +	scriptfn = *(script_fn *)data;
> +
> +	/*
> +	 * Call only in case of postinstall
> +	 */
> +	if (scriptfn != POSTINSTALL)
> +		return 0;
> +
> +	while (1) {
> +		snprintf(prop, sizeof(prop), "swap-%d", count);
> +		volumes = dict_get_list(&img->properties, prop);
> +		if (!volumes)
> +			break;
> +
> +		if (count >= (UBI_MAX_RNVOL / 2)) {
> +			ERROR("Too many requested swap");
> +			goto out;
> +		}
> +
> +		num = 0;
> +		LIST_FOREACH(volume, volumes, next) {
> +			if (num >= 2) {
> +				ERROR("Too many ubi volume (%s)", prop);
> +				goto out;
> +			}
> +
> +			name[num] = volume->value;
> +			if (ubi_volume_get_info(volume->value,
> +						&dev_num[num],
> +						&vol_id[num]) < 0)
> +				goto out;
> +
> +			num++;
> +		}
> +
> +		if (num != 2) {
> +			ERROR("Invalid number (%d) of ubi volume (%s)", num, prop);
> +			goto out;
> +		}
> +
> +		if (dev_num[0] != dev_num[1]) {
> +			ERROR("both volume should be on the same UBI device");
> +			goto out;
> +		}
> +
> +		if (global_dev_num == -1) {
> +			global_dev_num = dev_num[0];
> +			snprintf(&masternode[0], sizeof(masternode),
> +				 "/dev/ubi%d", global_dev_num);
> +		} else {
> +			if (global_dev_num != dev_num[0]) {
> +				ERROR("all volumes should be on the"
> +				      "same UBI device (%s)", prop);
> +				goto out;
> +			}
> +		}
> +
> +		TRACE("swap UBI volume %s <-> %s", name[0], name[1]);
> +
> +		/* swap first -> second */
> +		rnvol.ents[2 * count + 0].vol_id = vol_id[0];
> +		rnvol.ents[2 * count + 0].name_len = strlen(name[1]);
> +		strcpy(rnvol.ents[2 * count + 0].name, name[1]);
> +
> +		/* swap second -> first */
> +		rnvol.ents[2 * count + 1].vol_id = vol_id[1];
> +		rnvol.ents[2 * count + 1].name_len = strlen(name[0]);
> +		strcpy(rnvol.ents[2 * count + 1].name, name[0]);
> +
> +		count++;
> +	}
> +
> +	if (!count) {
> +		ERROR("No UBI volume provided");
> +		goto out;
> +	}
> +
> +	rnvol.count = count * 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 +501,6 @@ void ubi_handler(void)
>  				IMAGE_HANDLER, NULL);
>  	register_handler("ubipartition", adjust_volume,
>  				PARTITION_HANDLER, NULL);
> +	register_handler("ubiswap", swap_volume,
> +				SCRIPT_HANDLER, NULL);
>  }
> 


Acked-by: Stefano Babic <sbabic@denx.de>

Best regards,
Stefano Babic
diff mbox series

Patch

diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
index 03c0a69..f06a1d0 100644
--- a/doc/source/handlers.rst
+++ b/doc/source/handlers.rst
@@ -163,6 +163,24 @@  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: {
+				swap-0 = [ "boot" , " boot_r" ];
+				swap-1 = [ "kernel" , "kernel_r" ];
+				swap-2 = [ "rootfs" , "rootfs_r" ];
+			},
+		},
+	);
+
 
 Lua Handlers
 ------------
diff --git a/handlers/ubivol_handler.c b/handlers/ubivol_handler.c
index 60851e5..a1cdce5 100644
--- a/handlers/ubivol_handler.c
+++ b/handlers/ubivol_handler.c
@@ -373,6 +373,127 @@  static int adjust_volume(struct img_type *cfg,
 	return 0;
 }
 
+static int ubi_volume_get_info(char *name, int *dev_num, int *vol_id)
+{
+	struct ubi_part *ubi_part;
+
+	ubi_part = search_volume_global(name);
+	if (!ubi_part) {
+		ERROR("could not found UBI volume %s", name);
+		return -1;
+	}
+
+	*dev_num = ubi_part->vol_info.dev_num;
+	*vol_id  = ubi_part->vol_info.vol_id;
+
+	return 0;
+}
+
+static int swap_volume(struct img_type *img, void *data)
+{
+	script_fn scriptfn;
+	struct flash_description *flash = get_flash_info();
+	libubi_t libubi = flash->libubi;
+	int num, count = 0;
+	struct dict_list *volumes;
+	struct dict_list_elem *volume;
+	char *name[2];
+	int dev_num[2], vol_id[2], global_dev_num = -1;
+	char prop[SWUPDATE_GENERAL_STRING_SIZE];
+	char masternode[UBI_MAX_VOLUME_NAME+1];
+	struct ubi_rnvol_req rnvol;
+	int ret = -1;
+
+	if (!data)
+		return -EINVAL;
+
+	scriptfn = *(script_fn *)data;
+
+	/*
+	 * Call only in case of postinstall
+	 */
+	if (scriptfn != POSTINSTALL)
+		return 0;
+
+	while (1) {
+		snprintf(prop, sizeof(prop), "swap-%d", count);
+		volumes = dict_get_list(&img->properties, prop);
+		if (!volumes)
+			break;
+
+		if (count >= (UBI_MAX_RNVOL / 2)) {
+			ERROR("Too many requested swap");
+			goto out;
+		}
+
+		num = 0;
+		LIST_FOREACH(volume, volumes, next) {
+			if (num >= 2) {
+				ERROR("Too many ubi volume (%s)", prop);
+				goto out;
+			}
+
+			name[num] = volume->value;
+			if (ubi_volume_get_info(volume->value,
+						&dev_num[num],
+						&vol_id[num]) < 0)
+				goto out;
+
+			num++;
+		}
+
+		if (num != 2) {
+			ERROR("Invalid number (%d) of ubi volume (%s)", num, prop);
+			goto out;
+		}
+
+		if (dev_num[0] != dev_num[1]) {
+			ERROR("both volume should be on the same UBI device");
+			goto out;
+		}
+
+		if (global_dev_num == -1) {
+			global_dev_num = dev_num[0];
+			snprintf(&masternode[0], sizeof(masternode),
+				 "/dev/ubi%d", global_dev_num);
+		} else {
+			if (global_dev_num != dev_num[0]) {
+				ERROR("all volumes should be on the"
+				      "same UBI device (%s)", prop);
+				goto out;
+			}
+		}
+
+		TRACE("swap UBI volume %s <-> %s", name[0], name[1]);
+
+		/* swap first -> second */
+		rnvol.ents[2 * count + 0].vol_id = vol_id[0];
+		rnvol.ents[2 * count + 0].name_len = strlen(name[1]);
+		strcpy(rnvol.ents[2 * count + 0].name, name[1]);
+
+		/* swap second -> first */
+		rnvol.ents[2 * count + 1].vol_id = vol_id[1];
+		rnvol.ents[2 * count + 1].name_len = strlen(name[0]);
+		strcpy(rnvol.ents[2 * count + 1].name, name[0]);
+
+		count++;
+	}
+
+	if (!count) {
+		ERROR("No UBI volume provided");
+		goto out;
+	}
+
+	rnvol.count = count * 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 +501,6 @@  void ubi_handler(void)
 				IMAGE_HANDLER, NULL);
 	register_handler("ubipartition", adjust_volume,
 				PARTITION_HANDLER, NULL);
+	register_handler("ubiswap", swap_volume,
+				SCRIPT_HANDLER, NULL);
 }