Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a8f8ca5 authored by Jaegeuk Kim's avatar Jaegeuk Kim
Browse files

f2fs: avoid race condition in handling wait_io



__submit_merged_bio    f2fs_write_end_io        f2fs_write_end_io
                       wait_io = X              wait_io = x
                       complete(X)              complete(X)
                       wait_io = NULL
wait_for_completion()
free(X)
                                                 spin_lock(X)
                                                 kernel panic

In order to avoid this, this patch removes the wait_io facility.
Instead, we can use wait_on_all_pages_writeback(sbi) to wait for end_ios.

Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent adf4983b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -978,6 +978,9 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
	/* Here, we only have one bio having CP pack */
	sync_meta_pages(sbi, META_FLUSH, LONG_MAX);

	/* wait for previous submitted meta pages writeback */
	wait_on_all_pages_writeback(sbi);

	release_dirty_inode(sbi);

	if (unlikely(f2fs_cp_error(sbi)))
+7 −28
Original line number Diff line number Diff line
@@ -61,11 +61,6 @@ static void f2fs_write_end_io(struct bio *bio, int err)
		dec_page_count(sbi, F2FS_WRITEBACK);
	}

	if (sbi->wait_io) {
		complete(sbi->wait_io);
		sbi->wait_io = NULL;
	}

	if (!get_pages(sbi, F2FS_WRITEBACK) &&
			!list_empty(&sbi->cp_wait.task_list))
		wake_up(&sbi->cp_wait);
@@ -95,34 +90,18 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr,
static void __submit_merged_bio(struct f2fs_bio_info *io)
{
	struct f2fs_io_info *fio = &io->fio;
	int rw;

	if (!io->bio)
		return;

	rw = fio->rw;

	if (is_read_io(rw)) {
		trace_f2fs_submit_read_bio(io->sbi->sb, rw,
	if (is_read_io(fio->rw))
		trace_f2fs_submit_read_bio(io->sbi->sb, fio->rw,
							fio->type, io->bio);
		submit_bio(rw, io->bio);
	} else {
		trace_f2fs_submit_write_bio(io->sbi->sb, rw,
	else
		trace_f2fs_submit_write_bio(io->sbi->sb, fio->rw,
							fio->type, io->bio);
		/*
		 * META_FLUSH is only from the checkpoint procedure, and we
		 * should wait this metadata bio for FS consistency.
		 */
		if (fio->type == META_FLUSH) {
			DECLARE_COMPLETION_ONSTACK(wait);
			io->sbi->wait_io = &wait;
			submit_bio(rw, io->bio);
			wait_for_completion(&wait);
		} else {
			submit_bio(rw, io->bio);
		}
	}

	submit_bio(fio->rw, io->bio);
	io->bio = NULL;
}

+0 −1
Original line number Diff line number Diff line
@@ -516,7 +516,6 @@ struct f2fs_sb_info {
	/* for bio operations */
	struct f2fs_bio_info read_io;			/* for read bios */
	struct f2fs_bio_info write_io[NR_PAGE_TYPE];	/* for write bios */
	struct completion *wait_io;		/* for completion bios */

	/* for checkpoint */
	struct f2fs_checkpoint *ckpt;		/* raw checkpoint pointer */