#3562 PR merged: Partuuid recovery

Labels: enhancement, fixed / solved / done

svlv opened issue at 2026-02-05 13:03:

Relax-and-Recover (ReaR) Pull Request Template

Please fill in the following items before submitting a new pull request:

Pull Request Details:
  • Type: Enhancement

  • Impact: Normal

  • Reference to related issue (URL):

  • How was this pull request tested?
    The patch was tested over several months on multiple distributions and versions (RHEL, CentOS, Debian, Ubuntu) running on either EFI/GPT or BIOS/MBR, or BIOS+EFI/GPT.
    For GPT partition tables, PARTUUIDs are successfully backed up and restored. For MBR partition tables, the patch makes no changes. I haven't encountered any issue with this patch (at least none that were visible to me).

  • Description of the changes in this pull request:
    Fixes https://github.com/rear/rear/issues/3561.
    During backup, the PARTUUID values are added to layout/disklayout.conf. During recovery, these values are used to restore PARTUUIDs by running sgdisk --partition-guid=<partguid> <dev>.
    If sgdisk is not available or no valid PARTUUID value is present, this step is skipped because it is treated as optional.
    PARTUUID is added at the end of partition parameters because, in our setup, ReaR scripts are separated from the layout information. This is done for backward compatibility with previous ReaR scripts versions (I hope it is acceptable).

jsmeix commented at 2026-02-05 15:07:

@rear/contributors
please have a look here and review it (as time permits).

jsmeix commented at 2026-02-09 11:06:

@rear/contributors
all looks good now to me from plain looking at the code
so I would like to merge it on Thursday afternoon.
Please have a look here and review it (as time permits).

jsmeix commented at 2026-02-09 12:01:

@svlv
I would like to add some remarks and questions
about optional "cosmetic" naming issues
which are mostly my personal preference
so nothing is wrong with your current code.

It me it looks as if "partuuid"
written as partuuid or PARTUUID
is the proper name for what that is about
so I think this proper name should be used
consistently everywhere when that thingy is meant.

So I am wondering if the current functions
get_partition_guid() and set_partition_guid()
shouldn't be better named
get_partuuid() and set_partuuid()
?

Within those functions the locally used variable names
look meaningless and confusing to me.
I am wondering what a device versus a disk
actually is within the context of that functions.
I am also wondering what a guid is in contrast
to a partuuid - are they different or the same thing?

Cf. the section "Code must be easy to read" in
https://github.com/rear/rear/wiki/Coding-Style

According to how I understand those functions
from plain looking at the code I think
those functions are meant to do this:

