Skip to content

Commit 9086739

Browse files
jackpot51brs17
authored andcommitted
fix: bug in path to UUID code with multi-device btrfs (#31)
This also makes the UUID matching code more robust at the expense of using the external tool `findmnt' This bug is caused by the assumtion that there is a 1-1 correspondence between device files and UUIDs (which is almost always true). Unfortunately BTRFS multi-device filesystems may have multiple devices associated with a single UUID. The old link reading code does not handle this case and fails to work. Ultimately it's probably better to use a upstream maintained tool for computing path -> UUID as it is subtle and not a core problem this tool is trying to solve. Also, `findmnt' is already provided by the `util-linux' package so another package dependency is not added. Co-authored-by: Ben S <benpack101@gmail.com>
1 parent e314068 commit 9086739

File tree

1 file changed

+12
-13
lines changed

1 file changed

+12
-13
lines changed

kernelstub/drive.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
terms.
2323
"""
2424

25-
import os, logging
25+
import os, logging, subprocess
2626

2727
class NoBlockDevError(Exception):
2828
pass
@@ -56,7 +56,7 @@ def __init__(self, root_path="/", esp_path="/boot/efi"):
5656
self.esp_fs = self.get_part_dev(self.esp_path)
5757
self.drive_name = self.get_drive_dev(self.esp_fs)
5858
self.esp_num = self.esp_fs[-1]
59-
self.root_uuid = self.get_uuid(self.root_fs[5:])
59+
self.root_uuid = self.get_uuid(self.root_path)
6060
except NoBlockDevError as e:
6161
self.log.exception('Could not find a block device for the a ' +
6262
'partition. This is a critical error and we ' +
@@ -102,15 +102,14 @@ def get_drive_dev(self, esp):
102102
self.log.debug('ESP is a partition on /dev/%s' % disk_name)
103103
return disk_name
104104

105-
def get_uuid(self, fs):
106-
all_uuids = os.listdir('/dev/disk/by-uuid')
107-
self.log.debug('Looking for UUID for %s' % fs)
108-
self.log.debug('List of UUIDs:\n%s' % all_uuids)
109-
110-
for uuid in all_uuids:
111-
uuid_path = os.path.join('/dev/disk/by-uuid', uuid)
112-
if fs in os.path.realpath(uuid_path):
113-
return uuid
105+
def get_uuid(self, path):
106+
self.log.debug('Looking for UUID for path %s' % path)
107+
try:
108+
args = ['findmnt', '-n', '-o', 'uuid', '--mountpoint', path]
109+
result = subprocess.run(args, stdout=subprocess.PIPE)
110+
uuid = result.stdout.decode('ASCII')
111+
uuid = uuid.strip()
112+
return uuid
113+
except OSError as e:
114+
raise UUIDNotFoundError from e
114115

115-
raise UUIDNotFoundError
116-

0 commit comments

Comments
 (0)