Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[master] Crashes trying to use an already existing btrf layout. Does not find the root mount point #718

Closed
wllacer opened this issue Nov 15, 2021 · 33 comments · Fixed by #732

Comments

@wllacer
Copy link
Contributor

wllacer commented Nov 15, 2021

I have a somewhat peculiar btrfs layout (a flat one in the sense of https://btrfs.wiki.kernel.org/index.php/SysadminGuide). For reasons, i decided it was the one that suited me, but it is not set in stone
layout via findmnt


└─/mnt                              /dev/loop0p2[/root]
                                                       btrfs      rw,noatime,ssd,space_cache=v2,subvolid=256,subvol=/root
  ├─/mnt/boot                       /dev/loop0p1       vfat       rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro
  ├─/mnt/home                       /dev/loop0p2[/home]
  │                                                    btrfs      rw,noatime,ssd,space_cache=v2,subvolid=257,subvol=/home
  ├─/mnt/opt                        /dev/loop0p2[/opt] btrfs      rw,noatime,ssd,space_cache=v2,subvolid=259,subvol=/opt
  ├─/mnt/srv                        /dev/loop0p2[/srv] btrfs      rw,noatime,ssd,space_cache=v2,subvolid=260,subvol=/srv
  └─/mnt/var                        /dev/loop0p2[/var] btrfs      rw,noatime,ssd,space_cache=v2,subvolid=261,subvol=/var

Note that the root dir is also a subvolume.
Using this structure i run archinstall NOT doing anything disk related (for the time being i'm content to have my own partitioning/mounting script). When the system ought to pacstrap the base directories, archinstall abends with the following messages

Getting mount information for device path /dev/loop0p2[/root]
Could not get PARTUUID for /dev/loop0p2[/root]: lsblk: /dev/loop0p2[/root]: no es un dispositivo de bloques
{
   "blockdevices": [

   ]
}

[!] A log file has been created here: /var/log/archinstall/install.log
    Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues
Traceback (most recent call last):
...
  File "/home/werner/projects/archinstall/archinstall/lib/disk/helpers.py", line 168, in get_partitions_in_use
    mounts.append(Partition(target['source'], None, filesystem=target.get('fstype', None), mountpoint=target['target']))
  File "/home/werner/projects/archinstall/archinstall/lib/disk/partition.py", line 41, in __init__
    raise DiskError(f"{self} was given a mountpoint but the actual mountpoint differs: {mount_information.get('target', None)}")
  File "/home/werner/projects/archinstall/archinstall/lib/disk/partition.py", line 70, in __repr__
    return f'Partition(path={self.path}, size={self.size}, PARTUUID={self.uuid}, fs={self.filesystem}{mount_repr})'
  File "/home/werner/projects/archinstall/archinstall/lib/disk/partition.py", line 153, in uuid
    raise DiskError(f"Could not get PARTUUID for {self.path}: {partuuid_struct}")
archinstall.lib.exceptions.DiskError: Could not get PARTUUID for /dev/loop0p2[/root]: lsblk: /dev/loop0p2[/root]: no es un dispositivo de bloques
{
   "blockdevices": [

   ]
}

No wonder because my actual lsblk output is

[werner@xerneas test]$ lsblk --json
{
   "blockdevices": [
      {
         "name": "loop0",
         "maj:min": "7:0",
         "rm": false,
         "size": "8G",
         "ro": false,
         "type": "loop",
         "mountpoints": [
             null
         ],
         "children": [
            {
               "name": "loop0p1",
               "maj:min": "259:0",
               "rm": false,
               "size": "1020M",
               "ro": false,
               "type": "part",
               "mountpoints": [
                   "/mnt/boot"
               ]
            },{
               "name": "loop0p2",
               "maj:min": "259:1",
               "rm": false,
               "size": "7G",
               "ro": false,
               "type": "part",
               "mountpoints": [
                   "/mnt/var", "/mnt/srv", "/mnt/opt", "/mnt/home", "/mnt"
               ]
            }
         ]
      }
@wllacer
Copy link
Contributor Author

wllacer commented Nov 15, 2021

@wllacer
Copy link
Contributor Author

wllacer commented Nov 15, 2021

It might be an issue exclusively with my layout, or a btrfs specific one. I will investigate the issue further, so you don't have to worry with this one for the time being.
Only problem this week is a bit loaded for me in "real life" and will be a bit slow on reporting advances

@wllacer
Copy link
Contributor Author

wllacer commented Nov 16, 2021

Could spend some time at it and can pinpoint the cause.
When using btrfs with subvolumes (especially if you are using a flat layout like mine) the concept of partition is subverted. For a start a physical partition can have multiple subvolumes, which act as distinct partitions for the OS
Naming conventions are also distinct: path name is now something like /dev/physicalpartition/[subvolume path] and the needed identifier is UUID + a subvolumeid (f.i. this is needed at systemd-boot entry file )
The default schema now used in archinstall for btrfs somehow avoids this mess, mounting the full physical partition on /, as the subvolumes are created inside the root partition. In my layout, root is even a subvolume like the others so I have no "classic" partition available.
What to do next?
First a "workaround" using the scripts which simply take what is mounted, no questions asked*, as instalation target (and fiddling only a little with systemd-boot and perhaps grub). If we want to wipe previous data might not be trivial (edited)

The real solution would need the rethinking of the Partition class and its relation to Filesystems to make it to get along with btrfs

By the way, the main reason of my layout is because I could boot into an older snapshot / very different root contents "simply" switching the subvolid in the entries file and/or changing fstab.

@hkaancaliskan
Copy link

@Torxed this is still broken with latest commit 7d991ec with Virtual Box VM Windows host
4 core, 4GB ram, 15GB drive

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

@Torxed this is still broken with latest commit 7d991ec with Virtual Box VM Windows host 4 core, 4GB ram, 15GB drive

I need your underlaying specs more than anything tho, because this is 99% guaranteed a timing issue between us being "too quick" and the hardware not reporting changes, and those changes are based on how quick your hosts CPU, cache and harddrive is.

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

@wllacer: Loop devices & USB drives are currently very shaky and I would almost dare say not supported at this moment.
Does this issue happen on anything other than loop devices? and if so, even with latest master? If so, give me the hardware physical specs of the machine so I can evaluate our timeouts better.

Regarding btrfs subvolumes, we're aware they're not complete. The support for this will be built on coming releases.

@hkaancaliskan
Copy link

hkaancaliskan commented Nov 18, 2021

Got it. Host machine specs are Intel i5 8250U, system uses nvme but vdi is in the 5400rpm HDD, 12GB ram (guest has 4gb), up to date windows 11.
I'll move vdi to nvme and try again.

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

Got it. Host machine specs are Intel i5 8250U, system uses nvme but vdi is in the 5400rpm HDD, 12GB ram (guest has 4gb), up to date windows 11. I'll move vdi to nvme and try again.

Try it, if it works let me know. We might need more than 10 seconds of sleep for the 5400RPM specs. I hoped it was enough.
I'll double it and see if that solves the issue.

@hkaancaliskan
Copy link

hkaancaliskan commented Nov 18, 2021

I've moved vdi to Adata Xpg 8200Pro 256GB nvme drive but still same error.
Edit: Oh wait, I've formatted disk (created new gpt table and new ext4 partition exactly) with fdisk then of course selected wipe disk in archinstall and it's working now.

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

I've now doubled the disk timeouts to roughly 20 seconds. Successful attempts should still be delayed by maximum a second or so. So you should be able to test with the 5400 RPM drive again and have different results.

@hkaancaliskan
Copy link

@Torxed I've tried 3 times on 5400rpm hdd and 2 of them failed with same error.
If it waits some time on "Marking partition as bootable" it fails, if it not waits and proceeds directly it doesn't fail and install succesfully.

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

I can increase the time some more, but it's specifically these two parts of the code that "breaks" when it breaks..
First, we have the issue of Partition().uuid, the meta function returns None after the grace period:

def uuid(self) -> Optional[str]:
"""
Returns the PARTUUID as returned by lsblk.
This is more reliable than relying on /dev/disk/by-partuuid as
it doesn't seam to be able to detect md raid partitions.
"""
for i in range(storage['DISK_RETRY_ATTEMPTS']):
self.partprobe()
partuuid_struct = SysCommand(f'lsblk -J -o+PARTUUID {self.path}')
if partuuid_struct.exit_code == 0:
if partition_information := next(iter(json.loads(partuuid_struct.decode('UTF-8'))['blockdevices']), None):
return partition_information.get('partuuid', None)
time.sleep(storage['DISK_TIMEOUTS'])
raise DiskError(f"Could not get PARTUUID for {self.path} using 'lsblk -J -o+PARTUUID {self.path}'")

And the following code will attempt to find a partition with None as PARTUUID and return which index that partition has:

def partuuid_to_index(self, uuid):
for i in range(storage['DISK_RETRY_ATTEMPTS']):
self.partprobe()
output = json.loads(SysCommand(f"lsblk --json -o+PARTUUID {self.blockdevice.device}").decode('UTF-8'))
for device in output['blockdevices']:
for index, partition in enumerate(device['children']):
if (partuuid := partition.get('partuuid', None)) and partuuid.lower() == uuid:
return index
time.sleep(storage['DISK_TIMEOUTS'])
raise DiskError(f"Failed to convert PARTUUID {uuid} to a partition index number on blockdevice {self.blockdevice.device}")

I really, really don't get why the kernel some times returns the UUID immediately, and some times not even after 20 seconds. But if you run lsblk -o+PARTUUID manually you'll see the PARTUUID right after archinstall crashes usually.

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

Oh for f*** sake I'm born yesterday..

return partition_information.get('partuuid', None)

Will ALWAYS return None.. my bad..

@hkaancaliskan
Copy link

Oh for f*** sake I'm born yesterday..

return partition_information.get('partuuid', None)

Will ALWAYS return None.. my bad..

Oh god lol
You spent a lot of time on this shit :/
I'm waiting your fix to be in master to test it.

Torxed added a commit that referenced this issue Nov 18, 2021
Swapped .get() statement for a verification om Partition().uuid
@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

Oh for f*** sake I'm born yesterday..

return partition_information.get('partuuid', None)

Will ALWAYS return None.. my bad..

Oh god lol You spent a lot of time on this shit :/ I'm waiting your fix to be in master to test it.

Haha, yea.. I haven't laughed this hard and cried at the same time..
The feeling when you thought you were so smart for using .get() to be safe - just to find out it bit you in the ass.

Oh well hehe.. You live and you learn ^^ Fix is in master now! Thank you for bouncing ideas!

@hkaancaliskan
Copy link

@Torxed I can confirm it's working perfectly! Thanks heaps!

@hkaancaliskan
Copy link

hkaancaliskan commented Nov 18, 2021

Oh wait another problem

VirtualBox_Arch_18_11_2021_16_32_20
VirtualBox_Arch_18_11_2021_16_56_59

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

Humm, this is a new issue. I don't think we need to create a completely separate issue.
I'll track it here and I'll submit a new PR for that one. Out of interest, after leaving the PC for a good 2 minutes or so, what does the lsblk command say, still no partuuid?

@Torxed Torxed reopened this Nov 18, 2021
@hkaancaliskan
Copy link

Partuuid is empty for ainstloop after 2 mins :/

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

I wonder if it should use the PARTUUID of the parent device instead of the logical loop device created by cryptsetup.
This is most likely just a regression when we fixed and updated all the issues with partitions in general. I'll investigate : )

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

Partuuid is empty for ainstloop after 2 mins :/

Minor issue, it's the __repr__ function that simply cannot get PARTUUID in a timely manner.
This will add some delay, but for now that's fine.

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

@hkaancaliskan: Should be fixed in master now! : )

@Torxed Torxed closed this as completed Nov 18, 2021
@wllacer
Copy link
Contributor Author

wllacer commented Nov 18, 2021

Bad news. Still crashes for me, although the error is a bit more specific

 File "/home/werner/projects/archinstall/archinstall/lib/installer.py", line 152, in partitions
    return get_partitions_in_use(self.target)
  File "/home/werner/projects/archinstall/archinstall/lib/disk/helpers.py", line 168, in get_partitions_in_use
    mounts.append(Partition(target['source'], None, filesystem=target.get('fstype', None), mountpoint=target['target']))
  File "/home/werner/projects/archinstall/archinstall/lib/disk/partition.py", line 41, in __init__
    raise DiskError(f"{self} was given a mountpoint but the actual mountpoint differs: {mount_information.get('target', None)}")
archinstall.lib.exceptions.DiskError: Partition(path=/dev/loop0p2[/root], size=-1, PARTUUID=None, fs=btrfs, mounted=/mnt) was given a mountpoint but the actual mountpoint differs: None

This error was the original error that prompted me to have a look into archinstall (it was with v2.2.0). It happened to me both under Virtualbox, looped devices, and a real SSD. Might be there are delays, my rig is extremely underpowered (an Intel Celeron N2840@2.16GHz, 8 GiB of RAM and a Crucial MX500 SSD), but my reading of the code hasn't changed: there are naming issues with complex btrfs subvolume schemas. I understand too well that the code for that beast is still not ready. And, as it is the question which bugs me, I want to help it solved.
I include a variant of my disk partitioning script, if anyone is interested in replicate my layout (change the extension to something suitable)

fmt_disk.txt

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

Bad news. Still crashes for me, although the error is a bit more specific

 File "/home/werner/projects/archinstall/archinstall/lib/installer.py", line 152, in partitions
    return get_partitions_in_use(self.target)
  File "/home/werner/projects/archinstall/archinstall/lib/disk/helpers.py", line 168, in get_partitions_in_use
    mounts.append(Partition(target['source'], None, filesystem=target.get('fstype', None), mountpoint=target['target']))
  File "/home/werner/projects/archinstall/archinstall/lib/disk/partition.py", line 41, in __init__
    raise DiskError(f"{self} was given a mountpoint but the actual mountpoint differs: {mount_information.get('target', None)}")
archinstall.lib.exceptions.DiskError: Partition(path=/dev/loop0p2[/root], size=-1, PARTUUID=None, fs=btrfs, mounted=/mnt) was given a mountpoint but the actual mountpoint differs: None

This error was the original error that prompted me to have a look into archinstall (it was with v2.2.0). It happened to me both under Virtualbox, looped devices, and a real SSD. Might be there are delays, my rig is extremely underpowered (an Intel Celeron N2840@2.16GHz, 8 GiB of RAM and a Crucial MX500 SSD), but my reading of the code hasn't changed: there are naming issues with complex btrfs subvolume schemas. I understand too well that the code for that beast is still not ready. And, as it is the question which bugs me, I want to help it solved. I include a variant of my disk partitioning script, if anyone is interested in replicate my layout (change the extension to something suitable)

fmt_disk.txt

IIRC there was complaints about me mounting the subvolumes, but this script mounts subvolumes as well.
I can't make heads or tails of what's the best practice at this moment. It's a lot of back and forth and walls of information, but without really any clarity to the context.

I can wrap my head around btrfs and subvolumes, but I'll need a few days of tinkering with it.
And I don't see huge differences in the code we have and that script either quite frankly.

I will extract the command sequence used (and probably create a /var/log/archinstall/cmd_history.txt) and compare the two in more detail, but overall.. the "layout" looks pretty similar in terms of command execution.

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

mkfs.btrfs -f /dev/mapper/ainstloop
mount /dev/mapper/ainstloop /mnt/archinstall/

btrfs subvolume create /mnt/archinstall/home
mount /dev/mapper/ainstloop /mnt/archinstall/home -o subvol=@/home

btrfs subvolume create /mnt/archinstall/var/log
mount /dev/mapper/ainstloop /mnt/archinstall/var/log -o subvol=@/var/log

btrfs subvolume create /mnt/archinstall/var/cache/pacman/pkg
mount /dev/mapper/ainstloop /mnt/archinstall/var/cache/pacman/pkg -o subvol=@/var/cache/pacman/pkg

btrfs subvolume create /mnt/archinstall/.snapshots
mount /dev/mapper/ainstloop /mnt/archinstall/.snapshots -o subvol=@/.snapshots

vs fmt_disk.txt (converted your nomenclature of mounts and partition names to match for diff purposes)

mkfs.btrfs -f /dev/mapper/ainstloop
mount -t btrfs /dev/mapper/ainstloop /mnt/archinstall/

btrfs subvolume create /mnt/archinstall/root
mount -o subvol=root /dev/mapper/ainstloop /mnt/archinstall

btrfs subvolume create /mnt/archinstall/.snapshots

btrfs subvolume create /mnt/archinstall/home
mount -o subvol=home /dev/mapper/ainstloop /mnt/archinstall/home

btrfs subvolume create /mnt/archinstall/opt
mount -o subvol=opt /dev/mapper/ainstloop /mnt/archinstall/opt

btrfs subvolume create /mnt/archinstall/srv
mount -o subvol=srv /dev/mapper/ainstloop /mnt/archinstall/srv

btrfs subvolume create /mnt/archinstall/var
mount -o subvol=var /dev/mapper/ainstloop /mnt/archinstall/var

umount /mnt/ainstloop # Is done prior to running the above 'mount -o subvol'

The only huge difference I can see is that you unmount /mnt (in my case /mnt/archinstall) before you re-mount all your submounts, which I suspect include /root that you're referring to. Which has to do with the 3 different types of "strategies" that btrfs suggests.

@wllacer
Copy link
Contributor Author

wllacer commented Nov 18, 2021

There is a subtle difference. You create one simple file tree under /mnt/archinstall. Subvolumes behavea as subdirectores in the same partition. And the root partition has a name as any other (no subvolume in name) .
I make the filesystem, create subvolumes and I mount one of these (not the partition) as the "root". Anyone of them behave as separate trees, as if they were separate partitons. And I need to mount them, one by one. And the naming convention changes for the / mount to partitionid-subvolume

@Torxed
Copy link
Member

Torxed commented Nov 18, 2021

I see, I'll take a second look at the diff with that in mind.
But I think I need some rest before that because it sounds simple but I'm missing it heh.

Edit: Re-opening this as it's related to re-using existing BTRFS structures and not necessarily one of the issues mentioned during this thread.

@Torxed Torxed reopened this Nov 18, 2021
@wllacer
Copy link
Contributor Author

wllacer commented Nov 18, 2021

edited
I confess.
When I decided to choose that schema, for me the most important thing was that i could have two different root "subvolumes" (Arch and another distro f.i. -not true unless i had two var also) without needing a physical partition. Simply i change the subvolid in the / entry in fstab the boot entries and voila. distro hopping
it's a bit more complex for different distros but works with various Archlnux setups

@wllacer
Copy link
Contributor Author

wllacer commented Nov 22, 2021

I could work a little on this problem. And I'm glad to say that I managed at last a minimal installation on my BTRFS layout, using --script minimal and using the preexisting mount point (still /mnt btw).
The culprit is that the system gives any subvolume mounted device path as device_path[subvolume_path] i.e. the same notation as bind mounts. But sadly, neither findmnt nor lsblk recognize this notation as a device name argument. The former returns nothing and the latter an error if used as arguments. The havoc it creates in the disk/* modules is easy to understand.
I attach a file with a patch against master, with what i've done to get it running. It's just a hack, with the minimal changes to allow the installation to succeed, so you can get the idea what we have to deal.
The image created can still not boot. It needs the subvol or subvolid added in the boot option lines as in this example for gummi-boot (sorry systemd-boot)

options root=/dev/sda3 rootflags=subvol=root rw

btrfs_3.patch.txt

@wllacer
Copy link
Contributor Author

wllacer commented Nov 25, 2021

EUREKA. I got my setup booting under qemu. The last change has been to modify how the systemd-bootctl entry is generated to include the line above.
Code is still a hack (i'm solving problems as they appear) and i have still two open problems

  • with the minimal install I'm getting /dev/sda2 (the disk from my real machine) as swap device ¿? at the VM genfstab is doing it ¿?
  • i've found that root_fs_type (used in creating the boot entry) is None (my mistake)

If anyone is interested below you'll find a patch from my master, with all the changes till now

btrfs_4.patch.txt edited had an error

Edited: the two problems are fixed now

@Torxed Torxed added this to the v2.3.1 milestone Dec 2, 2021
@Torxed
Copy link
Member

Torxed commented Dec 2, 2021

Feedback has also been given in #781

@wllacer
Copy link
Contributor Author

wllacer commented Dec 4, 2021

I can now create any (well many) weird kind of subvolumes and their mounting. No UI still. but works fine with a disk_layouts file.
Once i clean it up a bit and document some of its quirks, i will load it more formally. We're close to the end.
Surprinsingly the creation and mounting part is rather slim change.
For testing i've created (adapted from guided) a script called guia-hd, which only performs disk partitioning and mounting (which might have some other uses

btrfs_5.patch.txt Is the accumulated patch set till now

user_disk_layout.json.txt the test layout i use. Never try this in a real environment ;-)

@Torxed
Copy link
Member

Torxed commented Dec 31, 2021

It's in master and in the v2.3.1 branch now. So scheduled for release in the upcoming release which I was planning on having done soon. It's going to be a minor release to address some patches, all of which are completed now. So this was the last thing in that version : ) Good job on this one, you've done a really good job getting to know the code really fast, all delays have been on my part. Happy new year!

@Torxed Torxed closed this as completed Dec 31, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants