Use of gpt partition swap

127 views
Skip to first unread message

Hamish Guthrie

unread,
Nov 27, 2023, 5:42:41 AM11/27/23
to Philippe Reynes, swup...@googlegroups.com

Hi Philippe,


I have been trying to use the gpt partition swap facility you added to swupdate, but I am running into difficulty with it and wondered if you could maybe give me some guidance?

In my use-case, I am attempting to provide an swupdate mechanism for a product running on eMMC. On the eMMC I have 3 partitions in the user-area of the eMMC, rootfs, rootfs_r and data. I have a root filesystem installed in the rootfs partition. My bootloaders are installed in raw mode in the boot blocks of the eMMC.

I have created a sw-description file, the important part of which is:

images: (
        ...
        {
                filename = "rootfs.ext4";
                type = "gptpart";
                device = "/dev/mmcblk0";
                volume = "rootfs_r";
        }
);

scripts: (
        {
                type = "gptswap";
                device = "/dev/mmcblk0";
                properties = {
                        swap-0 = [ "rootfs", "rootfs_r" ];
                };
        },
);

I run my update and the new rootfs image is installed into the rootfs_r partition, however, I then receive the error:

ERROR diskpart_handler.c : diskpart_blkdev_lock : 810 : /dev/mmcblk0: device in use
ERROR diskpart_handler.c : gpt_swap_partition : 1684 : Can't write table (err = -16)
ERROR diskpart_handler.c : diskpart_reread_partition : 904 : Scan cannot be done on device /dev/mmcblk0
ERROR installer.c : install_images : 361 : execute postinstall scripts failed
Installation failed !

In this implementation, I have swupdate installed in the root filesystem, so when the update is done, the active partition has swupdate running, and I am guessing that this is why I am seeing the device in use error. I guess I could have a separate swupdate image in a ramdisk which I could boot into, but this means extra state I would have to cater for, which I would prefer to avoid.

This is a next generation product, the existing product this generation is to replace has raw NAND and we use UBI with two root filesysems and we use the ubiswap mechanism you also developed for that. The one major advantage we have in using the partition/volume swap is that the bootloader does not need to refer to the u-boot environment to figure out which volume/partition to boot from because this never changes, and within u-boot it is quite easy to figure out the UUID for the rootfilesystem to be mounted, and to pass that along as a kernel command-line argument.


Hamish
   

 

Confidentiality Notice: This e-mail is privileged and confidential and for the use of the addressee only. Should you have received this e-mail in error please notify us by replying directly to the sender or by sending a message to in...@kistler.com. Unauthorised dissemination, disclosure or copying of the contents of this e-mail, or any similar action, is prohibited.

Philippe REYNES

unread,
Nov 27, 2023, 9:27:09 AM11/27/23
to Hamish Guthrie, swup...@googlegroups.com

Hi Hamish,



Le 27/11/2023 à 11:42, Hamish Guthrie a écrit :

 

This Mail comes from Outside of SoftAtHome: Do not answer, click links or open attachments unless you recognize the sender and know the content is safe.


Yes, I also suppose that this issue is raised because the rootfs is mounted so used.


To avoid this issue, you may use the property "noinuse" :

https://sbabic.github.io/swupdate/handlers.html#disk-partitioner


noinuse

string

“true” or “false” (default=false) If set, it does not require the device to be not in use (mounted, etc.)




This is a next generation product, the existing product this generation is to replace has raw NAND and we use UBI with two root filesysems and we use the ubiswap mechanism you also developed for that. The one major advantage we have in using the partition/volume swap is that the bootloader does not need to refer to the u-boot environment to figure out which volume/partition to boot from because this never changes, and within u-boot it is quite easy to figure out the UUID for the rootfilesystem to be mounted, and to pass that along as a kernel command-line argument.


Thanks, I am pleased to read that this feature is used.



Hamish
   

 

Confidentiality Notice: This e-mail is privileged and confidential and for the use of the addressee only. Should you have received this e-mail in error please notify us by replying directly to the sender or by sending a message to in...@kistler.com. Unauthorised dissemination, disclosure or copying of the contents of this e-mail, or any similar action, is prohibited.


Best regards,

Philippe


Hamish Guthrie

unread,
Nov 27, 2023, 10:50:38 AM11/27/23
to Philippe REYNES, swup...@googlegroups.com

Hi Philippe,




> To avoid this issue, you may use the property "noinuse" :
> https://sbabic.github.io/swupdate/handlers.html#disk-partitioner
>
> noinuse
> string
> “true” or “false” (default=false) If set, it does not require the device to be not in use (mounted, etc.)

I had tried setting the noinuse flag as per the documentation where it describes properties for the diskpart handler (i.e. in the partitions: section of the sw-description file). I then added some debug code to the diskpart_handler and in the gpt_swap_function, the value of that flag is reported as being false. I then added those properties to the properties section of the gptswap script and now it works as follows:

