|
@@ -149,6 +149,26 @@ static bool need_inode_page_update(struct f2fs_sb_info *sbi, nid_t ino)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void try_to_fix_pino(struct inode *inode)
|
|
|
|
+{
|
|
|
|
+ struct f2fs_inode_info *fi = F2FS_I(inode);
|
|
|
|
+ nid_t pino;
|
|
|
|
+
|
|
|
|
+ down_write(&fi->i_sem);
|
|
|
|
+ fi->xattr_ver = 0;
|
|
|
|
+ if (file_wrong_pino(inode) && inode->i_nlink == 1 &&
|
|
|
|
+ get_parent_ino(inode, &pino)) {
|
|
|
|
+ fi->i_pino = pino;
|
|
|
|
+ file_got_pino(inode);
|
|
|
|
+ up_write(&fi->i_sem);
|
|
|
|
+
|
|
|
|
+ mark_inode_dirty_sync(inode);
|
|
|
|
+ f2fs_write_inode(inode, NULL);
|
|
|
|
+ } else {
|
|
|
|
+ up_write(&fi->i_sem);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
|
|
int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
|
|
{
|
|
{
|
|
struct inode *inode = file->f_mapping->host;
|
|
struct inode *inode = file->f_mapping->host;
|
|
@@ -213,49 +233,36 @@ go_write:
|
|
up_read(&fi->i_sem);
|
|
up_read(&fi->i_sem);
|
|
|
|
|
|
if (need_cp) {
|
|
if (need_cp) {
|
|
- nid_t pino;
|
|
|
|
-
|
|
|
|
/* all the dirty node pages should be flushed for POR */
|
|
/* all the dirty node pages should be flushed for POR */
|
|
ret = f2fs_sync_fs(inode->i_sb, 1);
|
|
ret = f2fs_sync_fs(inode->i_sb, 1);
|
|
|
|
|
|
- down_write(&fi->i_sem);
|
|
|
|
- fi->xattr_ver = 0;
|
|
|
|
- if (file_wrong_pino(inode) && inode->i_nlink == 1 &&
|
|
|
|
- get_parent_ino(inode, &pino)) {
|
|
|
|
- fi->i_pino = pino;
|
|
|
|
- file_got_pino(inode);
|
|
|
|
- up_write(&fi->i_sem);
|
|
|
|
- mark_inode_dirty_sync(inode);
|
|
|
|
- ret = f2fs_write_inode(inode, NULL);
|
|
|
|
- if (ret)
|
|
|
|
- goto out;
|
|
|
|
- } else {
|
|
|
|
- up_write(&fi->i_sem);
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
|
|
+ /*
|
|
|
|
+ * We've secured consistency through sync_fs. Following pino
|
|
|
|
+ * will be used only for fsynced inodes after checkpoint.
|
|
|
|
+ */
|
|
|
|
+ try_to_fix_pino(inode);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
sync_nodes:
|
|
sync_nodes:
|
|
- sync_node_pages(sbi, ino, &wbc);
|
|
|
|
-
|
|
|
|
- if (need_inode_block_update(sbi, ino)) {
|
|
|
|
- mark_inode_dirty_sync(inode);
|
|
|
|
- ret = f2fs_write_inode(inode, NULL);
|
|
|
|
- if (ret)
|
|
|
|
- goto out;
|
|
|
|
- goto sync_nodes;
|
|
|
|
- }
|
|
|
|
|
|
+ sync_node_pages(sbi, ino, &wbc);
|
|
|
|
|
|
- ret = wait_on_node_pages_writeback(sbi, ino);
|
|
|
|
- if (ret)
|
|
|
|
- goto out;
|
|
|
|
|
|
+ if (need_inode_block_update(sbi, ino)) {
|
|
|
|
+ mark_inode_dirty_sync(inode);
|
|
|
|
+ f2fs_write_inode(inode, NULL);
|
|
|
|
+ goto sync_nodes;
|
|
|
|
+ }
|
|
|
|
|
|
- /* once recovery info is written, don't need to tack this */
|
|
|
|
- remove_dirty_inode(sbi, ino, APPEND_INO);
|
|
|
|
- clear_inode_flag(fi, FI_APPEND_WRITE);
|
|
|
|
|
|
+ ret = wait_on_node_pages_writeback(sbi, ino);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ /* once recovery info is written, don't need to tack this */
|
|
|
|
+ remove_dirty_inode(sbi, ino, APPEND_INO);
|
|
|
|
+ clear_inode_flag(fi, FI_APPEND_WRITE);
|
|
flush_out:
|
|
flush_out:
|
|
- remove_dirty_inode(sbi, ino, UPDATE_INO);
|
|
|
|
- clear_inode_flag(fi, FI_UPDATE_WRITE);
|
|
|
|
- ret = f2fs_issue_flush(sbi);
|
|
|
|
- }
|
|
|
|
|
|
+ remove_dirty_inode(sbi, ino, UPDATE_INO);
|
|
|
|
+ clear_inode_flag(fi, FI_UPDATE_WRITE);
|
|
|
|
+ ret = f2fs_issue_flush(sbi);
|
|
out:
|
|
out:
|
|
trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret);
|
|
trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret);
|
|
return ret;
|
|
return ret;
|