f2fs: add F2FS_INLINE_DOTS to recover missing dot dentries

If f2fs was corrupted with missing dot dentries, it needs to recover them after
fsck.f2fs detection.

The underlying precedure is:

1. The fsck.f2fs remains F2FS_INLINE_DOTS flag in directory inode, if it detects
missing dot dentries.

2. When f2fs looks up the corrupted directory, it triggers f2fs_add_link with
proper inode numbers and their dot and dotdot names.

3. Once f2fs recovers the directory without errors, it removes F2FS_INLINE_DOTS
finally.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Jaegeuk Kim
2015-03-30 15:07:16 -07:00
parent c9ef481097
commit 510022a858
6 changed files with 112 additions and 42 deletions

View File

@@ -390,7 +390,7 @@ out:
}
int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name,
struct inode *inode)
struct inode *inode, nid_t ino, umode_t mode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
struct page *ipage;
@@ -400,7 +400,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name,
struct f2fs_inline_dentry *dentry_blk = NULL;
struct f2fs_dentry_ptr d;
int slots = GET_DENTRY_SLOTS(namelen);
struct page *page;
struct page *page = NULL;
int err = 0;
ipage = get_node_page(sbi, dir->i_ino);
@@ -417,29 +417,34 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name,
goto out;
}
down_write(&F2FS_I(inode)->i_sem);
page = init_inode_metadata(inode, dir, name, ipage);
if (IS_ERR(page)) {
err = PTR_ERR(page);
goto fail;
if (inode) {
down_write(&F2FS_I(inode)->i_sem);
page = init_inode_metadata(inode, dir, name, ipage);
if (IS_ERR(page)) {
err = PTR_ERR(page);
goto fail;
}
}
f2fs_wait_on_page_writeback(ipage, NODE);
name_hash = f2fs_dentry_hash(name);
make_dentry_ptr(&d, (void *)dentry_blk, 2);
f2fs_update_dentry(inode, &d, name, name_hash, bit_pos);
f2fs_update_dentry(ino, mode, &d, name, name_hash, bit_pos);
set_page_dirty(ipage);
/* we don't need to mark_inode_dirty now */
F2FS_I(inode)->i_pino = dir->i_ino;
update_inode(inode, page);
f2fs_put_page(page, 1);
if (inode) {
F2FS_I(inode)->i_pino = dir->i_ino;
update_inode(inode, page);
f2fs_put_page(page, 1);
}
update_parent_metadata(dir, inode, 0);
fail:
up_write(&F2FS_I(inode)->i_sem);
if (inode)
up_write(&F2FS_I(inode)->i_sem);
if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) {
update_inode(dir, ipage);