Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Martijn Coenen and committed by
Jens Axboe
faf1d254 571fae6e

+21 -8
+13 -6
drivers/block/loop.c
··· 1036 1036 lo->transfer = xfer->transfer; 1037 1037 lo->ioctl = xfer->ioctl; 1038 1038 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; 1042 1040 1043 1041 lo->lo_encrypt_key_size = info->lo_encrypt_key_size; 1044 1042 lo->lo_init[0] = info->lo_init[0]; ··· 1321 1323 int err; 1322 1324 struct block_device *bdev; 1323 1325 kuid_t uid = current_uid(); 1326 + int prev_lo_flags; 1324 1327 bool partscan = false; 1325 1328 bool size_changed = false; 1326 1329 ··· 1358 1359 goto out_unfreeze; 1359 1360 } 1360 1361 1362 + prev_lo_flags = lo->lo_flags; 1363 + 1361 1364 err = loop_set_status_from_info(lo, info); 1362 1365 if (err) 1363 1366 goto out_unfreeze; 1367 + 1368 + /* Mask out flags that can't be set using LOOP_SET_STATUS. */ 1369 + lo->lo_flags &= ~LOOP_SET_STATUS_SETTABLE_FLAGS; 1370 + /* For those flags, use the previous values instead */ 1371 + lo->lo_flags |= prev_lo_flags & ~LOOP_SET_STATUS_SETTABLE_FLAGS; 1372 + /* For flags that can't be cleared, use previous values too */ 1373 + lo->lo_flags |= prev_lo_flags & ~LOOP_SET_STATUS_CLEARABLE_FLAGS; 1364 1374 1365 1375 if (size_changed) { 1366 1376 loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit, ··· 1385 1377 out_unfreeze: 1386 1378 blk_mq_unfreeze_queue(lo->lo_queue); 1387 1379 1388 - if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) && 1389 - !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { 1390 - lo->lo_flags |= LO_FLAGS_PARTSCAN; 1380 + if (!err && (lo->lo_flags & LO_FLAGS_PARTSCAN) && 1381 + !(prev_lo_flags & LO_FLAGS_PARTSCAN)) { 1391 1382 lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; 1392 1383 bdev = lo->lo_device; 1393 1384 partscan = true;
+8 -2
include/uapi/linux/loop.h
··· 25 25 LO_FLAGS_DIRECT_IO = 16, 26 26 }; 27 27 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 + 28 34 #include <asm/posix_types.h> /* for __kernel_old_dev_t */ 29 35 #include <linux/types.h> /* for __u64 */ 30 36 ··· 43 37 int lo_offset; 44 38 int lo_encrypt_type; 45 39 int lo_encrypt_key_size; /* ioctl w/o */ 46 - int lo_flags; /* ioctl r/o */ 40 + int lo_flags; 47 41 char lo_name[LO_NAME_SIZE]; 48 42 unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ 49 43 unsigned long lo_init[2]; ··· 59 53 __u32 lo_number; /* ioctl r/o */ 60 54 __u32 lo_encrypt_type; 61 55 __u32 lo_encrypt_key_size; /* ioctl w/o */ 62 - __u32 lo_flags; /* ioctl r/o */ 56 + __u32 lo_flags; 63 57 __u8 lo_file_name[LO_NAME_SIZE]; 64 58 __u8 lo_crypt_name[LO_NAME_SIZE]; 65 59 __u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */