diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-10-29 17:37:22 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-11-04 20:34:14 -0500 |
commit | 6a8f8ca582a1bafe6b620e000316206c8719f1d0 (patch) | |
tree | c66b23b131af9dceb04004d8851cbcbb17467bba /fs/f2fs | |
parent | adf4983bde9c07c074be12eadb040a88479aa421 (diff) |
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: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/checkpoint.c | 3 | ||||
-rw-r--r-- | fs/f2fs/data.c | 35 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 1 |
3 files changed, 10 insertions, 29 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index ca514d599b79..dd6a357a59de 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -978,6 +978,9 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) | |||
978 | /* Here, we only have one bio having CP pack */ | 978 | /* Here, we only have one bio having CP pack */ |
979 | sync_meta_pages(sbi, META_FLUSH, LONG_MAX); | 979 | sync_meta_pages(sbi, META_FLUSH, LONG_MAX); |
980 | 980 | ||
981 | /* wait for previous submitted meta pages writeback */ | ||
982 | wait_on_all_pages_writeback(sbi); | ||
983 | |||
981 | release_dirty_inode(sbi); | 984 | release_dirty_inode(sbi); |
982 | 985 | ||
983 | if (unlikely(f2fs_cp_error(sbi))) | 986 | if (unlikely(f2fs_cp_error(sbi))) |
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index ceee1a69c5aa..8f164432408e 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -61,11 +61,6 @@ static void f2fs_write_end_io(struct bio *bio, int err) | |||
61 | dec_page_count(sbi, F2FS_WRITEBACK); | 61 | dec_page_count(sbi, F2FS_WRITEBACK); |
62 | } | 62 | } |
63 | 63 | ||
64 | if (sbi->wait_io) { | ||
65 | complete(sbi->wait_io); | ||
66 | sbi->wait_io = NULL; | ||
67 | } | ||
68 | |||
69 | if (!get_pages(sbi, F2FS_WRITEBACK) && | 64 | if (!get_pages(sbi, F2FS_WRITEBACK) && |
70 | !list_empty(&sbi->cp_wait.task_list)) | 65 | !list_empty(&sbi->cp_wait.task_list)) |
71 | wake_up(&sbi->cp_wait); | 66 | wake_up(&sbi->cp_wait); |
@@ -95,34 +90,18 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr, | |||
95 | static void __submit_merged_bio(struct f2fs_bio_info *io) | 90 | static void __submit_merged_bio(struct f2fs_bio_info *io) |
96 | { | 91 | { |
97 | struct f2fs_io_info *fio = &io->fio; | 92 | struct f2fs_io_info *fio = &io->fio; |
98 | int rw; | ||
99 | 93 | ||
100 | if (!io->bio) | 94 | if (!io->bio) |
101 | return; | 95 | return; |
102 | 96 | ||
103 | rw = fio->rw; | 97 | if (is_read_io(fio->rw)) |
104 | 98 | trace_f2fs_submit_read_bio(io->sbi->sb, fio->rw, | |
105 | if (is_read_io(rw)) { | 99 | fio->type, io->bio); |
106 | trace_f2fs_submit_read_bio(io->sbi->sb, rw, | 100 | else |
107 | fio->type, io->bio); | 101 | trace_f2fs_submit_write_bio(io->sbi->sb, fio->rw, |
108 | submit_bio(rw, io->bio); | 102 | fio->type, io->bio); |
109 | } else { | ||
110 | trace_f2fs_submit_write_bio(io->sbi->sb, rw, | ||
111 | fio->type, io->bio); | ||
112 | /* | ||
113 | * META_FLUSH is only from the checkpoint procedure, and we | ||
114 | * should wait this metadata bio for FS consistency. | ||
115 | */ | ||
116 | if (fio->type == META_FLUSH) { | ||
117 | DECLARE_COMPLETION_ONSTACK(wait); | ||
118 | io->sbi->wait_io = &wait; | ||
119 | submit_bio(rw, io->bio); | ||
120 | wait_for_completion(&wait); | ||
121 | } else { | ||
122 | submit_bio(rw, io->bio); | ||
123 | } | ||
124 | } | ||
125 | 103 | ||
104 | submit_bio(fio->rw, io->bio); | ||
126 | io->bio = NULL; | 105 | io->bio = NULL; |
127 | } | 106 | } |
128 | 107 | ||
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index afe3022ffac5..5a9705842f10 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -516,7 +516,6 @@ struct f2fs_sb_info { | |||
516 | /* for bio operations */ | 516 | /* for bio operations */ |
517 | struct f2fs_bio_info read_io; /* for read bios */ | 517 | struct f2fs_bio_info read_io; /* for read bios */ |
518 | struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */ | 518 | struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */ |
519 | struct completion *wait_io; /* for completion bios */ | ||
520 | 519 | ||
521 | /* for checkpoint */ | 520 | /* for checkpoint */ |
522 | struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */ | 521 | struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */ |