gpt-auto: try to handle LUKS root partitions better
If the root file system is located on an encrypted root disk, we'll not find the GPT partition table for it. Let's fix that by following the slaves/ symlinks in /sys for the device. We only handle devices having exactly one backing device. Also see: #1167
This commit is contained in:
parent
5e8d4254f9
commit
c6ba0c184d
|
@ -799,6 +799,10 @@ static int get_block_device(const char *path, dev_t *dev) {
|
|||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
/* Get's the block device directly backing a file system. If
|
||||
* the block device is encrypted, returns the device mapper
|
||||
* block device. */
|
||||
|
||||
if (lstat(path, &st))
|
||||
return -errno;
|
||||
|
||||
|
@ -816,6 +820,77 @@ static int get_block_device(const char *path, dev_t *dev) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int get_block_device_harder(const char *path, dev_t *dev) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
_cleanup_free_ char *p = NULL, *t = NULL;
|
||||
struct dirent *de, *found = NULL;
|
||||
const char *q;
|
||||
unsigned maj, min;
|
||||
dev_t dt;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
/* Gets the backing block device for a file system, and
|
||||
* handles LUKS encrypted file systems, looking for its
|
||||
* immediate parent, if there is one. */
|
||||
|
||||
r = get_block_device(path, &dt);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
d = opendir(p);
|
||||
if (!d) {
|
||||
if (errno == ENOENT)
|
||||
goto fallback;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
FOREACH_DIRENT_ALL(de, d, return -errno) {
|
||||
|
||||
if (STR_IN_SET(de->d_name, ".", ".."))
|
||||
continue;
|
||||
|
||||
if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
|
||||
continue;
|
||||
|
||||
if (found) /* Don't try to support multiple backing block devices */
|
||||
goto fallback;
|
||||
|
||||
found = de;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
goto fallback;
|
||||
|
||||
q = strjoina(p, "/", found->d_name, "/dev");
|
||||
|
||||
r = read_one_line_file(q, &t);
|
||||
if (r == -ENOENT)
|
||||
goto fallback;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sscanf(t, "%u:%u", &maj, &min) != 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (maj == 0)
|
||||
goto fallback;
|
||||
|
||||
*dev = makedev(maj, min);
|
||||
return 1;
|
||||
|
||||
fallback:
|
||||
*dev = dt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse_proc_cmdline_item(const char *key, const char *value) {
|
||||
int r;
|
||||
|
||||
|
@ -883,11 +958,11 @@ static int add_mounts(void) {
|
|||
dev_t devno;
|
||||
int r;
|
||||
|
||||
r = get_block_device("/", &devno);
|
||||
r = get_block_device_harder("/", &devno);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine block device of root file system: %m");
|
||||
else if (r == 0) {
|
||||
r = get_block_device("/usr", &devno);
|
||||
r = get_block_device_harder("/usr", &devno);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
|
||||
else if (r == 0) {
|
||||
|
|
Loading…
Reference in a new issue