get_partuuid() {
    local partition_device=$1
    local partuuid=""
    if has_binary blkid; then
        partuuid="$( blkid -s PARTUUID -o value "$partition_device" )"
    # Fallback for cases when blkid is not available
    elif [ -d /dev/disk/by-partuuid ]; then
        local partition_symlink
        for partition_symlink in /dev/disk/by-partuuid/*; do
            if [ -h "$partition_symlink" ] && [ "$( readlink -f "$partition_symlink" )" = "$partition_device" ]; then
                partuuid="${partition_symlink#/dev/disk/by-partuuid/}"
                break
            fi
        done
    fi
    echo "$partuuid"
}

set_partuuid() {
    local disk=$1
    local partnum=$2
    local partuuid=$3
    if has_binary sgdisk; then
        sgdisk --partition-guid="$partnum":"$partuuid" "$disk"
    fi
}

I removed a 2>/dev/null because I assume
it is not needed, cf. the section
"What to do with stdin, stdout, and stderr" in
https://github.com/rear/rear/wiki/Coding-Style

I wonder if [ -h "$partition_symlink" ] is really reeded?
Couldn't
[ "$( readlink -f "$partition_symlink" )" = "$partition_device" ]
alone be good enough?

I wonder why readlink -f and not readlink -e ?
On my workstation it also works with readlink -e
so I wonder why not "all components must exist"
but only "all but the last component must exist"
cf. "man readlink".

Or do I misunderstand what those functions are meant to do?

By the way:
I know we have many such meaningless and confusing
variable names all over the place in existing ReaR code.
For example right now I had a look at
layout/prepare/GNU/Linux/100_include_partition_code.sh
and got immediately totally confused what device
versus disk means therein :-(
That (old) code is so confusing to me because of its bad
variable names that I won't dare to touch it to clean it up.

svlv commented at 2026-02-09 13:16:

@jsmeix

Regarding partition GUID vs. PARTUUID naming, I totally agree that it would be better to choose a single term.

While reading articles and comments on this topic, I noticed that the term partition GUID is quite commonly used ,
even GPT stands for GUID Partition Table, not UUID Partition Table. That's why, in my initial draft, I named the functions get_partition_guid and set_partition_guid. Later, during testing and further investigation, I mostly used PARTUUID variant in tools like blkid and lsblk, this led me to the conclusion that PARTUUIDs would be more clear for users, since it is used in the util-linux package and the /dev/disk/by-partuuid/ directory.

Did I consider unifying the naming and choosing just one term? Yes. However, I decided to leave it as is, since I wasn't sure that anyone would care about it. Personally, I'm more or less fine with non-unified naming, because renaming always takes some extra time.

I wonder if [ -h "$partition_symlink" ] is really reeded?

It can be removed, I mainly used it as a reminder that enries /dev/disk/by-partuuid/ are supposed to be symlinks.

I wonder why readlink -f and not readlink -e ?

Because I don't use the resolved link afterward to do something with it, e.g., to refer a device. I only use the path itself. But agree, readlink -e is safer and it's probably the better choice here.

Or do I misunderstand what those functions are meant to do?

You got it correctly.

I'll fix your comments when I have time.

jsmeix commented at 2026-02-09 14:31:

Only out of curiosity:

Now I got interested in "GUID" versus "UUID":

The "ultimate answer to everything" ;-) tells
https://en.wikipedia.org/wiki/Universally_unique_identifier

A universally unique identifier (UUID) is a 128-bit number
used to identify information in computer systems.
The term globally unique identifier (GUID) is also used,
typically in software created by Microsoft
[https://www.rfc-editor.org/rfc/rfc4122]

I further asked Google AI

why is it called "GUID Partition Table"
and not "UUID Partition Table" ?

and got this reply (excerpts):

The Origins: Microsoft and Intel
The term GUID (Globally Unique Identifier) was popularized
by Microsoft and is heavily baked into the Windows ecosystem
and the Component Object Model (COM).
When Intel was developing the EFI (Extensible Firmware
Interface) specification in the late 990s - which eventually
became UEFI - they worked closely with Microsoft.
...
Technically, a GUID is a specific implementation of the
broader UUID (Universally Unique Identifier) standard.

jsmeix commented at 2026-02-10 13:12:

@svlv
thank you.
Much appreciated!

pcahyna commented at 2026-02-11 17:51:

Thank you, more faithful restoration of layout is always better.

I am afraid though that you need to change more than usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh. Quick search reveals that the format of the partition entries in disklayout is also used in at least: usr/share/rear/layout/prepare/default/420_autoresize_last_partitions.sh usr/share/rear/layout/prepare/default/430_autoresize_all_partitions.sh usr/share/rear/layout/prepare/default/319_rename_xfs_configs.sh (these three look important), usr/share/rear/layout/save/default/950_verify_disklayout_file.sh usr/share/rear/lib/layout-functions.sh (probably less important).

svlv commented at 2026-02-12 07:43:

Thanks @pcahyna. It is a good point. I'll fix it when I have time

svlv commented at 2026-02-12 13:13:

I am afraid though that you need to change more than usr/share/rear/layout/prepare/GNU/Linux/100_include_partition_code.sh. Quick search reveals that the format of the partition entries in disklayout is also used in at least: usr/share/rear/layout/prepare/default/420_autoresize_last_partitions.sh usr/share/rear/layout/prepare/default/430_autoresize_all_partitions.sh usr/share/rear/layout/prepare/default/319_rename_xfs_configs.sh (these three look important), usr/share/rear/layout/save/default/950_verify_disklayout_file.sh usr/share/rear/lib/layout-functions.sh (probably less important).

Corrected:

  • usr/share/rear/layout/prepare/default/420_autoresize_last_partitions.sh
  • usr/share/rear/layout/prepare/default/430_autoresize_all_partitions.sh
  • usr/share/rear/layout/prepare/default/319_rename_xfs_configs.sh
  • usr/share/rear/lib/layout-functions.sh

In usr/share/rear/layout/save/default/950_verify_disklayout_file.sh, PARTUUIDs were left in junk.

The changes were tested by restoring to a bigger disk with the default AUTORESIZE_PARTITIONS and when AUTORESIZE_PARTITIONS=true to test changes in 430_autoresize_all_partitions.sh

svlv commented at 2026-02-14 08:30:

I've reviewed 420_autoresize_last_partitions.sh one more time and noticed that for raid0 one important update it still required.

svlv commented at 2026-02-16 08:26:

Fixed finding part entries for RAID0 and RAID1 to auto-resize them.

Tested manually on Debian 13 with RAID0. The system uses two 10GB disks and is migrated into two 12GB disks.

Before the migration:

lsblk -o NAME,FSTYPE,UUID,PARTUUID,SIZE,MOUNTPOINTS
NAME    FSTYPE            UUID                                 PARTUUID                              SIZE MOUNTPOINTS
sr0                                                                                                 1024M 
vda                                                                                                   10G 
├─vda1  vfat              AED2-8E94                            25896747-0b2f-4ab1-8f08-bcd96c8a852e  953M /boot/efi
└─vda2  linux_raid_member 1321c636-e080-979c-49dd-5cc43b2f4861 58810dc1-f22d-48b5-bead-62b4d9e2ab1b  9.1G 
   └─md0 ext4             f7e1c368-cf94-4955-88d8-10f20c54cabb                                        19G /
vdb                                                                                                   10G 
└─vdb1  linux_raid_member 1321c636-e080-979c-49dd-5cc43b2f4861 6e1d9c2b-1a31-443d-a492-0108abe98012   10G 
   └─md0 ext4             f7e1c368-cf94-4955-88d8-10f20c54cabb                                        19G /

After the migration:

lsblk -o NAME,FSTYPE,UUID,PARTUUID,SIZE,MOUNTPOINTS
NAME    FSTYPE            UUID                                 PARTUUID                               SIZE MOUNTPOINTS
sr0     iso9660           2026-02-14-17-46-44-00                                                    271.7M 
vda                                                                                                    12G 
├─vda1  vfat              AED2-8E94                            25896747-0b2f-4ab1-8f08-bcd96c8a852e   953M /boot/efi
└─vda2  linux_raid_member 1321c636-e080-979c-49dd-5cc43b2f4861 58810dc1-f22d-48b5-bead-62b4d9e2ab1b  11.1G 
  └─md0 ext4              f7e1c368-cf94-4955-88d8-10f20c54cabb                                         23G /
vdb                                                                                                    12G 
└─vdb1  linux_raid_member 1321c636-e080-979c-49dd-5cc43b2f4861 6e1d9c2b-1a31-443d-a492-0108abe98012    12G 
  └─md0 ext4              f7e1c368-cf94-4955-88d8-10f20c54cabb

svlv commented at 2026-02-17 07:11:

I've additionally tested autoresize for RAID1 - no issues with parsing part entries.
Please let me know if anything else is required from my side.

jsmeix commented at 2026-02-24 14:25:

@rear/contributors

there is a false alarm of Codacy Static Code Analysis
https://github.com/rear/rear/pull/3562/checks?check_run_id=63720542563

How can I mark this specific alarm as false
so that it will not appear again at this code place?

See
https://github.com/rear/rear/pull/3562/changes
what it is about:
In usr/share/rear/lib/layout-functions.sh
this is added

# The regex defines the expected PARTUUID format.
# Pseudo-UUIDs (not RFC 4122–compliant) are intentionally allowed, as they can
# be manually assigned as PARTUUID using sgdisk. sgdisk primarily validates
# the length.
PARTUUID_REGEX="(no-partuuid|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"

Of course PARTUUID_REGEX is not used in
usr/share/rear/lib/layout-functions.sh
It is only set here as a global variable
which is used in other scripts.

jsmeix commented at 2026-02-24 14:29:

@rear/contributors
I would like to merge it next Monday (02. March) afternoon
unless there are objections.
Please have a look and review it (as time permits).

gdha commented at 2026-02-24 14:32:

@rear/contributors

there is a false alarm of Codacy Static Code Analysis https://github.com/rear/rear/pull/3562/checks?check_run_id=63720542563

How can I mark this specific alarm as false so that it will not appear again at this code place?

See https://github.com/rear/rear/pull/3562/changes what it is about: In usr/share/rear/lib/layout-functions.sh this is added

# The regex defines the expected PARTUUID format.
# Pseudo-UUIDs (not RFC 4122–compliant) are intentionally allowed, as they can
# be manually assigned as PARTUUID using sgdisk. sgdisk primarily validates
# the length.
PARTUUID_REGEX="(no-partuuid|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"

Of course PARTUUID_REGEX is not used in usr/share/rear/lib/layout-functions.sh It is only set here as a global variable which is used in other scripts.

@jsmeix marked this issue as "false positive" in Codacy https://app.codacy.com/gh/rear/rear/pull-requests/3562/issues#issue-f8e82ff46f7010d94e11fc4206ec4e2c

svlv commented at 2026-02-24 14:34:

@jsmeix and @gdha

I can also add # shellcheck disable=SC2034 above the variable if it is desirable.

jsmeix commented at 2026-02-24 15:48:

@gdha
seems I am somewhat blind but I fail to see how I could
mark an issue as "false positive" in Codacy
or can only you do that?

pcahyna commented at 2026-02-24 15:55:

@jsmeix and @gdha

I can also add # shellcheck disable=SC2034 above the variable if it is desirable.

Thanks for the proposal, but I don't think we should litter the code with such comments. Instead we should configure the tools to not report false positives (and am I right that warnings are reported only once and on subsequent PRs that do not touch this code line they don't appear again?)

svlv commented at 2026-02-27 12:47:

I've re-tested a fallback for getting PARTUUIDs for cases when blkid is not available.

I know that blkid is put to the REQUIRED_PROGS array in default.conf, however, particularly for getting PARTUUID there is a fallback. To test the fallback I remaned blkid and removed it from the REQUIRED_PROGS array.

Just in case if blkid will be removed from REQUIRED_PROGS in the future

jsmeix commented at 2026-03-02 12:38:

@pcahyna
is it OK for you to be merged?
If yes, please approve it.

pcahyna commented at 2026-03-02 15:18:

Hi @svlv , the changes are fine, I would just like to do reshuffle the diffs a bit, see https://github.com/rear/rear/pull/3562/changes#r2794621337 and also some commits could be squashed together (you are introducing a new file, then you remove it).

If you don't mind I will do that myself, I often look at the git history and prefer to have it clean.

svlv commented at 2026-03-02 15:22:

@pcahyna

Yes, sure, please do it. Thank you

pcahyna commented at 2026-03-02 15:25:

@svlv by the way, I am just curious, is there a reason why to care about blkid not being available? It is part of util-linux, so a pretty basic utility, and we call it unconditionally at other places already, although a failure there is possibly not fatal.

Of course defensive programming is not bad at all, I just would like to know if you have a special reason for this.

pcahyna commented at 2026-03-02 15:36:

@svlv by the way, thank you for the thorough updates of all the places where the layout file is being used. What did you use to find them? I simply searched the code for the string ^part (not pattern, the literal string), assuming that any processing of the layout file that needs partition entries will use grep ^part or awk /^part/. Hopefully that's enough...

svlv commented at 2026-03-02 15:45:

@pcahyna

I was curious how to get PARTUUID without blkid, relying on /dev/disk/by-partuuid only.

Yes, I'm aware that blkid is part of GNU util-linux, but when you are building util-linux package from source you may decide not to build blkid.

After testing it on some systems (RHEL 7, 8, 9, 10) I decided to leave this fallback because I though it might be useful for other individuals who want to minimise REQUIRED_PROGS array as much as possible.

svlv commented at 2026-03-02 15:54:

What did you use to find them?

I used rg "\^part" and looked through the code where LAYOUT_FILE is used.

pcahyna commented at 2026-03-02 16:12:

@pcahyna

Yes, sure, please do it. Thank you

Hmm it seems I am not allowed to commit to your branch. Perhaps it is because it is not in a personal fork, or you have not granted the permissions? https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork

I pushed it to my fork: https://github.com/pcahyna/rear/tree/partuuid-recovery , please reset your branch to it and force-push.

svlv commented at 2026-03-03 09:09:

By the way, all of these commits could be squashed. Re-writing git history made sense only if you wanted to keep them.

pcahyna commented at 2026-03-03 10:46:

@svlv of course I want to preserve the commits :-)

pcahyna commented at 2026-03-03 10:52:

Merging, thanks a lot for all the work!


[Export of Github issue for rear/rear.]