Skip to content

Commit b0bd158

Browse files
Martijn Coenenaxboe
authored andcommitted
loop: Refactor loop_set_status() size calculation
figure_loop_size() calculates the loop size based on the passed in parameters, but at the same time it updates the offset and sizelimit parameters in the loop device configuration. That is a somewhat unexpected side effect of a function with this name, and it is only only needed by one of the two callers of this function - loop_set_status(). Move the lo_offset and lo_sizelimit assignment back into loop_set_status(), and use the newly factored out functions to validate and apply the newly calculated size. This allows us to get rid of figure_loop_size() in a follow-up commit. Signed-off-by: Martijn Coenen <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 716ad09 commit b0bd158

File tree

1 file changed

+19
-18
lines changed

1 file changed

+19
-18
lines changed

drivers/block/loop.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,6 @@ figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
250250
{
251251
loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);
252252

253-
if (lo->lo_offset != offset)
254-
lo->lo_offset = offset;
255-
if (lo->lo_sizelimit != sizelimit)
256-
lo->lo_sizelimit = sizelimit;
257-
258253
loop_set_size(lo, size);
259254
}
260255

@@ -1272,6 +1267,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
12721267
kuid_t uid = current_uid();
12731268
struct block_device *bdev;
12741269
bool partscan = false;
1270+
bool size_changed = false;
12751271

12761272
err = mutex_lock_killable(&loop_ctl_mutex);
12771273
if (err)
@@ -1293,13 +1289,23 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
12931289

12941290
if (lo->lo_offset != info->lo_offset ||
12951291
lo->lo_sizelimit != info->lo_sizelimit) {
1292+
size_changed = true;
12961293
sync_blockdev(lo->lo_device);
12971294
kill_bdev(lo->lo_device);
12981295
}
12991296

13001297
/* I/O need to be drained during transfer transition */
13011298
blk_mq_freeze_queue(lo->lo_queue);
13021299

1300+
if (size_changed && lo->lo_device->bd_inode->i_mapping->nrpages) {
1301+
/* If any pages were dirtied after kill_bdev(), try again */
1302+
err = -EAGAIN;
1303+
pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
1304+
__func__, lo->lo_number, lo->lo_file_name,
1305+
lo->lo_device->bd_inode->i_mapping->nrpages);
1306+
goto out_unfreeze;
1307+
}
1308+
13031309
err = loop_release_xfer(lo);
13041310
if (err)
13051311
goto out_unfreeze;
@@ -1323,19 +1329,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
13231329
if (err)
13241330
goto out_unfreeze;
13251331

1326-
if (lo->lo_offset != info->lo_offset ||
1327-
lo->lo_sizelimit != info->lo_sizelimit) {
1328-
/* kill_bdev should have truncated all the pages */
1329-
if (lo->lo_device->bd_inode->i_mapping->nrpages) {
1330-
err = -EAGAIN;
1331-
pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
1332-
__func__, lo->lo_number, lo->lo_file_name,
1333-
lo->lo_device->bd_inode->i_mapping->nrpages);
1334-
goto out_unfreeze;
1335-
}
1336-
figure_loop_size(lo, info->lo_offset, info->lo_sizelimit);
1337-
}
1338-
1332+
lo->lo_offset = info->lo_offset;
1333+
lo->lo_sizelimit = info->lo_sizelimit;
13391334
memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
13401335
memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
13411336
lo->lo_file_name[LO_NAME_SIZE-1] = 0;
@@ -1359,6 +1354,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
13591354
lo->lo_key_owner = uid;
13601355
}
13611356

1357+
if (size_changed) {
1358+
loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit,
1359+
lo->lo_backing_file);
1360+
loop_set_size(lo, new_size);
1361+
}
1362+
13621363
loop_config_discard(lo);
13631364

13641365
/* update dio if lo_offset or transfer is changed */

0 commit comments

Comments
 (0)