Commit d555438b authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

Btrfs: drop dir i_size when adding new names on replay

So if we have dir_index items in the log that means we also have the inode item
as well, which means that the inode's i_size is correct.  However when we
process dir_index'es we call btrfs_add_link() which will increase the
directory's i_size for the new entry.  To fix this we need to just set the dir
items i_size to 0, and then as we find dir_index items we adjust the i_size.
btrfs_add_link() will do it for new entries, and if the entry already exists we
can just add the name_len to the i_size ourselves.  Thanks,
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
Signed-off-by: default avatarChris Mason <chris.mason@fusionio.com>
parent dd8e7217
...@@ -394,6 +394,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, ...@@ -394,6 +394,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
if (inode_item) { if (inode_item) {
struct btrfs_inode_item *item; struct btrfs_inode_item *item;
u64 nbytes; u64 nbytes;
u32 mode;
item = btrfs_item_ptr(path->nodes[0], path->slots[0], item = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_inode_item); struct btrfs_inode_item);
...@@ -401,9 +402,19 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, ...@@ -401,9 +402,19 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
item = btrfs_item_ptr(eb, slot, item = btrfs_item_ptr(eb, slot,
struct btrfs_inode_item); struct btrfs_inode_item);
btrfs_set_inode_nbytes(eb, item, nbytes); btrfs_set_inode_nbytes(eb, item, nbytes);
/*
* If this is a directory we need to reset the i_size to
* 0 so that we can set it up properly when replaying
* the rest of the items in this log.
*/
mode = btrfs_inode_mode(eb, item);
if (S_ISDIR(mode))
btrfs_set_inode_size(eb, item, 0);
} }
} else if (inode_item) { } else if (inode_item) {
struct btrfs_inode_item *item; struct btrfs_inode_item *item;
u32 mode;
/* /*
* New inode, set nbytes to 0 so that the nbytes comes out * New inode, set nbytes to 0 so that the nbytes comes out
...@@ -411,6 +422,15 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, ...@@ -411,6 +422,15 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
*/ */
item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item); item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
btrfs_set_inode_nbytes(eb, item, 0); btrfs_set_inode_nbytes(eb, item, 0);
/*
* If this is a directory we need to reset the i_size to 0 so
* that we can set it up properly when replaying the rest of
* the items in this log.
*/
mode = btrfs_inode_mode(eb, item);
if (S_ISDIR(mode))
btrfs_set_inode_size(eb, item, 0);
} }
insert: insert:
btrfs_release_path(path); btrfs_release_path(path);
...@@ -1497,6 +1517,7 @@ static noinline int insert_one_name(struct btrfs_trans_handle *trans, ...@@ -1497,6 +1517,7 @@ static noinline int insert_one_name(struct btrfs_trans_handle *trans,
iput(inode); iput(inode);
return -EIO; return -EIO;
} }
ret = btrfs_add_link(trans, dir, inode, name, name_len, 1, index); ret = btrfs_add_link(trans, dir, inode, name, name_len, 1, index);
/* FIXME, put inode into FIXUP list */ /* FIXME, put inode into FIXUP list */
...@@ -1535,6 +1556,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, ...@@ -1535,6 +1556,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
u8 log_type; u8 log_type;
int exists; int exists;
int ret = 0; int ret = 0;
bool update_size = (key->type == BTRFS_DIR_INDEX_KEY);
dir = read_one_inode(root, key->objectid); dir = read_one_inode(root, key->objectid);
if (!dir) if (!dir)
...@@ -1605,6 +1627,10 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, ...@@ -1605,6 +1627,10 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
goto insert; goto insert;
out: out:
btrfs_release_path(path); btrfs_release_path(path);
if (!ret && update_size) {
btrfs_i_size_write(dir, dir->i_size + name_len * 2);
ret = btrfs_update_inode(trans, root, dir);
}
kfree(name); kfree(name);
iput(dir); iput(dir);
return ret; return ret;
...@@ -1615,6 +1641,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, ...@@ -1615,6 +1641,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
name, name_len, log_type, &log_key); name, name_len, log_type, &log_key);
if (ret && ret != -ENOENT) if (ret && ret != -ENOENT)
goto out; goto out;
update_size = false;
ret = 0; ret = 0;
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment