Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e515bc15 authored by Martijn Coenen's avatar Martijn Coenen
Browse files

BACKPORT: loop: Clean up LOOP_SET_STATUS lo_flags handling



LOOP_SET_STATUS(64) will actually allow some lo_flags to be modified; in
particular, LO_FLAGS_AUTOCLEAR can be set and cleared, whereas
LO_FLAGS_PARTSCAN can be set to request a partition scan. Make this
explicit by updating the UAPI to include the flags that can be
set/cleared using this ioctl.

The implementation can then blindly take over the passed in flags,
and use the previous flags for those flags that can't be set / cleared
using LOOP_SET_STATUS.

Signed-off-by: default avatarMartijn Coenen <maco@android.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Bug: 148607611
(cherry picked from commit faf1d25440d6ad06d509dada4b6fe62fea844370)
Change-Id: I88487db28e785ee83e400904b685ef9e98c0287d
parent 77a5e7c3
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -970,9 +970,7 @@ loop_set_status_from_info(struct loop_device *lo,
	lo->transfer = xfer->transfer;
	lo->ioctl = xfer->ioctl;

	if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) !=
	     (info->lo_flags & LO_FLAGS_AUTOCLEAR))
		lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
	lo->lo_flags = info->lo_flags;

	lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
	lo->lo_init[0] = info->lo_init[0];
@@ -1168,6 +1166,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
{
	int err;
	kuid_t uid = current_uid();
	int prev_lo_flags;
	bool size_changed = false;

	if (lo->lo_encrypt_key_size &&
@@ -1197,10 +1196,18 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
		goto exit;
	}

	prev_lo_flags = lo->lo_flags;

	err = loop_set_status_from_info(lo, info);
	if (err)
		goto exit;

	/* Mask out flags that can't be set using LOOP_SET_STATUS. */
	lo->lo_flags &= ~LOOP_SET_STATUS_SETTABLE_FLAGS;
	/* For those flags, use the previous values instead */
	lo->lo_flags |= prev_lo_flags & ~LOOP_SET_STATUS_SETTABLE_FLAGS;
	/* For flags that can't be cleared, use previous values too */
	lo->lo_flags |= prev_lo_flags & ~LOOP_SET_STATUS_CLEARABLE_FLAGS;
	if (size_changed) {
		loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit,
					   lo->lo_backing_file);
@@ -1215,9 +1222,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 exit:
	blk_mq_unfreeze_queue(lo->lo_queue);

	if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) &&
	     !(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
		lo->lo_flags |= LO_FLAGS_PARTSCAN;
	if (!err && (lo->lo_flags & LO_FLAGS_PARTSCAN) &&
	     !(prev_lo_flags & LO_FLAGS_PARTSCAN)) {
		lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
		loop_reread_partitions(lo, lo->lo_device);
	}
+8 −2
Original line number Diff line number Diff line
@@ -24,6 +24,12 @@ enum {
	LO_FLAGS_DIRECT_IO	= 16,
};

/* LO_FLAGS that can be set using LOOP_SET_STATUS(64) */
#define LOOP_SET_STATUS_SETTABLE_FLAGS (LO_FLAGS_AUTOCLEAR | LO_FLAGS_PARTSCAN)

/* LO_FLAGS that can be cleared using LOOP_SET_STATUS(64) */
#define LOOP_SET_STATUS_CLEARABLE_FLAGS (LO_FLAGS_AUTOCLEAR)

#include <asm/posix_types.h>	/* for __kernel_old_dev_t */
#include <linux/types.h>	/* for __u64 */

@@ -36,7 +42,7 @@ struct loop_info {
	int		   lo_offset;
	int		   lo_encrypt_type;
	int		   lo_encrypt_key_size; 	/* ioctl w/o */
	int		   lo_flags;			/* ioctl r/o */
	int		   lo_flags;
	char		   lo_name[LO_NAME_SIZE];
	unsigned char	   lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
	unsigned long	   lo_init[2];
@@ -52,7 +58,7 @@ struct loop_info64 {
	__u32		   lo_number;			/* ioctl r/o */
	__u32		   lo_encrypt_type;
	__u32		   lo_encrypt_key_size;		/* ioctl w/o */
	__u32		   lo_flags;			/* ioctl r/o */
	__u32		   lo_flags;
	__u8		   lo_file_name[LO_NAME_SIZE];
	__u8		   lo_crypt_name[LO_NAME_SIZE];
	__u8		   lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */