diff options
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r-- | fs/f2fs/file.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index e755ee57e042..a9474cd4e0db 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -111,6 +111,7 @@ static int get_parent_ino(struct inode *inode, nid_t *pino) | |||
111 | int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | 111 | int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) |
112 | { | 112 | { |
113 | struct inode *inode = file->f_mapping->host; | 113 | struct inode *inode = file->f_mapping->host; |
114 | struct f2fs_inode_info *fi = F2FS_I(inode); | ||
114 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 115 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
115 | int ret = 0; | 116 | int ret = 0; |
116 | bool need_cp = false; | 117 | bool need_cp = false; |
@@ -133,7 +134,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
133 | /* guarantee free sections for fsync */ | 134 | /* guarantee free sections for fsync */ |
134 | f2fs_balance_fs(sbi); | 135 | f2fs_balance_fs(sbi); |
135 | 136 | ||
136 | mutex_lock(&inode->i_mutex); | 137 | down_read(&fi->i_sem); |
137 | 138 | ||
138 | /* | 139 | /* |
139 | * Both of fdatasync() and fsync() are able to be recovered from | 140 | * Both of fdatasync() and fsync() are able to be recovered from |
@@ -150,21 +151,27 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
150 | else if (F2FS_I(inode)->xattr_ver == cur_cp_version(F2FS_CKPT(sbi))) | 151 | else if (F2FS_I(inode)->xattr_ver == cur_cp_version(F2FS_CKPT(sbi))) |
151 | need_cp = true; | 152 | need_cp = true; |
152 | 153 | ||
154 | up_read(&fi->i_sem); | ||
155 | |||
153 | if (need_cp) { | 156 | if (need_cp) { |
154 | nid_t pino; | 157 | nid_t pino; |
155 | 158 | ||
156 | F2FS_I(inode)->xattr_ver = 0; | ||
157 | |||
158 | /* all the dirty node pages should be flushed for POR */ | 159 | /* all the dirty node pages should be flushed for POR */ |
159 | ret = f2fs_sync_fs(inode->i_sb, 1); | 160 | ret = f2fs_sync_fs(inode->i_sb, 1); |
161 | |||
162 | down_write(&fi->i_sem); | ||
163 | F2FS_I(inode)->xattr_ver = 0; | ||
160 | if (file_wrong_pino(inode) && inode->i_nlink == 1 && | 164 | if (file_wrong_pino(inode) && inode->i_nlink == 1 && |
161 | get_parent_ino(inode, &pino)) { | 165 | get_parent_ino(inode, &pino)) { |
162 | F2FS_I(inode)->i_pino = pino; | 166 | F2FS_I(inode)->i_pino = pino; |
163 | file_got_pino(inode); | 167 | file_got_pino(inode); |
168 | up_write(&fi->i_sem); | ||
164 | mark_inode_dirty_sync(inode); | 169 | mark_inode_dirty_sync(inode); |
165 | ret = f2fs_write_inode(inode, NULL); | 170 | ret = f2fs_write_inode(inode, NULL); |
166 | if (ret) | 171 | if (ret) |
167 | goto out; | 172 | goto out; |
173 | } else { | ||
174 | up_write(&fi->i_sem); | ||
168 | } | 175 | } |
169 | } else { | 176 | } else { |
170 | /* if there is no written node page, write its inode page */ | 177 | /* if there is no written node page, write its inode page */ |
@@ -180,7 +187,6 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
180 | ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); | 187 | ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); |
181 | } | 188 | } |
182 | out: | 189 | out: |
183 | mutex_unlock(&inode->i_mutex); | ||
184 | trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); | 190 | trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); |
185 | return ret; | 191 | return ret; |
186 | } | 192 | } |