aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2014-01-24 09:42:16 +0900
committerAndreas Blaesius <skate4life@gmx.de>2016-06-05 21:21:12 +0200
commit6b9122c2daca28a0a0790a967411631785553a36 (patch)
tree57a61ba2a63354839db8ea1a5eddf835ac354189
parent24f2efc9ae763729da95d7768fef878b2eef6f71 (diff)
downloadkernel_samsung_espresso10-6b9122c2daca28a0a0790a967411631785553a36.zip
kernel_samsung_espresso10-6b9122c2daca28a0a0790a967411631785553a36.tar.gz
kernel_samsung_espresso10-6b9122c2daca28a0a0790a967411631785553a36.tar.bz2
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> Conflicts: fs/f2fs/f2fs.h
-rw-r--r--fs/f2fs/data.c3
-rw-r--r--fs/f2fs/f2fs.h8
-rw-r--r--fs/f2fs/inode.c23
3 files changed, 22 insertions, 12 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index d866037..dd58694 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -61,8 +61,7 @@ static void f2fs_write_end_io(struct bio *bio, int err)
if (unlikely(!uptodate)) {
SetPageError(page);
set_bit(AS_EIO, &page->mapping->flags);
- set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
- sbi->sb->s_flags |= MS_RDONLY;
+ f2fs_stop_checkpoint(sbi);
}
end_page_writeback(page);
dec_page_count(sbi, F2FS_WRITEBACK);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index af51a0b..42903c3 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1023,6 +1023,12 @@ static inline int f2fs_readonly(struct super_block *sb)
return sb->s_flags & MS_RDONLY;
}
+static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi)
+{
+ set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
+ sbi->sb->s_flags |= MS_RDONLY;
+}
+
/*
* file.c
*/
@@ -1044,7 +1050,7 @@ void f2fs_set_inode_flags(struct inode *);
struct inode *f2fs_iget(struct super_block *, unsigned long);
int try_to_free_nats(struct f2fs_sb_info *, int);
void update_inode(struct inode *, struct page *);
-int update_inode_page(struct inode *);
+void update_inode_page(struct inode *);
int f2fs_write_inode(struct inode *, struct writeback_control *);
void f2fs_evict_inode(struct inode *);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 28a8792..d7f64af 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)
clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE);
}
-int update_inode_page(struct inode *inode)
+void update_inode_page(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
struct page *node_page;
-
+retry:
node_page = get_node_page(sbi, inode->i_ino);
- if (IS_ERR(node_page))
- return PTR_ERR(node_page);
-
+ if (IS_ERR(node_page)) {
+ int err = PTR_ERR(node_page);
+ if (err == -ENOMEM) {
+ cond_resched();
+ goto retry;
+ } else if (err != -ENOENT) {
+ f2fs_stop_checkpoint(sbi);
+ }
+ return;
+ }
update_inode(inode, node_page);
f2fs_put_page(node_page, 1);
- return 0;
}
int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
{
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
- int ret;
if (inode->i_ino == F2FS_NODE_INO(sbi) ||
inode->i_ino == F2FS_META_INO(sbi))
@@ -243,13 +248,13 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
* during the urgent cleaning time when runing out of free sections.
*/
f2fs_lock_op(sbi);
- ret = update_inode_page(inode);
+ update_inode_page(inode);
f2fs_unlock_op(sbi);
if (wbc)
f2fs_balance_fs(sbi);
- return ret;
+ return 0;
}
/*