Skip to content

Commit

Permalink
f2fs: fix tracking parent inode number
Browse files Browse the repository at this point in the history
Previously, f2fs didn't track the parent inode number correctly which is stored
in each f2fs_inode. In the case of the following scenario, a bug can be occured.

Let's suppose there are one directory, "/b", and two files, "/a" and "/b/a".
 - pino of "/a" is ROOT_INO.
 - pino of "/b/a" is DIR_B_INO.

Then,
 # sync
  : The inode pages of "/a" and "/b/a" contain the parent inode numbers as
    ROOT_INO and DIR_B_INO respectively.
 # mv /a /b/a
  : The parent inode number of "/a" should be changed to DIR_B_INO, but f2fs
    didn't do that. Ref. f2fs_set_link().

In order to fix this clearly, I added i_pino in f2fs_inode_info, and whenever
it needs to be changed like in f2fs_add_link() and f2fs_set_link(), it is
updated temporarily in f2fs_inode_info.

And later, f2fs_write_inode() stores the latest information to the inode pages.
For power-off-recovery, f2fs_sync_file() triggers simply f2fs_write_inode().

Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
  • Loading branch information
Jaegeuk Kim committed Dec 11, 2012
1 parent 3cd8a23 commit 6666e6a
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 2 deletions.
10 changes: 8 additions & 2 deletions fs/f2fs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,16 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
set_page_dirty(page);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
mark_inode_dirty(dir);

/* update parent inode number before releasing dentry page */
F2FS_I(inode)->i_pino = dir->i_ino;

f2fs_put_page(page, 1);
mutex_unlock_op(sbi, DENTRY_OPS);
}

void init_dent_inode(struct dentry *dentry, struct page *ipage)
{
struct inode *dir = dentry->d_parent->d_inode;
struct f2fs_node *rn;

if (IS_ERR(ipage))
Expand All @@ -272,7 +275,6 @@ void init_dent_inode(struct dentry *dentry, struct page *ipage)

/* copy dentry info. to this inode page */
rn = (struct f2fs_node *)page_address(ipage);
rn->i.i_pino = cpu_to_le32(dir->i_ino);
rn->i.i_namelen = cpu_to_le32(dentry->d_name.len);
memcpy(rn->i.i_name, dentry->d_name.name, dentry->d_name.len);
set_page_dirty(ipage);
Expand Down Expand Up @@ -444,7 +446,11 @@ int f2fs_add_link(struct dentry *dentry, struct inode *inode)
for (i = 0; i < slots; i++)
test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
set_page_dirty(dentry_page);

update_parent_metadata(dir, inode, current_depth);

/* update parent inode number before releasing dentry page */
F2FS_I(inode)->i_pino = dir->i_ino;
fail:
kunmap(dentry_page);
f2fs_put_page(dentry_page, 1);
Expand Down
1 change: 1 addition & 0 deletions fs/f2fs/f2fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ struct f2fs_inode_info {
unsigned long i_flags; /* keep an inode flags for ioctl */
unsigned char i_advise; /* use to give file attribute hints */
unsigned int i_current_depth; /* use only in directory structure */
unsigned int i_pino; /* parent inode number */
umode_t i_acl_mode; /* keep file acl mode temporarily */

/* Use below internally in f2fs*/
Expand Down
2 changes: 2 additions & 0 deletions fs/f2fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ static int do_read_inode(struct inode *inode)
fi->flags = 0;
fi->data_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver) - 1;
fi->i_advise = ri->i_advise;
fi->i_pino = le32_to_cpu(ri->i_pino);
get_extent_info(&fi->ext, ri->i_ext);
f2fs_put_page(node_page, 1);
return 0;
Expand Down Expand Up @@ -200,6 +201,7 @@ void update_inode(struct inode *inode, struct page *node_page)
ri->i_current_depth = cpu_to_le32(F2FS_I(inode)->i_current_depth);
ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
ri->i_generation = cpu_to_le32(inode->i_generation);
set_page_dirty(node_page);
}
Expand Down

0 comments on commit 6666e6a

Please sign in to comment.