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>
return dev->ramdisk ? dev->ramdisk->snapshot : dev->device_path;
}
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;
static bool check_existing_mount(struct discover_device *dev)
{
struct stat devstat, mntstat;
if (mntstat.st_rdev == devstat.st_rdev) {
dev->mount_path = talloc_strdup(dev, mnt->mnt_dir);
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;
dev->mounted_rw = !!hasmntopt(mnt, "rw");
dev->mounted = true;
dev->unmount = false;
dev->mounted = true;
dev->mounted_rw = false;
dev->unmount = true;
dev->mounted = true;
dev->mounted_rw = false;
dev->unmount = true;
+ dev->root_path = check_subvols(dev);
talloc_free(dev->mount_path);
dev->mount_path = NULL;
talloc_free(dev->mount_path);
dev->mount_path = NULL;
const char *label;
char *mount_path;
const char *label;
char *mount_path;
const char *device_path;
struct ramdisk_device *ramdisk;
bool mounted;
const char *device_path;
struct ramdisk_device *ramdisk;
bool mounted;
struct discover_device *dev,
const char *filename)
{
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,
}
int parser_request_file(struct discover_context *ctx,