scripts: (
{
type = "gptswap";
device = "/dev/mmcblk0";
properties = {
nolock = "true";
noinuse = "true";
swap-0 = [ "rootfs", "rootfs_r" ];
};
},

So I have now managed to get it to work, but the documentation I believe could be extended to point this out. Would you like me to extend the documentation to reflect this?

There is another issue, however, and maybe you could assist me with this:

In the partitions section of my sw-description file, I define the partitions on my eMMC, but once I have updated the device, and I attempt to do a second update, the partition table is re-written because the names of the partitions are incorrect, so in my sw-description file I have:

partitions: (
{
type = "diskpart";
device = "/dev/mmcblk0"
properties: {
labeltype = "gpt";
nolock = "true";
noinuse = "true";
partition-1 = [ "size=256M", "start=2048", "name=rootfs",
"type=B921B045-1DF0-41C3-AF44-4C6F280D3FAE"];
partition-2 = [ "size=256M", "start=526336", "name=rootfs_r",
"type=B921B045-1DF0-41C3-AF44-4C6F280D3FAE"];
partition-3 = [ "size=256M", "start=1050624", "name=data",
"type=0FC63DAF-8483-4772-8E79-3D69D8477DE4"];
}
}
);

So during the first update of the device, the new root filesystem image is installed in partition 2 which is named rootfs_r, which is what I would expect, and then the gptswap does it's magic and now on my device, partition 1 is now named rootfs_r and partition 2 is now named rootfs. Now if I do another update, the partitions in the sw-description file are different to the partitions in my device and the partitioning handler swaps them back again, and I am not sure how best to handle this. Is it an invalid use-case to attempt to provide the partition table layout in the sw-description file?

Would you by any chance have an example of a sw-description file available which illustrates how you handle this?

Best regards
Hamish

Stefano Babic

unread,
Nov 27, 2023, 11:05:08 AM11/27/23
to Hamish Guthrie, Philippe REYNES, swup...@googlegroups.com
Hi Hamish,

On 27.11.23 16:50, Hamish Guthrie wrote:
>
> Hi Philippe,
>
>
>
>
>> To avoid this issue, you may use the property "noinuse" :
>> https://sbabic.github.io/swupdate/handlers.html#disk-partitioner
>>
>> noinuse
>> string
>> “true” or “false” (default=false) If set, it does not require the device to be not in use (mounted, etc.)
>
> I had tried setting the noinuse flag as per the documentation where it describes properties for the diskpart handler (i.e. in the partitions: section of the sw-description file).

These properties are in common between diskpart and gptswap. In your
case, you should set them to gptswap handler, else they have no effect.

> I then added some debug code to the diskpart_handler and in the gpt_swap_function, the value of that flag is reported as being false. I then added those properties to the properties section of the gptswap script and now it works as follows:
>
> scripts: (
> {
> type = "gptswap";
> device = "/dev/mmcblk0";
> properties = {
> nolock = "true";
> noinuse = "true";
> swap-0 = [ "rootfs", "rootfs_r" ];
> };
> },
>
> So I have now managed to get it to work, but the documentation I believe could be extended to point this out. Would you like me to extend the documentation to reflect this?

Any attempt to make documentation clearer is well accepted ;-)

>
> There is another issue, however, and maybe you could assist me with this:
>
> In the partitions section of my sw-description file, I define the partitions on my eMMC, but once I have updated the device, and I attempt to do a second update, the partition table is re-written because the names of the partitions are incorrect,

...well, yes, it is expected, you are changing the table with the swap....

> so in my sw-description file I have:
>
> partitions: (
> {
> type = "diskpart";
> device = "/dev/mmcblk0"
> properties: {
> labeltype = "gpt";
> nolock = "true";
> noinuse = "true";
> partition-1 = [ "size=256M", "start=2048", "name=rootfs",
> "type=B921B045-1DF0-41C3-AF44-4C6F280D3FAE"];
> partition-2 = [ "size=256M", "start=526336", "name=rootfs_r",
> "type=B921B045-1DF0-41C3-AF44-4C6F280D3FAE"];
> partition-3 = [ "size=256M", "start=1050624", "name=data",
> "type=0FC63DAF-8483-4772-8E79-3D69D8477DE4"];
> }
> }
> );
>

Nevertheless, this does not work always. Think about you do not change
the label, but you want to change the size of the partitions. And you
have mounted rootfs on one of that. It does not work. Think like you
shrink partition and then install a new rootfs, damaging where you are
running.

It is common to create the partitions during first system deploying - at
that time, eMMC is empty. You should add partitions when "rescue" (aka a
swupdate running on a ramdisk) is running, not during production.

Of course, it is still possible to change partitions on the field, but a
migration should be designed to avoid to damage where you are running.
In your case, you are "damaging", because you overwrite the label - but
from SWupdate's point of view, this is as changing size, start address,
whatever...

> So during the first update of the device,

First update means first deployment with empty eMMC, you should then
have a case in your sw-description to distinguish from an update in
field, and you shouln't have the partitions during update in field but
just gptswap.

> the new root filesystem image is installed in partition 2 which is named rootfs_r, which is what I would expect, and then the gptswap does it's magic and now on my device, partition 1 is now named rootfs_r and partition 2 is now named rootfs. Now if I do another update, the partitions in the sw-description file are different to the partitions in my device and the partitioning handler swaps them back again, and I am not sure how best to handle this.
> Is it an invalid use-case to attempt to provide the partition table layout in the sw-description file?

It is invalid when you rely on the partitions itself, as in your case.

>
> Would you by any chance have an example of a sw-description file available which illustrates how you handle this?

You should set partitions just in rescue, it is the only case where it
makes sense.

Best regards.,
Stefano
Reply all
Reply to author
Forward
0 new messages