Skip to content

Commit 0c3796c

Browse files
Martijn Coenenaxboe
authored andcommitted
loop: Factor out configuring loop from status
Factor out this code into a separate function, so it can be reused by other code more easily. Signed-off-by: Martijn Coenen <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 0a6ed1b commit 0c3796c

File tree

1 file changed

+67
-50
lines changed

1 file changed

+67
-50
lines changed

drivers/block/loop.c

Lines changed: 67 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,75 +1251,43 @@ static int loop_clr_fd(struct loop_device *lo)
12511251
return __loop_clr_fd(lo, false);
12521252
}
12531253

1254+
/**
1255+
* loop_set_status_from_info - configure device from loop_info
1256+
* @lo: struct loop_device to configure
1257+
* @info: struct loop_info64 to configure the device with
1258+
*
1259+
* Configures the loop device parameters according to the passed
1260+
* in loop_info64 configuration.
1261+
*/
12541262
static int
1255-
loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
1263+
loop_set_status_from_info(struct loop_device *lo,
1264+
const struct loop_info64 *info)
12561265
{
12571266
int err;
12581267
struct loop_func_table *xfer;
12591268
kuid_t uid = current_uid();
1260-
struct block_device *bdev;
1261-
bool partscan = false;
1262-
bool size_changed = false;
1263-
1264-
err = mutex_lock_killable(&loop_ctl_mutex);
1265-
if (err)
1266-
return err;
1267-
if (lo->lo_encrypt_key_size &&
1268-
!uid_eq(lo->lo_key_owner, uid) &&
1269-
!capable(CAP_SYS_ADMIN)) {
1270-
err = -EPERM;
1271-
goto out_unlock;
1272-
}
1273-
if (lo->lo_state != Lo_bound) {
1274-
err = -ENXIO;
1275-
goto out_unlock;
1276-
}
1277-
if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) {
1278-
err = -EINVAL;
1279-
goto out_unlock;
1280-
}
1281-
1282-
if (lo->lo_offset != info->lo_offset ||
1283-
lo->lo_sizelimit != info->lo_sizelimit) {
1284-
size_changed = true;
1285-
sync_blockdev(lo->lo_device);
1286-
kill_bdev(lo->lo_device);
1287-
}
12881269

1289-
/* I/O need to be drained during transfer transition */
1290-
blk_mq_freeze_queue(lo->lo_queue);
1291-
1292-
if (size_changed && lo->lo_device->bd_inode->i_mapping->nrpages) {
1293-
/* If any pages were dirtied after kill_bdev(), try again */
1294-
err = -EAGAIN;
1295-
pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
1296-
__func__, lo->lo_number, lo->lo_file_name,
1297-
lo->lo_device->bd_inode->i_mapping->nrpages);
1298-
goto out_unfreeze;
1299-
}
1270+
if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE)
1271+
return -EINVAL;
13001272

13011273
err = loop_release_xfer(lo);
13021274
if (err)
1303-
goto out_unfreeze;
1275+
return err;
13041276

13051277
if (info->lo_encrypt_type) {
13061278
unsigned int type = info->lo_encrypt_type;
13071279

1308-
if (type >= MAX_LO_CRYPT) {
1309-
err = -EINVAL;
1310-
goto out_unfreeze;
1311-
}
1280+
if (type >= MAX_LO_CRYPT)
1281+
return -EINVAL;
13121282
xfer = xfer_funcs[type];
1313-
if (xfer == NULL) {
1314-
err = -EINVAL;
1315-
goto out_unfreeze;
1316-
}
1283+
if (xfer == NULL)
1284+
return -EINVAL;
13171285
} else
13181286
xfer = NULL;
13191287

13201288
err = loop_init_xfer(lo, xfer, info);
13211289
if (err)
1322-
goto out_unfreeze;
1290+
return err;
13231291

13241292
lo->lo_offset = info->lo_offset;
13251293
lo->lo_sizelimit = info->lo_sizelimit;
@@ -1346,6 +1314,55 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
13461314
lo->lo_key_owner = uid;
13471315
}
13481316

1317+
return 0;
1318+
}
1319+
1320+
static int
1321+
loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
1322+
{
1323+
int err;
1324+
struct block_device *bdev;
1325+
kuid_t uid = current_uid();
1326+
bool partscan = false;
1327+
bool size_changed = false;
1328+
1329+
err = mutex_lock_killable(&loop_ctl_mutex);
1330+
if (err)
1331+
return err;
1332+
if (lo->lo_encrypt_key_size &&
1333+
!uid_eq(lo->lo_key_owner, uid) &&
1334+
!capable(CAP_SYS_ADMIN)) {
1335+
err = -EPERM;
1336+
goto out_unlock;
1337+
}
1338+
if (lo->lo_state != Lo_bound) {
1339+
err = -ENXIO;
1340+
goto out_unlock;
1341+
}
1342+
1343+
if (lo->lo_offset != info->lo_offset ||
1344+
lo->lo_sizelimit != info->lo_sizelimit) {
1345+
size_changed = true;
1346+
sync_blockdev(lo->lo_device);
1347+
kill_bdev(lo->lo_device);
1348+
}
1349+
1350+
/* I/O need to be drained during transfer transition */
1351+
blk_mq_freeze_queue(lo->lo_queue);
1352+
1353+
if (size_changed && lo->lo_device->bd_inode->i_mapping->nrpages) {
1354+
/* If any pages were dirtied after kill_bdev(), try again */
1355+
err = -EAGAIN;
1356+
pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
1357+
__func__, lo->lo_number, lo->lo_file_name,
1358+
lo->lo_device->bd_inode->i_mapping->nrpages);
1359+
goto out_unfreeze;
1360+
}
1361+
1362+
err = loop_set_status_from_info(lo, info);
1363+
if (err)
1364+
goto out_unfreeze;
1365+
13491366
if (size_changed) {
13501367
loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit,
13511368
lo->lo_backing_file);

0 commit comments

Comments
 (0)