mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
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: Martijn Coenen <maco@android.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
571fae6e29
commit
faf1d25440
@ -1036,9 +1036,7 @@ loop_set_status_from_info(struct loop_device *lo,
|
|||||||
lo->transfer = xfer->transfer;
|
lo->transfer = xfer->transfer;
|
||||||
lo->ioctl = xfer->ioctl;
|
lo->ioctl = xfer->ioctl;
|
||||||
|
|
||||||
if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) !=
|
lo->lo_flags = info->lo_flags;
|
||||||
(info->lo_flags & LO_FLAGS_AUTOCLEAR))
|
|
||||||
lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
|
|
||||||
|
|
||||||
lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
|
lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
|
||||||
lo->lo_init[0] = info->lo_init[0];
|
lo->lo_init[0] = info->lo_init[0];
|
||||||
@ -1323,6 +1321,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
|||||||
int err;
|
int err;
|
||||||
struct block_device *bdev;
|
struct block_device *bdev;
|
||||||
kuid_t uid = current_uid();
|
kuid_t uid = current_uid();
|
||||||
|
int prev_lo_flags;
|
||||||
bool partscan = false;
|
bool partscan = false;
|
||||||
bool size_changed = false;
|
bool size_changed = false;
|
||||||
|
|
||||||
@ -1359,10 +1358,19 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
|||||||
goto out_unfreeze;
|
goto out_unfreeze;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prev_lo_flags = lo->lo_flags;
|
||||||
|
|
||||||
err = loop_set_status_from_info(lo, info);
|
err = loop_set_status_from_info(lo, info);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unfreeze;
|
goto out_unfreeze;
|
||||||
|
|
||||||
|
/* 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) {
|
if (size_changed) {
|
||||||
loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit,
|
loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit,
|
||||||
lo->lo_backing_file);
|
lo->lo_backing_file);
|
||||||
@ -1377,9 +1385,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
|||||||
out_unfreeze:
|
out_unfreeze:
|
||||||
blk_mq_unfreeze_queue(lo->lo_queue);
|
blk_mq_unfreeze_queue(lo->lo_queue);
|
||||||
|
|
||||||
if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) &&
|
if (!err && (lo->lo_flags & LO_FLAGS_PARTSCAN) &&
|
||||||
!(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
|
!(prev_lo_flags & LO_FLAGS_PARTSCAN)) {
|
||||||
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
|
||||||
lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
|
lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
|
||||||
bdev = lo->lo_device;
|
bdev = lo->lo_device;
|
||||||
partscan = true;
|
partscan = true;
|
||||||
|
@ -25,6 +25,12 @@ enum {
|
|||||||
LO_FLAGS_DIRECT_IO = 16,
|
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 <asm/posix_types.h> /* for __kernel_old_dev_t */
|
||||||
#include <linux/types.h> /* for __u64 */
|
#include <linux/types.h> /* for __u64 */
|
||||||
|
|
||||||
@ -37,7 +43,7 @@ struct loop_info {
|
|||||||
int lo_offset;
|
int lo_offset;
|
||||||
int lo_encrypt_type;
|
int lo_encrypt_type;
|
||||||
int lo_encrypt_key_size; /* ioctl w/o */
|
int lo_encrypt_key_size; /* ioctl w/o */
|
||||||
int lo_flags; /* ioctl r/o */
|
int lo_flags;
|
||||||
char lo_name[LO_NAME_SIZE];
|
char lo_name[LO_NAME_SIZE];
|
||||||
unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
|
unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
|
||||||
unsigned long lo_init[2];
|
unsigned long lo_init[2];
|
||||||
@ -53,7 +59,7 @@ struct loop_info64 {
|
|||||||
__u32 lo_number; /* ioctl r/o */
|
__u32 lo_number; /* ioctl r/o */
|
||||||
__u32 lo_encrypt_type;
|
__u32 lo_encrypt_type;
|
||||||
__u32 lo_encrypt_key_size; /* ioctl w/o */
|
__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_file_name[LO_NAME_SIZE];
|
||||||
__u8 lo_crypt_name[LO_NAME_SIZE];
|
__u8 lo_crypt_name[LO_NAME_SIZE];
|
||||||
__u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
|
__u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
|
||||||
|
Loading…
Reference in New Issue
Block a user