diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-01-23 19:42:16 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-02-17 00:58:51 -0500 |
commit | 744602cf45ce35758b8637f76bc263c871abc6ea (patch) | |
tree | ad269d5514188d9ca87b7906bae3c863a8b46d3b /fs/f2fs | |
parent | 6d0abeca3242a88cab8232e4acd7e2bf088f3bc2 (diff) |
f2fs: update_inode_page should be done all the time
In order to make fs consistency, update_inode_page should not be failed all
the time. Otherwise, it is possible to lose some metadata in the inode like
a link count.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/data.c | 3 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 8 | ||||
-rw-r--r-- | fs/f2fs/inode.c | 23 |
3 files changed, 22 insertions, 12 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 2261ccdd0b5f..20c3c648e56d 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -55,8 +55,7 @@ static void f2fs_write_end_io(struct bio *bio, int err) | |||
55 | if (unlikely(err)) { | 55 | if (unlikely(err)) { |
56 | SetPageError(page); | 56 | SetPageError(page); |
57 | set_bit(AS_EIO, &page->mapping->flags); | 57 | set_bit(AS_EIO, &page->mapping->flags); |
58 | set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG); | 58 | f2fs_stop_checkpoint(sbi); |
59 | sbi->sb->s_flags |= MS_RDONLY; | ||
60 | } | 59 | } |
61 | end_page_writeback(page); | 60 | end_page_writeback(page); |
62 | dec_page_count(sbi, F2FS_WRITEBACK); | 61 | dec_page_count(sbi, F2FS_WRITEBACK); |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index fc3c558cb4f3..0f0ad3aa148a 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -1023,6 +1023,12 @@ static inline int f2fs_readonly(struct super_block *sb) | |||
1023 | return sb->s_flags & MS_RDONLY; | 1023 | return sb->s_flags & MS_RDONLY; |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi) | ||
1027 | { | ||
1028 | set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG); | ||
1029 | sbi->sb->s_flags |= MS_RDONLY; | ||
1030 | } | ||
1031 | |||
1026 | #define get_inode_mode(i) \ | 1032 | #define get_inode_mode(i) \ |
1027 | ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \ | 1033 | ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \ |
1028 | (F2FS_I(i)->i_acl_mode) : ((i)->i_mode)) | 1034 | (F2FS_I(i)->i_acl_mode) : ((i)->i_mode)) |
@@ -1048,7 +1054,7 @@ void f2fs_set_inode_flags(struct inode *); | |||
1048 | struct inode *f2fs_iget(struct super_block *, unsigned long); | 1054 | struct inode *f2fs_iget(struct super_block *, unsigned long); |
1049 | int try_to_free_nats(struct f2fs_sb_info *, int); | 1055 | int try_to_free_nats(struct f2fs_sb_info *, int); |
1050 | void update_inode(struct inode *, struct page *); | 1056 | void update_inode(struct inode *, struct page *); |
1051 | int update_inode_page(struct inode *); | 1057 | void update_inode_page(struct inode *); |
1052 | int f2fs_write_inode(struct inode *, struct writeback_control *); | 1058 | int f2fs_write_inode(struct inode *, struct writeback_control *); |
1053 | void f2fs_evict_inode(struct inode *); | 1059 | void f2fs_evict_inode(struct inode *); |
1054 | 1060 | ||
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 4d67ed736dca..08d69c94ab8b 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c | |||
@@ -212,24 +212,29 @@ void update_inode(struct inode *inode, struct page *node_page) | |||
212 | clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); | 212 | clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); |
213 | } | 213 | } |
214 | 214 | ||
215 | int update_inode_page(struct inode *inode) | 215 | void update_inode_page(struct inode *inode) |
216 | { | 216 | { |
217 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 217 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
218 | struct page *node_page; | 218 | struct page *node_page; |
219 | 219 | retry: | |
220 | node_page = get_node_page(sbi, inode->i_ino); | 220 | node_page = get_node_page(sbi, inode->i_ino); |
221 | if (IS_ERR(node_page)) | 221 | if (IS_ERR(node_page)) { |
222 | return PTR_ERR(node_page); | 222 | int err = PTR_ERR(node_page); |
223 | 223 | if (err == -ENOMEM) { | |
224 | cond_resched(); | ||
225 | goto retry; | ||
226 | } else if (err != -ENOENT) { | ||
227 | f2fs_stop_checkpoint(sbi); | ||
228 | } | ||
229 | return; | ||
230 | } | ||
224 | update_inode(inode, node_page); | 231 | update_inode(inode, node_page); |
225 | f2fs_put_page(node_page, 1); | 232 | f2fs_put_page(node_page, 1); |
226 | return 0; | ||
227 | } | 233 | } |
228 | 234 | ||
229 | int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | 235 | int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) |
230 | { | 236 | { |
231 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 237 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
232 | int ret; | ||
233 | 238 | ||
234 | if (inode->i_ino == F2FS_NODE_INO(sbi) || | 239 | if (inode->i_ino == F2FS_NODE_INO(sbi) || |
235 | inode->i_ino == F2FS_META_INO(sbi)) | 240 | inode->i_ino == F2FS_META_INO(sbi)) |
@@ -243,13 +248,13 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
243 | * during the urgent cleaning time when runing out of free sections. | 248 | * during the urgent cleaning time when runing out of free sections. |
244 | */ | 249 | */ |
245 | f2fs_lock_op(sbi); | 250 | f2fs_lock_op(sbi); |
246 | ret = update_inode_page(inode); | 251 | update_inode_page(inode); |
247 | f2fs_unlock_op(sbi); | 252 | f2fs_unlock_op(sbi); |
248 | 253 | ||
249 | if (wbc) | 254 | if (wbc) |
250 | f2fs_balance_fs(sbi); | 255 | f2fs_balance_fs(sbi); |
251 | 256 | ||
252 | return ret; | 257 | return 0; |
253 | } | 258 | } |
254 | 259 | ||
255 | /* | 260 | /* |