summaryrefslogtreecommitdiffstats
path: root/discover/device-handler.c
diff options
context:
space:
mode:
authorSam Mendoza-Jonas <sam@mendozajonas.com>2016-01-05 15:01:58 +1100
committerSam Mendoza-Jonas <sam@mendozajonas.com>2016-02-09 13:37:37 +1100
commitd9fc4558e66c32834f2a4fdab31010b40f0a88de (patch)
tree6ad9090c84d3fc65b4cbcbfde5a41acc802d5c1c /discover/device-handler.c
parent01e104dfb79a09bc28f8c5fb65bfe44596c25161 (diff)
downloadtalos-petitboot-d9fc4558e66c32834f2a4fdab31010b40f0a88de.zip
talos-petitboot-d9fc4558e66c32834f2a4fdab31010b40f0a88de.tar.gz
discover: Handle BTRFS root subvolumes
During install some distributions[0] will create subvolumes when formatting the root filesystem with BTRFS. In particular this can mean that bootloader config files will appear (in the case of GRUB) under /var/petitboot/mnt/dev/$device/@/boot/grub/ rather than the expected /var/petitboot/mnt/dev/$device/boot/grub/ If this is the case, perform all file operations from the parser relative to this subvolume rather than the mount point. At the moment this only supports the trivial case where the subvolume name for root is blank (ie. '@'). [0] In particular, Ubuntu from at least 14.04 Signed-off-by: Sam Mendoza-Jonas <sam@mendozajonas.com>
Diffstat (limited to 'discover/device-handler.c')
-rw-r--r--discover/device-handler.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/discover/device-handler.c b/discover/device-handler.c
index 5df0700..77f9e3c 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -1285,6 +1285,28 @@ static inline const char *get_device_path(struct discover_device *dev)
return dev->ramdisk ? dev->ramdisk->snapshot : dev->device_path;
}
+static char *check_subvols(struct discover_device *dev)
+{
+ const char *fstype = discover_device_get_param(dev, "ID_FS_TYPE");
+ struct stat sb;
+ char *path;
+ int rc;
+
+ if (strncmp(fstype, "btrfs", strlen("btrfs")))
+ return dev->mount_path;
+
+ /* On btrfs a device's root may be under a subvolume path */
+ path = join_paths(dev, dev->mount_path, "@");
+ rc = stat(path, &sb);
+ if (!rc && S_ISDIR(sb.st_mode)) {
+ pb_debug("Using '%s' for btrfs root path\n", path);
+ return path;
+ }
+
+ talloc_free(path);
+ return dev->mount_path;
+}
+
static bool check_existing_mount(struct discover_device *dev)
{
struct stat devstat, mntstat;
@@ -1326,6 +1348,7 @@ static bool check_existing_mount(struct discover_device *dev)
if (mntstat.st_rdev == devstat.st_rdev) {
dev->mount_path = talloc_strdup(dev, mnt->mnt_dir);
+ dev->root_path = check_subvols(dev);
dev->mounted_rw = !!hasmntopt(mnt, "rw");
dev->mounted = true;
dev->unmount = false;
@@ -1388,6 +1411,7 @@ static int mount_device(struct discover_device *dev)
dev->mounted = true;
dev->mounted_rw = false;
dev->unmount = true;
+ dev->root_path = check_subvols(dev);
return 0;
}
@@ -1426,6 +1450,7 @@ static int umount_device(struct discover_device *dev)
talloc_free(dev->mount_path);
dev->mount_path = NULL;
+ dev->root_path = NULL;
return 0;
}
OpenPOWER on IntegriCloud