Re: [f2fs-dev] [PATCH v2] loop: avoid EAGAIN, if offset or block_size are changed

From: Jaegeuk Kim
Date: Mon Jun 17 2019 - 17:14:12 EST


Jens,

Any chance to get a review for this?

(Added Tested-by:)

On 05/17, Jaegeuk Kim wrote:
> This patch tries to avoid EAGAIN due to nrpages!=0 that was originally trying
> to drop stale pages resulting in wrong data access.
>
> Report: https://bugs.chromium.org/p/chromium/issues/detail?id=938958#c38
>
> Cc: <stable@xxxxxxxxxxxxxxx>
> Cc: Jens Axboe <axboe@xxxxxxxxx>
> Cc: linux-block@xxxxxxxxxxxxxxx
> Cc: Bart Van Assche <bvanassche@xxxxxxx>
> Fixes: 5db470e229e2 ("loop: drop caches if offset or block_size are changed")
> Reported-by: Gwendal Grignou <gwendal@xxxxxxxxxxxx>
> Reported-by: grygorii tertychnyi <gtertych@xxxxxxxxx>

Tested-by: Francesco Ruggeri <fruggeri@xxxxxxxxxx>

> Signed-off-by: Jaegeuk Kim <jaegeuk@xxxxxxxxxx>
> ---
> v2 from v1:
> - remove obsolete jump
>
> drivers/block/loop.c | 45 +++++++++++++++++---------------------------
> 1 file changed, 17 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> index 102d79575895..42994de2dd12 100644
> --- a/drivers/block/loop.c
> +++ b/drivers/block/loop.c
> @@ -1212,6 +1212,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
> kuid_t uid = current_uid();
> struct block_device *bdev;
> bool partscan = false;
> + bool drop_caches = false;
>
> err = mutex_lock_killable(&loop_ctl_mutex);
> if (err)
> @@ -1232,10 +1233,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
> }
>
> if (lo->lo_offset != info->lo_offset ||
> - lo->lo_sizelimit != info->lo_sizelimit) {
> - sync_blockdev(lo->lo_device);
> - kill_bdev(lo->lo_device);
> - }
> + lo->lo_sizelimit != info->lo_sizelimit)
> + drop_caches = true;
>
> /* I/O need to be drained during transfer transition */
> blk_mq_freeze_queue(lo->lo_queue);
> @@ -1265,14 +1264,6 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
>
> if (lo->lo_offset != info->lo_offset ||
> lo->lo_sizelimit != info->lo_sizelimit) {
> - /* kill_bdev should have truncated all the pages */
> - if (lo->lo_device->bd_inode->i_mapping->nrpages) {
> - err = -EAGAIN;
> - pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
> - __func__, lo->lo_number, lo->lo_file_name,
> - lo->lo_device->bd_inode->i_mapping->nrpages);
> - goto out_unfreeze;
> - }
> if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
> err = -EFBIG;
> goto out_unfreeze;
> @@ -1317,6 +1308,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
> bdev = lo->lo_device;
> partscan = true;
> }
> +
> + /* truncate stale pages cached by previous operations */
> + if (!err && drop_caches) {
> + sync_blockdev(lo->lo_device);
> + kill_bdev(lo->lo_device);
> + }
> out_unlock:
> mutex_unlock(&loop_ctl_mutex);
> if (partscan)
> @@ -1498,6 +1495,7 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg)
>
> static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
> {
> + bool drop_caches = false;
> int err = 0;
>
> if (lo->lo_state != Lo_bound)
> @@ -1506,30 +1504,21 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
> if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg))
> return -EINVAL;
>
> - if (lo->lo_queue->limits.logical_block_size != arg) {
> - sync_blockdev(lo->lo_device);
> - kill_bdev(lo->lo_device);
> - }
> + if (lo->lo_queue->limits.logical_block_size != arg)
> + drop_caches = true;
>
> blk_mq_freeze_queue(lo->lo_queue);
> -
> - /* kill_bdev should have truncated all the pages */
> - if (lo->lo_queue->limits.logical_block_size != arg &&
> - lo->lo_device->bd_inode->i_mapping->nrpages) {
> - err = -EAGAIN;
> - pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
> - __func__, lo->lo_number, lo->lo_file_name,
> - lo->lo_device->bd_inode->i_mapping->nrpages);
> - goto out_unfreeze;
> - }
> -
> blk_queue_logical_block_size(lo->lo_queue, arg);
> blk_queue_physical_block_size(lo->lo_queue, arg);
> blk_queue_io_min(lo->lo_queue, arg);
> loop_update_dio(lo);
> -out_unfreeze:
> blk_mq_unfreeze_queue(lo->lo_queue);
>
> + /* truncate stale pages cached by previous operations */
> + if (drop_caches) {
> + sync_blockdev(lo->lo_device);
> + kill_bdev(lo->lo_device);
> + }
> return err;
> }
>
> --
> 2.19.0.605.g01d371f741-goog
>
>
>
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@xxxxxxxxxxxxxxxxxxxxx
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel