[PATCH] discover: Handle BTRFS root subvolumes

Cyril Bur cyril.bur at au1.ibm.com
Fri Jan 8 10:39:06 AEDT 2016


On Tue,  5 Jan 2016 16:47:01 +1100
Sam Mendoza-Jonas <sam at mendozajonas.com> wrote:

> 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. '@').
> 

I'm going to gloss over the total awkwardness of the whole process and $reasons
and such and say that since petitboot will struggle with newer ubuntu then...
on balance this kinda has to go in...

> [0] In particular, Ubuntu from at least 14.04
> 
> Signed-off-by: Sam Mendoza-Jonas <sam at mendozajonas.com>

Reviewed-by: Cyril Bur <cyrilbur at gmail.com>

> ---
>  discover/device-handler.c | 25 +++++++++++++++++++++++++
>  discover/device-handler.h |  1 +
>  discover/parser.c         |  2 +-
>  3 files changed, 27 insertions(+), 1 deletion(-)
> 
> 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,



More information about the Petitboot mailing list