summaryrefslogtreecommitdiffstats
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
parent01e104dfb79a09bc28f8c5fb65bfe44596c25161 (diff)
downloadtalos-petitboot-d9fc4558e66c32834f2a4fdab31010b40f0a88de.tar.gz
talos-petitboot-d9fc4558e66c32834f2a4fdab31010b40f0a88de.zip
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>
-rw-r--r--discover/device-handler.c25
-rw-r--r--discover/device-handler.h1
-rw-r--r--discover/parser.c2
3 files changed, 27 insertions, 1 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;
}
diff --git a/discover/device-handler.h b/discover/device-handler.h
index e5501ec..12f5ce0 100644
--- a/discover/device-handler.h
+++ b/discover/device-handler.h
@@ -25,6 +25,7 @@ struct discover_device {
const char *label;
char *mount_path;
+ char *root_path;
const char *device_path;
struct ramdisk_device *ramdisk;
bool mounted;
diff --git a/discover/parser.c b/discover/parser.c
index 8e767c6..fbf31b2 100644
--- a/discover/parser.c
+++ b/discover/parser.c
@@ -25,7 +25,7 @@ static char *local_path(struct discover_context *ctx,
struct discover_device *dev,
const char *filename)
{
- return join_paths(ctx, dev->mount_path, filename);
+ return join_paths(ctx, dev->root_path, filename);
}
int parser_request_file(struct discover_context *ctx,
OpenPOWER on IntegriCloud