aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2014-10-29 17:37:22 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2014-11-04 20:34:14 -0500
commit6a8f8ca582a1bafe6b620e000316206c8719f1d0 (patch)
treec66b23b131af9dceb04004d8851cbcbb17467bba /fs/f2fs
parentadf4983bde9c07c074be12eadb040a88479aa421 (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.c3
-rw-r--r--fs/f2fs/data.c35
-rw-r--r--fs/f2fs/f2fs.h1
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,
95static void __submit_merged_bio(struct f2fs_bio_info *io) 90static 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 */