aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/namei.c')
-rw-r--r--fs/f2fs/namei.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 1e2ae21bd6b6..8055e30eb14d 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -187,6 +187,44 @@ struct dentry *f2fs_get_parent(struct dentry *child)
187 return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino)); 187 return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino));
188} 188}
189 189
190static int __recover_dot_dentries(struct inode *dir, nid_t pino)
191{
192 struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
193 struct qstr dot = QSTR_INIT(".", 1);
194 struct qstr dotdot = QSTR_INIT("..", 2);
195 struct f2fs_dir_entry *de;
196 struct page *page;
197 int err = 0;
198
199 f2fs_lock_op(sbi);
200
201 de = f2fs_find_entry(dir, &dot, &page);
202 if (de) {
203 f2fs_dentry_kunmap(dir, page);
204 f2fs_put_page(page, 0);
205 } else {
206 err = __f2fs_add_link(dir, &dot, NULL, dir->i_ino, S_IFDIR);
207 if (err)
208 goto out;
209 }
210
211 de = f2fs_find_entry(dir, &dotdot, &page);
212 if (de) {
213 f2fs_dentry_kunmap(dir, page);
214 f2fs_put_page(page, 0);
215 } else {
216 err = __f2fs_add_link(dir, &dotdot, NULL, pino, S_IFDIR);
217 }
218out:
219 if (!err) {
220 clear_inode_flag(F2FS_I(dir), FI_INLINE_DOTS);
221 mark_inode_dirty(dir);
222 }
223
224 f2fs_unlock_op(sbi);
225 return err;
226}
227
190static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, 228static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
191 unsigned int flags) 229 unsigned int flags)
192{ 230{
@@ -206,6 +244,16 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
206 inode = f2fs_iget(dir->i_sb, ino); 244 inode = f2fs_iget(dir->i_sb, ino);
207 if (IS_ERR(inode)) 245 if (IS_ERR(inode))
208 return ERR_CAST(inode); 246 return ERR_CAST(inode);
247
248 if (f2fs_has_inline_dots(inode)) {
249 int err;
250
251 err = __recover_dot_dentries(inode, dir->i_ino);
252 if (err) {
253 iget_failed(inode);
254 return ERR_PTR(err);
255 }
256 }
209 } 257 }
210 258
211 return d_splice_alias(inode, dentry); 259 return d_splice_alias(inode, dentry);