We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[master] Booting encrypted installation is missing `/sbin/init`.
![screenshot](https://user-images.githubusercontent.com/861439/170537967-88f66aaa-09a2-475e-8bd9-779b098455ae.png)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `archinstall/lib/disk/btrfs/btrfs_helpers.py`
Content:
```
1 import pathlib
2 import logging
3 from typing import Optional
4 
5 from ...exceptions import SysCallError, DiskError
6 from ...general import SysCommand
7 from ...output import log
8 from ..helpers import get_mount_info
9 from .btrfssubvolume import BtrfsSubvolume
10 
11 
12 def mount_subvolume(installation, device, name, subvolume_information):
13 	# we normalize the subvolume name (getting rid of slash at the start if exists. In our implemenation has no semantic load.
14 	# Every subvolume is created from the top of the hierarchy- and simplifies its further use
15 	name = name.lstrip('/')
16 
17 	# renormalize the right hand.
18 	mountpoint = subvolume_information.get('mountpoint', None)
19 	if not mountpoint:
20 		return None
21 
22 	if type(mountpoint) == str:
23 		mountpoint = pathlib.Path(mountpoint)
24 
25 	installation_target = installation.target
26 	if type(installation_target) == str:
27 		installation_target = pathlib.Path(installation_target)
28 
29 	mountpoint = installation_target / mountpoint.relative_to(mountpoint.anchor)
30 	mountpoint.mkdir(parents=True, exist_ok=True)
31 
32 	mount_options = subvolume_information.get('options', [])
33 	if not any('subvol=' in x for x in mount_options):
34 		mount_options += [f'subvol={name}']
35 
36 	log(f"Mounting subvolume {name} on {device} to {mountpoint}", level=logging.INFO, fg="gray")
37 	SysCommand(f"mount {device.path} {mountpoint} -o {','.join(mount_options)}")
38 
39 
40 def setup_subvolumes(installation, partition_dict):
41 	"""
42 	Taken from: ..user_guides.py
43 
44 	partition['btrfs'] = {
45 		"subvolumes" : {
46 			"@":           "/",
47 			"@home":       "/home",
48 			"@log":        "/var/log",
49 			"@pkg":        "/var/cache/pacman/pkg",
50 			"@.snapshots": "/.snapshots"
51 		}
52 	}
53 	"""
54 	log(f"Setting up subvolumes: {partition_dict['btrfs']['subvolumes']}", level=logging.INFO, fg="gray")
55 	for name, right_hand in partition_dict['btrfs']['subvolumes'].items():
56 		# we normalize the subvolume name (getting rid of slash at the start if exists. In our implemenation has no semantic load.
57 		# Every subvolume is created from the top of the hierarchy- and simplifies its further use
58 		name = name.lstrip('/')
59 
60 		# renormalize the right hand.
61 		# mountpoint = None
62 		subvol_options = []
63 
64 		match right_hand:
65 			# case str(): # backwards-compatability
66 			# 	mountpoint = right_hand
67 			case dict():
68 				# mountpoint = right_hand.get('mountpoint', None)
69 				subvol_options = right_hand.get('options', [])
70 
71 		# We create the subvolume using the BTRFSPartition instance.
72 		# That way we ensure not only easy access, but also accurate mount locations etc.
73 		partition_dict['device_instance'].create_subvolume(name, installation=installation)
74 
75 		# Make the nodatacow processing now
76 		# It will be the main cause of creation of subvolumes which are not to be mounted
77 		# it is not an options which can be established by subvolume (but for whole file systems), and can be
78 		# set up via a simple attribute change in a directory (if empty). And here the directories are brand new
79 		if 'nodatacow' in subvol_options:
80 			if (cmd := SysCommand(f"chattr +C {installation.target}/{name}")).exit_code != 0:
81 				raise DiskError(f"Could not set  nodatacow attribute at {installation.target}/{name}: {cmd}")
82 			# entry is deleted so nodatacow doesn't propagate to the mount options
83 			del subvol_options[subvol_options.index('nodatacow')]
84 		# Make the compress processing now
85 		# it is not an options which can be established by subvolume (but for whole file systems), and can be
86 		# set up via a simple attribute change in a directory (if empty). And here the directories are brand new
87 		# in this way only zstd compression is activaded
88 		# TODO WARNING it is not clear if it should be a standard feature, so it might need to be deactivated
89 
90 		if 'compress' in subvol_options:
91 			if not any(['compress' in filesystem_option for filesystem_option in partition_dict.get('filesystem', {}).get('mount_options', [])]):
92 				if (cmd := SysCommand(f"chattr +c {installation.target}/{name}")).exit_code != 0:
93 					raise DiskError(f"Could not set compress attribute at {installation.target}/{name}: {cmd}")
94 			# entry is deleted so compress doesn't propagate to the mount options
95 			del subvol_options[subvol_options.index('compress')]
96 
97 def subvolume_info_from_path(path :pathlib.Path) -> Optional[BtrfsSubvolume]:
98 	try:
99 		subvolume_name = None
100 		result = {}
101 		for index, line in enumerate(SysCommand(f"btrfs subvolume show {path}")):
102 			if index == 0:
103 				subvolume_name = line.strip().decode('UTF-8')
104 				continue
105 
106 			if b':' in line:
107 				key, value = line.strip().decode('UTF-8').split(':', 1)
108 
109 				# A bit of a hack, until I figure out how @dataclass
110 				# allows for hooking in a pre-processor to do this we have to do it here:
111 				result[key.lower().replace(' ', '_').replace('(s)', 's')] = value.strip()
112 
113 		return BtrfsSubvolume(**{'full_path' : path, 'name' : subvolume_name, **result})
114 
115 	except SysCallError:
116 		pass
117 
118 	return None
119 
120 def find_parent_subvolume(path :pathlib.Path, filters=[]):
121 	# A root path cannot have a parent
122 	if str(path) == '/':
123 		return None
124 
125 	if found_mount := get_mount_info(str(path.parent), traverse=True, ignore=filters):
126 		if not (subvolume := subvolume_info_from_path(found_mount['target'])):
127 			if found_mount['target'] == '/':
128 				return None
129 
130 			return find_parent_subvolume(path.parent, traverse=True, filters=[*filters, found_mount['target']])
131 
132 		return subvolume
```

Path: `archinstall/lib/disk/mapperdev.py`
Content:
```
1 import glob
2 import pathlib
3 import logging
4 import json
5 from dataclasses import dataclass
6 from typing import Optional, List, Dict, Any, Iterator, TYPE_CHECKING
7 
8 from ..exceptions import SysCallError
9 from ..general import SysCommand
10 from ..output import log
11 
12 if TYPE_CHECKING:
13 	from .btrfs import BtrfsSubvolume
14 
15 @dataclass
16 class MapperDev:
17 	mappername :str
18 
19 	@property
20 	def name(self):
21 		return self.mappername
22 
23 	@property
24 	def path(self):
25 		return f"/dev/mapper/{self.mappername}"
26 
27 	@property
28 	def partition(self):
29 		from .helpers import uevent, get_parent_of_partition
30 		from .partition import Partition
31 		from .blockdevice import BlockDevice
32 
33 		for mapper in glob.glob('/dev/mapper/*'):
34 			path_obj = pathlib.Path(mapper)
35 			if path_obj.name == self.mappername and pathlib.Path(mapper).is_symlink():
36 				dm_device = (pathlib.Path("/dev/mapper/") / path_obj.readlink()).resolve()
37 
38 				for slave in glob.glob(f"/sys/class/block/{dm_device.name}/slaves/*"):
39 					partition_belonging_to_dmcrypt_device = pathlib.Path(slave).name
40 					
41 					try:
42 						uevent_data = SysCommand(f"blkid -o export /dev/{partition_belonging_to_dmcrypt_device}").decode()
43 					except SysCallError as error:
44 						log(f"Could not get information on device /dev/{partition_belonging_to_dmcrypt_device}: {error}", level=logging.ERROR, fg="red")
45 					
46 					information = uevent(uevent_data)
47 					block_device = BlockDevice(get_parent_of_partition('/dev/' / pathlib.Path(information['DEVNAME'])))
48 
49 					return Partition(information['DEVNAME'], block_device=block_device)
50 
51 		raise ValueError(f"Could not convert {self.mappername} to a real dm-crypt device")
52 
53 	@property
54 	def mountpoint(self) -> Optional[pathlib.Path]:
55 		try:
56 			data = json.loads(SysCommand(f"findmnt --json -R {self.path}").decode())
57 			for filesystem in data['filesystems']:
58 				return pathlib.Path(filesystem.get('target'))
59 
60 		except SysCallError as error:
61 			# Not mounted anywhere most likely
62 			log(f"Could not locate mount information for {self.path}: {error}", level=logging.WARNING, fg="yellow")
63 			pass
64 
65 		return None
66 
67 	@property
68 	def mount_information(self) -> List[Dict[str, Any]]:
69 		from .helpers import find_mountpoint
70 		return list(find_mountpoint(self.path))
71 
72 	@property
73 	def filesystem(self) -> Optional[str]:
74 		from .helpers import get_filesystem_type
75 		return get_filesystem_type(self.path)
76 
77 	@property
78 	def subvolumes(self) -> Iterator['BtrfsSubvolume']:
79 		from .btrfs import subvolume_info_from_path
80 		
81 		for mountpoint in self.mount_information:
82 			if subvolume := subvolume_info_from_path(mountpoint):
83 				yield subvolume
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/archinstall/lib/disk/btrfs/btrfs_helpers.py b/archinstall/lib/disk/btrfs/btrfs_helpers.py
--- a/archinstall/lib/disk/btrfs/btrfs_helpers.py
+++ b/archinstall/lib/disk/btrfs/btrfs_helpers.py
@@ -112,8 +112,8 @@
 
 		return BtrfsSubvolume(**{'full_path' : path, 'name' : subvolume_name, **result})
 
-	except SysCallError:
-		pass
+	except SysCallError as error:
+		log(f"Could not retrieve subvolume information from {path}: {error}", level=logging.WARNING, fg="orange")
 
 	return None
 
diff --git a/archinstall/lib/disk/mapperdev.py b/archinstall/lib/disk/mapperdev.py
--- a/archinstall/lib/disk/mapperdev.py
+++ b/archinstall/lib/disk/mapperdev.py
@@ -77,7 +77,8 @@
 	@property
 	def subvolumes(self) -> Iterator['BtrfsSubvolume']:
 		from .btrfs import subvolume_info_from_path
-		
+
 		for mountpoint in self.mount_information:
-			if subvolume := subvolume_info_from_path(mountpoint):
-				yield subvolume
\ No newline at end of file
+			if target := mountpoint.get('target'):
+				if subvolume := subvolume_info_from_path(pathlib.Path(target)):
+					yield subvolume
\ No newline at end of file

{"golden_diff": "diff --git a/archinstall/lib/disk/btrfs/btrfs_helpers.py b/archinstall/lib/disk/btrfs/btrfs_helpers.py\n--- a/archinstall/lib/disk/btrfs/btrfs_helpers.py\n+++ b/archinstall/lib/disk/btrfs/btrfs_helpers.py\n@@ -112,8 +112,8 @@\n \n \t\treturn BtrfsSubvolume(**{'full_path' : path, 'name' : subvolume_name, **result})\n \n-\texcept SysCallError:\n-\t\tpass\n+\texcept SysCallError as error:\n+\t\tlog(f\"Could not retrieve subvolume information from {path}: {error}\", level=logging.WARNING, fg=\"orange\")\n \n \treturn None\n \ndiff --git a/archinstall/lib/disk/mapperdev.py b/archinstall/lib/disk/mapperdev.py\n--- a/archinstall/lib/disk/mapperdev.py\n+++ b/archinstall/lib/disk/mapperdev.py\n@@ -77,7 +77,8 @@\n \t@property\n \tdef subvolumes(self) -> Iterator['BtrfsSubvolume']:\n \t\tfrom .btrfs import subvolume_info_from_path\n-\t\t\n+\n \t\tfor mountpoint in self.mount_information:\n-\t\t\tif subvolume := subvolume_info_from_path(mountpoint):\n-\t\t\t\tyield subvolume\n\\ No newline at end of file\n+\t\t\tif target := mountpoint.get('target'):\n+\t\t\t\tif subvolume := subvolume_info_from_path(pathlib.Path(target)):\n+\t\t\t\t\tyield subvolume\n\\ No newline at end of file\n", "issue": "[master] Booting encrypted installation is missing `/sbin/init`.\n![screenshot](https://user-images.githubusercontent.com/861439/170537967-88f66aaa-09a2-475e-8bd9-779b098455ae.png)\r\n\n", "before_files": [{"content": "import pathlib\nimport logging\nfrom typing import Optional\n\nfrom ...exceptions import SysCallError, DiskError\nfrom ...general import SysCommand\nfrom ...output import log\nfrom ..helpers import get_mount_info\nfrom .btrfssubvolume import BtrfsSubvolume\n\n\ndef mount_subvolume(installation, device, name, subvolume_information):\n\t# we normalize the subvolume name (getting rid of slash at the start if exists. In our implemenation has no semantic load.\n\t# Every subvolume is created from the top of the hierarchy- and simplifies its further use\n\tname = name.lstrip('/')\n\n\t# renormalize the right hand.\n\tmountpoint = subvolume_information.get('mountpoint', None)\n\tif not mountpoint:\n\t\treturn None\n\n\tif type(mountpoint) == str:\n\t\tmountpoint = pathlib.Path(mountpoint)\n\n\tinstallation_target = installation.target\n\tif type(installation_target) == str:\n\t\tinstallation_target = pathlib.Path(installation_target)\n\n\tmountpoint = installation_target / mountpoint.relative_to(mountpoint.anchor)\n\tmountpoint.mkdir(parents=True, exist_ok=True)\n\n\tmount_options = subvolume_information.get('options', [])\n\tif not any('subvol=' in x for x in mount_options):\n\t\tmount_options += [f'subvol={name}']\n\n\tlog(f\"Mounting subvolume {name} on {device} to {mountpoint}\", level=logging.INFO, fg=\"gray\")\n\tSysCommand(f\"mount {device.path} {mountpoint} -o {','.join(mount_options)}\")\n\n\ndef setup_subvolumes(installation, partition_dict):\n\t\"\"\"\n\tTaken from: ..user_guides.py\n\n\tpartition['btrfs'] = {\n\t\t\"subvolumes\" : {\n\t\t\t\"@\":           \"/\",\n\t\t\t\"@home\":       \"/home\",\n\t\t\t\"@log\":        \"/var/log\",\n\t\t\t\"@pkg\":        \"/var/cache/pacman/pkg\",\n\t\t\t\"@.snapshots\": \"/.snapshots\"\n\t\t}\n\t}\n\t\"\"\"\n\tlog(f\"Setting up subvolumes: {partition_dict['btrfs']['subvolumes']}\", level=logging.INFO, fg=\"gray\")\n\tfor name, right_hand in partition_dict['btrfs']['subvolumes'].items():\n\t\t# we normalize the subvolume name (getting rid of slash at the start if exists. In our implemenation has no semantic load.\n\t\t# Every subvolume is created from the top of the hierarchy- and simplifies its further use\n\t\tname = name.lstrip('/')\n\n\t\t# renormalize the right hand.\n\t\t# mountpoint = None\n\t\tsubvol_options = []\n\n\t\tmatch right_hand:\n\t\t\t# case str(): # backwards-compatability\n\t\t\t# \tmountpoint = right_hand\n\t\t\tcase dict():\n\t\t\t\t# mountpoint = right_hand.get('mountpoint', None)\n\t\t\t\tsubvol_options = right_hand.get('options', [])\n\n\t\t# We create the subvolume using the BTRFSPartition instance.\n\t\t# That way we ensure not only easy access, but also accurate mount locations etc.\n\t\tpartition_dict['device_instance'].create_subvolume(name, installation=installation)\n\n\t\t# Make the nodatacow processing now\n\t\t# It will be the main cause of creation of subvolumes which are not to be mounted\n\t\t# it is not an options which can be established by subvolume (but for whole file systems), and can be\n\t\t# set up via a simple attribute change in a directory (if empty). And here the directories are brand new\n\t\tif 'nodatacow' in subvol_options:\n\t\t\tif (cmd := SysCommand(f\"chattr +C {installation.target}/{name}\")).exit_code != 0:\n\t\t\t\traise DiskError(f\"Could not set  nodatacow attribute at {installation.target}/{name}: {cmd}\")\n\t\t\t# entry is deleted so nodatacow doesn't propagate to the mount options\n\t\t\tdel subvol_options[subvol_options.index('nodatacow')]\n\t\t# Make the compress processing now\n\t\t# it is not an options which can be established by subvolume (but for whole file systems), and can be\n\t\t# set up via a simple attribute change in a directory (if empty). And here the directories are brand new\n\t\t# in this way only zstd compression is activaded\n\t\t# TODO WARNING it is not clear if it should be a standard feature, so it might need to be deactivated\n\n\t\tif 'compress' in subvol_options:\n\t\t\tif not any(['compress' in filesystem_option for filesystem_option in partition_dict.get('filesystem', {}).get('mount_options', [])]):\n\t\t\t\tif (cmd := SysCommand(f\"chattr +c {installation.target}/{name}\")).exit_code != 0:\n\t\t\t\t\traise DiskError(f\"Could not set compress attribute at {installation.target}/{name}: {cmd}\")\n\t\t\t# entry is deleted so compress doesn't propagate to the mount options\n\t\t\tdel subvol_options[subvol_options.index('compress')]\n\ndef subvolume_info_from_path(path :pathlib.Path) -> Optional[BtrfsSubvolume]:\n\ttry:\n\t\tsubvolume_name = None\n\t\tresult = {}\n\t\tfor index, line in enumerate(SysCommand(f\"btrfs subvolume show {path}\")):\n\t\t\tif index == 0:\n\t\t\t\tsubvolume_name = line.strip().decode('UTF-8')\n\t\t\t\tcontinue\n\n\t\t\tif b':' in line:\n\t\t\t\tkey, value = line.strip().decode('UTF-8').split(':', 1)\n\n\t\t\t\t# A bit of a hack, until I figure out how @dataclass\n\t\t\t\t# allows for hooking in a pre-processor to do this we have to do it here:\n\t\t\t\tresult[key.lower().replace(' ', '_').replace('(s)', 's')] = value.strip()\n\n\t\treturn BtrfsSubvolume(**{'full_path' : path, 'name' : subvolume_name, **result})\n\n\texcept SysCallError:\n\t\tpass\n\n\treturn None\n\ndef find_parent_subvolume(path :pathlib.Path, filters=[]):\n\t# A root path cannot have a parent\n\tif str(path) == '/':\n\t\treturn None\n\n\tif found_mount := get_mount_info(str(path.parent), traverse=True, ignore=filters):\n\t\tif not (subvolume := subvolume_info_from_path(found_mount['target'])):\n\t\t\tif found_mount['target'] == '/':\n\t\t\t\treturn None\n\n\t\t\treturn find_parent_subvolume(path.parent, traverse=True, filters=[*filters, found_mount['target']])\n\n\t\treturn subvolume", "path": "archinstall/lib/disk/btrfs/btrfs_helpers.py"}, {"content": "import glob\nimport pathlib\nimport logging\nimport json\nfrom dataclasses import dataclass\nfrom typing import Optional, List, Dict, Any, Iterator, TYPE_CHECKING\n\nfrom ..exceptions import SysCallError\nfrom ..general import SysCommand\nfrom ..output import log\n\nif TYPE_CHECKING:\n\tfrom .btrfs import BtrfsSubvolume\n\n@dataclass\nclass MapperDev:\n\tmappername :str\n\n\t@property\n\tdef name(self):\n\t\treturn self.mappername\n\n\t@property\n\tdef path(self):\n\t\treturn f\"/dev/mapper/{self.mappername}\"\n\n\t@property\n\tdef partition(self):\n\t\tfrom .helpers import uevent, get_parent_of_partition\n\t\tfrom .partition import Partition\n\t\tfrom .blockdevice import BlockDevice\n\n\t\tfor mapper in glob.glob('/dev/mapper/*'):\n\t\t\tpath_obj = pathlib.Path(mapper)\n\t\t\tif path_obj.name == self.mappername and pathlib.Path(mapper).is_symlink():\n\t\t\t\tdm_device = (pathlib.Path(\"/dev/mapper/\") / path_obj.readlink()).resolve()\n\n\t\t\t\tfor slave in glob.glob(f\"/sys/class/block/{dm_device.name}/slaves/*\"):\n\t\t\t\t\tpartition_belonging_to_dmcrypt_device = pathlib.Path(slave).name\n\t\t\t\t\t\n\t\t\t\t\ttry:\n\t\t\t\t\t\tuevent_data = SysCommand(f\"blkid -o export /dev/{partition_belonging_to_dmcrypt_device}\").decode()\n\t\t\t\t\texcept SysCallError as error:\n\t\t\t\t\t\tlog(f\"Could not get information on device /dev/{partition_belonging_to_dmcrypt_device}: {error}\", level=logging.ERROR, fg=\"red\")\n\t\t\t\t\t\n\t\t\t\t\tinformation = uevent(uevent_data)\n\t\t\t\t\tblock_device = BlockDevice(get_parent_of_partition('/dev/' / pathlib.Path(information['DEVNAME'])))\n\n\t\t\t\t\treturn Partition(information['DEVNAME'], block_device=block_device)\n\n\t\traise ValueError(f\"Could not convert {self.mappername} to a real dm-crypt device\")\n\n\t@property\n\tdef mountpoint(self) -> Optional[pathlib.Path]:\n\t\ttry:\n\t\t\tdata = json.loads(SysCommand(f\"findmnt --json -R {self.path}\").decode())\n\t\t\tfor filesystem in data['filesystems']:\n\t\t\t\treturn pathlib.Path(filesystem.get('target'))\n\n\t\texcept SysCallError as error:\n\t\t\t# Not mounted anywhere most likely\n\t\t\tlog(f\"Could not locate mount information for {self.path}: {error}\", level=logging.WARNING, fg=\"yellow\")\n\t\t\tpass\n\n\t\treturn None\n\n\t@property\n\tdef mount_information(self) -> List[Dict[str, Any]]:\n\t\tfrom .helpers import find_mountpoint\n\t\treturn list(find_mountpoint(self.path))\n\n\t@property\n\tdef filesystem(self) -> Optional[str]:\n\t\tfrom .helpers import get_filesystem_type\n\t\treturn get_filesystem_type(self.path)\n\n\t@property\n\tdef subvolumes(self) -> Iterator['BtrfsSubvolume']:\n\t\tfrom .btrfs import subvolume_info_from_path\n\t\t\n\t\tfor mountpoint in self.mount_information:\n\t\t\tif subvolume := subvolume_info_from_path(mountpoint):\n\t\t\t\tyield subvolume", "path": "archinstall/lib/disk/mapperdev.py"}], "after_files": [{"content": "import pathlib\nimport logging\nfrom typing import Optional\n\nfrom ...exceptions import SysCallError, DiskError\nfrom ...general import SysCommand\nfrom ...output import log\nfrom ..helpers import get_mount_info\nfrom .btrfssubvolume import BtrfsSubvolume\n\n\ndef mount_subvolume(installation, device, name, subvolume_information):\n\t# we normalize the subvolume name (getting rid of slash at the start if exists. In our implemenation has no semantic load.\n\t# Every subvolume is created from the top of the hierarchy- and simplifies its further use\n\tname = name.lstrip('/')\n\n\t# renormalize the right hand.\n\tmountpoint = subvolume_information.get('mountpoint', None)\n\tif not mountpoint:\n\t\treturn None\n\n\tif type(mountpoint) == str:\n\t\tmountpoint = pathlib.Path(mountpoint)\n\n\tinstallation_target = installation.target\n\tif type(installation_target) == str:\n\t\tinstallation_target = pathlib.Path(installation_target)\n\n\tmountpoint = installation_target / mountpoint.relative_to(mountpoint.anchor)\n\tmountpoint.mkdir(parents=True, exist_ok=True)\n\n\tmount_options = subvolume_information.get('options', [])\n\tif not any('subvol=' in x for x in mount_options):\n\t\tmount_options += [f'subvol={name}']\n\n\tlog(f\"Mounting subvolume {name} on {device} to {mountpoint}\", level=logging.INFO, fg=\"gray\")\n\tSysCommand(f\"mount {device.path} {mountpoint} -o {','.join(mount_options)}\")\n\n\ndef setup_subvolumes(installation, partition_dict):\n\t\"\"\"\n\tTaken from: ..user_guides.py\n\n\tpartition['btrfs'] = {\n\t\t\"subvolumes\" : {\n\t\t\t\"@\":           \"/\",\n\t\t\t\"@home\":       \"/home\",\n\t\t\t\"@log\":        \"/var/log\",\n\t\t\t\"@pkg\":        \"/var/cache/pacman/pkg\",\n\t\t\t\"@.snapshots\": \"/.snapshots\"\n\t\t}\n\t}\n\t\"\"\"\n\tlog(f\"Setting up subvolumes: {partition_dict['btrfs']['subvolumes']}\", level=logging.INFO, fg=\"gray\")\n\tfor name, right_hand in partition_dict['btrfs']['subvolumes'].items():\n\t\t# we normalize the subvolume name (getting rid of slash at the start if exists. In our implemenation has no semantic load.\n\t\t# Every subvolume is created from the top of the hierarchy- and simplifies its further use\n\t\tname = name.lstrip('/')\n\n\t\t# renormalize the right hand.\n\t\t# mountpoint = None\n\t\tsubvol_options = []\n\n\t\tmatch right_hand:\n\t\t\t# case str(): # backwards-compatability\n\t\t\t# \tmountpoint = right_hand\n\t\t\tcase dict():\n\t\t\t\t# mountpoint = right_hand.get('mountpoint', None)\n\t\t\t\tsubvol_options = right_hand.get('options', [])\n\n\t\t# We create the subvolume using the BTRFSPartition instance.\n\t\t# That way we ensure not only easy access, but also accurate mount locations etc.\n\t\tpartition_dict['device_instance'].create_subvolume(name, installation=installation)\n\n\t\t# Make the nodatacow processing now\n\t\t# It will be the main cause of creation of subvolumes which are not to be mounted\n\t\t# it is not an options which can be established by subvolume (but for whole file systems), and can be\n\t\t# set up via a simple attribute change in a directory (if empty). And here the directories are brand new\n\t\tif 'nodatacow' in subvol_options:\n\t\t\tif (cmd := SysCommand(f\"chattr +C {installation.target}/{name}\")).exit_code != 0:\n\t\t\t\traise DiskError(f\"Could not set  nodatacow attribute at {installation.target}/{name}: {cmd}\")\n\t\t\t# entry is deleted so nodatacow doesn't propagate to the mount options\n\t\t\tdel subvol_options[subvol_options.index('nodatacow')]\n\t\t# Make the compress processing now\n\t\t# it is not an options which can be established by subvolume (but for whole file systems), and can be\n\t\t# set up via a simple attribute change in a directory (if empty). And here the directories are brand new\n\t\t# in this way only zstd compression is activaded\n\t\t# TODO WARNING it is not clear if it should be a standard feature, so it might need to be deactivated\n\n\t\tif 'compress' in subvol_options:\n\t\t\tif not any(['compress' in filesystem_option for filesystem_option in partition_dict.get('filesystem', {}).get('mount_options', [])]):\n\t\t\t\tif (cmd := SysCommand(f\"chattr +c {installation.target}/{name}\")).exit_code != 0:\n\t\t\t\t\traise DiskError(f\"Could not set compress attribute at {installation.target}/{name}: {cmd}\")\n\t\t\t# entry is deleted so compress doesn't propagate to the mount options\n\t\t\tdel subvol_options[subvol_options.index('compress')]\n\ndef subvolume_info_from_path(path :pathlib.Path) -> Optional[BtrfsSubvolume]:\n\ttry:\n\t\tsubvolume_name = None\n\t\tresult = {}\n\t\tfor index, line in enumerate(SysCommand(f\"btrfs subvolume show {path}\")):\n\t\t\tif index == 0:\n\t\t\t\tsubvolume_name = line.strip().decode('UTF-8')\n\t\t\t\tcontinue\n\n\t\t\tif b':' in line:\n\t\t\t\tkey, value = line.strip().decode('UTF-8').split(':', 1)\n\n\t\t\t\t# A bit of a hack, until I figure out how @dataclass\n\t\t\t\t# allows for hooking in a pre-processor to do this we have to do it here:\n\t\t\t\tresult[key.lower().replace(' ', '_').replace('(s)', 's')] = value.strip()\n\n\t\treturn BtrfsSubvolume(**{'full_path' : path, 'name' : subvolume_name, **result})\n\n\texcept SysCallError as error:\n\t\tlog(f\"Could not retrieve subvolume information from {path}: {error}\", level=logging.WARNING, fg=\"orange\")\n\n\treturn None\n\ndef find_parent_subvolume(path :pathlib.Path, filters=[]):\n\t# A root path cannot have a parent\n\tif str(path) == '/':\n\t\treturn None\n\n\tif found_mount := get_mount_info(str(path.parent), traverse=True, ignore=filters):\n\t\tif not (subvolume := subvolume_info_from_path(found_mount['target'])):\n\t\t\tif found_mount['target'] == '/':\n\t\t\t\treturn None\n\n\t\t\treturn find_parent_subvolume(path.parent, traverse=True, filters=[*filters, found_mount['target']])\n\n\t\treturn subvolume", "path": "archinstall/lib/disk/btrfs/btrfs_helpers.py"}, {"content": "import glob\nimport pathlib\nimport logging\nimport json\nfrom dataclasses import dataclass\nfrom typing import Optional, List, Dict, Any, Iterator, TYPE_CHECKING\n\nfrom ..exceptions import SysCallError\nfrom ..general import SysCommand\nfrom ..output import log\n\nif TYPE_CHECKING:\n\tfrom .btrfs import BtrfsSubvolume\n\n@dataclass\nclass MapperDev:\n\tmappername :str\n\n\t@property\n\tdef name(self):\n\t\treturn self.mappername\n\n\t@property\n\tdef path(self):\n\t\treturn f\"/dev/mapper/{self.mappername}\"\n\n\t@property\n\tdef partition(self):\n\t\tfrom .helpers import uevent, get_parent_of_partition\n\t\tfrom .partition import Partition\n\t\tfrom .blockdevice import BlockDevice\n\n\t\tfor mapper in glob.glob('/dev/mapper/*'):\n\t\t\tpath_obj = pathlib.Path(mapper)\n\t\t\tif path_obj.name == self.mappername and pathlib.Path(mapper).is_symlink():\n\t\t\t\tdm_device = (pathlib.Path(\"/dev/mapper/\") / path_obj.readlink()).resolve()\n\n\t\t\t\tfor slave in glob.glob(f\"/sys/class/block/{dm_device.name}/slaves/*\"):\n\t\t\t\t\tpartition_belonging_to_dmcrypt_device = pathlib.Path(slave).name\n\t\t\t\t\t\n\t\t\t\t\ttry:\n\t\t\t\t\t\tuevent_data = SysCommand(f\"blkid -o export /dev/{partition_belonging_to_dmcrypt_device}\").decode()\n\t\t\t\t\texcept SysCallError as error:\n\t\t\t\t\t\tlog(f\"Could not get information on device /dev/{partition_belonging_to_dmcrypt_device}: {error}\", level=logging.ERROR, fg=\"red\")\n\t\t\t\t\t\n\t\t\t\t\tinformation = uevent(uevent_data)\n\t\t\t\t\tblock_device = BlockDevice(get_parent_of_partition('/dev/' / pathlib.Path(information['DEVNAME'])))\n\n\t\t\t\t\treturn Partition(information['DEVNAME'], block_device=block_device)\n\n\t\traise ValueError(f\"Could not convert {self.mappername} to a real dm-crypt device\")\n\n\t@property\n\tdef mountpoint(self) -> Optional[pathlib.Path]:\n\t\ttry:\n\t\t\tdata = json.loads(SysCommand(f\"findmnt --json -R {self.path}\").decode())\n\t\t\tfor filesystem in data['filesystems']:\n\t\t\t\treturn pathlib.Path(filesystem.get('target'))\n\n\t\texcept SysCallError as error:\n\t\t\t# Not mounted anywhere most likely\n\t\t\tlog(f\"Could not locate mount information for {self.path}: {error}\", level=logging.WARNING, fg=\"yellow\")\n\t\t\tpass\n\n\t\treturn None\n\n\t@property\n\tdef mount_information(self) -> List[Dict[str, Any]]:\n\t\tfrom .helpers import find_mountpoint\n\t\treturn list(find_mountpoint(self.path))\n\n\t@property\n\tdef filesystem(self) -> Optional[str]:\n\t\tfrom .helpers import get_filesystem_type\n\t\treturn get_filesystem_type(self.path)\n\n\t@property\n\tdef subvolumes(self) -> Iterator['BtrfsSubvolume']:\n\t\tfrom .btrfs import subvolume_info_from_path\n\n\t\tfor mountpoint in self.mount_information:\n\t\t\tif target := mountpoint.get('target'):\n\t\t\t\tif subvolume := subvolume_info_from_path(pathlib.Path(target)):\n\t\t\t\t\tyield subvolume", "path": "archinstall/lib/disk/mapperdev.py"}]}