aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2012-12-19 01:28:39 -0500
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2012-12-25 20:39:52 -0500
commit398b1ac5a57219823f942a8d3665b27ab99354de (patch)
tree7e4806bf658cdffdd977f83a1365f673b9f8e487 /fs
parent38e0abdcfb5e69aa61a1e9b474d434afc1c177a9 (diff)
f2fs: fix handling errors got by f2fs_write_inode
Ruslan reported that f2fs hangs with an infinite loop in f2fs_sync_file(): while (sync_node_pages(sbi, inode->i_ino, &wbc) == 0) f2fs_write_inode(inode, NULL); The reason was revealed that the cold flag is not set even thought this inode is a normal file. Therefore, sync_node_pages() skips to write node blocks since it only writes cold node blocks. The cold flag is stored to the node_footer in node block, and whenever a new node page is allocated, it is set according to its file type, file or directory. But, after sudden-power-off, when recovering the inode page, f2fs doesn't recover its cold flag. So, let's assign the cold flag in more right places. One more thing: If f2fs_write_inode() returns an error due to whatever situations, there would be no dirty node pages so that sync_node_pages() returns zero. (i.e., zero means nothing was written.) Reported-by: Ruslan N. Marchenko <me@ruff.mobi> Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/f2fs/dir.c2
-rw-r--r--fs/f2fs/file.c10
-rw-r--r--fs/f2fs/inode.c1
-rw-r--r--fs/f2fs/node.c2
4 files changed, 10 insertions, 5 deletions
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index e1f66df0f97d..4a78d6c4f3a7 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -11,6 +11,7 @@
11#include <linux/fs.h> 11#include <linux/fs.h>
12#include <linux/f2fs_fs.h> 12#include <linux/f2fs_fs.h>
13#include "f2fs.h" 13#include "f2fs.h"
14#include "node.h"
14#include "acl.h" 15#include "acl.h"
15 16
16static unsigned long dir_blocks(struct inode *inode) 17static unsigned long dir_blocks(struct inode *inode)
@@ -308,6 +309,7 @@ static int init_inode_metadata(struct inode *inode, struct dentry *dentry)
308 ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino); 309 ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino);
309 if (IS_ERR(ipage)) 310 if (IS_ERR(ipage))
310 return PTR_ERR(ipage); 311 return PTR_ERR(ipage);
312 set_cold_node(inode, ipage);
311 init_dent_inode(dentry, ipage); 313 init_dent_inode(dentry, ipage);
312 f2fs_put_page(ipage, 1); 314 f2fs_put_page(ipage, 1);
313 } 315 }
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index f9e085dfb1f0..7f9ea9271ebe 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -160,15 +160,17 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
160 if (need_to_sync_dir(sbi, inode)) 160 if (need_to_sync_dir(sbi, inode))
161 need_cp = true; 161 need_cp = true;
162 162
163 f2fs_write_inode(inode, NULL);
164
165 if (need_cp) { 163 if (need_cp) {
166 /* all the dirty node pages should be flushed for POR */ 164 /* all the dirty node pages should be flushed for POR */
167 ret = f2fs_sync_fs(inode->i_sb, 1); 165 ret = f2fs_sync_fs(inode->i_sb, 1);
168 clear_inode_flag(F2FS_I(inode), FI_NEED_CP); 166 clear_inode_flag(F2FS_I(inode), FI_NEED_CP);
169 } else { 167 } else {
170 while (sync_node_pages(sbi, inode->i_ino, &wbc) == 0) 168 /* if there is no written node page, write its inode page */
171 f2fs_write_inode(inode, NULL); 169 while (!sync_node_pages(sbi, inode->i_ino, &wbc)) {
170 ret = f2fs_write_inode(inode, NULL);
171 if (ret)
172 goto out;
173 }
172 filemap_fdatawait_range(sbi->node_inode->i_mapping, 174 filemap_fdatawait_range(sbi->node_inode->i_mapping,
173 0, LONG_MAX); 175 0, LONG_MAX);
174 } 176 }
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index df5fb381ebf1..bf20b4d03214 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -203,6 +203,7 @@ void update_inode(struct inode *inode, struct page *node_page)
203 ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags); 203 ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
204 ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino); 204 ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
205 ri->i_generation = cpu_to_le32(inode->i_generation); 205 ri->i_generation = cpu_to_le32(inode->i_generation);
206 set_cold_node(inode, node_page);
206 set_page_dirty(node_page); 207 set_page_dirty(node_page);
207} 208}
208 209
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 19870361497e..dffac1c11f63 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -834,11 +834,11 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
834 goto fail; 834 goto fail;
835 } 835 }
836 set_node_addr(sbi, &new_ni, NEW_ADDR); 836 set_node_addr(sbi, &new_ni, NEW_ADDR);
837 set_cold_node(dn->inode, page);
837 838
838 dn->node_page = page; 839 dn->node_page = page;
839 sync_inode_page(dn); 840 sync_inode_page(dn);
840 set_page_dirty(page); 841 set_page_dirty(page);
841 set_cold_node(dn->inode, page);
842 if (ofs == 0) 842 if (ofs == 0)
843 inc_valid_inode_count(sbi); 843 inc_valid_inode_count(sbi);
844 844