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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user