Skip to content

Commit faf1d25

Browse files
Martijn Coenenaxboe
authored andcommitted
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 <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 571fae6 commit faf1d25

File tree

2 files changed

+21
-8
lines changed

2 files changed

+21
-8
lines changed

drivers/block/loop.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,9 +1036,7 @@ loop_set_status_from_info(struct loop_device *lo,
10361036
lo->transfer = xfer->transfer;
10371037
lo->ioctl = xfer->ioctl;
10381038

1039-
if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) !=
1040-
(info->lo_flags & LO_FLAGS_AUTOCLEAR))
1041-
lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
1039+
lo->lo_flags = info->lo_flags;
10421040

10431041
lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
10441042
lo->lo_init[0] = info->lo_init[0];
@@ -1323,6 +1321,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
13231321
int err;
13241322
struct block_device *bdev;
13251323
kuid_t uid = current_uid();
1324+
int prev_lo_flags;
13261325
bool partscan = false;
13271326
bool size_changed = false;
13281327

@@ -1359,10 +1358,19 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
13591358
goto out_unfreeze;
13601359
}
13611360

1361+
prev_lo_flags = lo->lo_flags;
1362+
13621363
err = loop_set_status_from_info(lo, info);
13631364
if (err)
13641365
goto out_unfreeze;
13651366

1367+
/* Mask out flags that can't be set using LOOP_SET_STATUS. */
1368+
lo->lo_flags &= ~LOOP_SET_STATUS_SETTABLE_FLAGS;
1369+
/* For those flags, use the previous values instead */
1370+
lo->lo_flags |= prev_lo_flags & ~LOOP_SET_STATUS_SETTABLE_FLAGS;
1371+
/* For flags that can't be cleared, use previous values too */
1372+
lo->lo_flags |= prev_lo_flags & ~LOOP_SET_STATUS_CLEARABLE_FLAGS;
1373+
13661374
if (size_changed) {
13671375
loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit,
13681376
lo->lo_backing_file);
@@ -1377,9 +1385,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
13771385
out_unfreeze:
13781386
blk_mq_unfreeze_queue(lo->lo_queue);
13791387

1380-
if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) &&
1381-
!(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
1382-
lo->lo_flags |= LO_FLAGS_PARTSCAN;
1388+
if (!err && (lo->lo_flags & LO_FLAGS_PARTSCAN) &&
1389+
!(prev_lo_flags & LO_FLAGS_PARTSCAN)) {
13831390
lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
13841391
bdev = lo->lo_device;
13851392
partscan = true;

include/uapi/linux/loop.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ enum {
2525
LO_FLAGS_DIRECT_IO = 16,
2626
};
2727

28+
/* LO_FLAGS that can be set using LOOP_SET_STATUS(64) */
29+
#define LOOP_SET_STATUS_SETTABLE_FLAGS (LO_FLAGS_AUTOCLEAR | LO_FLAGS_PARTSCAN)
30+
31+
/* LO_FLAGS that can be cleared using LOOP_SET_STATUS(64) */
32+
#define LOOP_SET_STATUS_CLEARABLE_FLAGS (LO_FLAGS_AUTOCLEAR)
33+
2834
#include <asm/posix_types.h> /* for __kernel_old_dev_t */
2935
#include <linux/types.h> /* for __u64 */
3036

@@ -37,7 +43,7 @@ struct loop_info {
3743
int lo_offset;
3844
int lo_encrypt_type;
3945
int lo_encrypt_key_size; /* ioctl w/o */
40-
int lo_flags; /* ioctl r/o */
46+
int lo_flags;
4147
char lo_name[LO_NAME_SIZE];
4248
unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
4349
unsigned long lo_init[2];
@@ -53,7 +59,7 @@ struct loop_info64 {
5359
__u32 lo_number; /* ioctl r/o */
5460
__u32 lo_encrypt_type;
5561
__u32 lo_encrypt_key_size; /* ioctl w/o */
56-
__u32 lo_flags; /* ioctl r/o */
62+
__u32 lo_flags;
5763
__u8 lo_file_name[LO_NAME_SIZE];
5864
__u8 lo_crypt_name[LO_NAME_SIZE];
5965
__u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */

0 commit comments

Comments
 (0)