diff --git a/drivers/block/loop.c b/drivers/block/loop.c index a42c49e04954b..2926cb9ff9ad6 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1247,6 +1247,8 @@ 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_request = false; + bool drop_cache = false; err = mutex_lock_killable(&loop_ctl_mutex); if (err) @@ -1266,14 +1268,21 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) goto out_unlock; } + if (lo->lo_offset != info->lo_offset) + drop_request = true; 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_cache = true; - /* I/O need to be drained during transfer transition */ - blk_mq_freeze_queue(lo->lo_queue); + sync_blockdev(lo->lo_device); + + if (drop_request) { + blk_set_queue_dying(lo->lo_queue); + blk_mq_freeze_queue_wait(lo->lo_queue); + } else { + /* I/O need to be drained during transfer transition */ + blk_mq_freeze_queue(lo->lo_queue); + } err = loop_release_xfer(lo); if (err) @@ -1300,14 +1309,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; @@ -1344,6 +1345,8 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) out_unfreeze: blk_mq_unfreeze_queue(lo->lo_queue); + if (drop_request) + blk_queue_flag_clear(QUEUE_FLAG_DYING, lo->lo_queue); if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) && !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { @@ -1352,6 +1355,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_cache) { + sync_blockdev(lo->lo_device); + invalidate_bdev(lo->lo_device); + } out_unlock: mutex_unlock(&loop_ctl_mutex); if (partscan) @@ -1533,8 +1542,6 @@ 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) { - int err = 0; - if (lo->lo_state != Lo_bound) return -ENXIO; @@ -1545,27 +1552,18 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg) return 0; sync_blockdev(lo->lo_device); - kill_bdev(lo->lo_device); - blk_mq_freeze_queue(lo->lo_queue); - /* 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; - } - 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); - return err; + /* truncate stale pages cached by previous operations */ + sync_blockdev(lo->lo_device); + invalidate_bdev(lo->lo_device); + return 0; } static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd, diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 48a622b95b76e..9229e4715f376 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3437,6 +3437,9 @@ static int f2fs_write_end(struct file *file, /* overwrite compressed file */ if (f2fs_compressed_file(inode) && fsdata) { f2fs_compress_write_end(inode, fsdata, page->index, copied); + if (pos + copied > i_size_read(inode) && + !f2fs_verity_in_progress(inode)) + f2fs_i_size_write(inode, pos + copied); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); return copied; } diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 5b95d5a146eb6..0e8ed3db84429 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -50,6 +50,12 @@ static int gc_thread_func(void *data) if (kthread_should_stop()) break; + if (unlikely(is_sbi_flag_set(sbi, SBI_NEED_FSCK) || + f2fs_cp_error(sbi))) { + increase_sleep_time(gc_th, &wait_ms); + continue; + } + if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) { increase_sleep_time(gc_th, &wait_ms); stat_other_skip_bggc_count(sbi); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 1c48ec866b8cd..29ee941beb481 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -1062,6 +1062,10 @@ static void __check_sit_bitmap(struct f2fs_sb_info *sbi, size = max_blocks; map = (unsigned long *)(sentry->cur_valid_map); offset = __find_rev_next_bit(map, size, offset); + + if (unlikely(f2fs_cp_error(sbi))) + break; + f2fs_bug_on(sbi, offset != size); blk = START_BLOCK(sbi, segno + 1); } @@ -1131,7 +1135,8 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, if (dc->state != D_PREP) return 0; - if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) + if (unlikely(is_sbi_flag_set(sbi, SBI_NEED_FSCK) || + f2fs_cp_error(sbi))) return 0; trace_f2fs_issue_discard(bdev, dc->start, dc->len); @@ -1733,7 +1738,8 @@ static int issue_discard_thread(void *data) continue; if (kthread_should_stop()) return 0; - if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) { + if (unlikely(is_sbi_flag_set(sbi, SBI_NEED_FSCK) || + f2fs_cp_error(sbi))) { wait_ms = dpolicy.max_interval; continue; }