f2fs: avoid race condition in handling wait_io
authorJaegeuk Kim <jaegeuk@kernel.org>
Wed, 29 Oct 2014 21:37:22 +0000 (14:37 -0700)
committerJaegeuk Kim <jaegeuk@kernel.org>
Wed, 5 Nov 2014 01:34:14 +0000 (17:34 -0800)
__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: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/f2fs.h

index ca514d599b79a66b4fdf3aa3dda855d214a2f261..dd6a357a59de56014067ee46f7d5931e0510d044 100644 (file)
@@ -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)))
index ceee1a69c5aa62217b15ceddc23028ab633db484..8f164432408e1a5663d7896df9a2584488348819 100644 (file)
@@ -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,
-                                               fio->type, io->bio);
-               submit_bio(rw, io->bio);
-       } else {
-               trace_f2fs_submit_write_bio(io->sbi->sb, 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);
-               }
-       }
+       if (is_read_io(fio->rw))
+               trace_f2fs_submit_read_bio(io->sbi->sb, fio->rw,
+                                                       fio->type, io->bio);
+       else
+               trace_f2fs_submit_write_bio(io->sbi->sb, fio->rw,
+                                                       fio->type, io->bio);
 
+       submit_bio(fio->rw, io->bio);
        io->bio = NULL;
 }
 
index afe3022ffac5835d4f93884c07eef237793d2cb0..5a9705842f10a24a21f8f87a10af633f465977ed 100644 (file)
@@ -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 */