Commit 3792a64f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs

Pull one more btrfs fix from Chris Mason:
 "This has a recent fix from Josef for our tree log replay code.  It
  fixes problems where the inode counter for the number of bytes in the
  file wasn't getting updated properly during fsync replay.

  The commit did get rebased this morning, but it was only to clean up
  the subject line.  The code hasn't changed."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: make sure nbytes are right after log replay
parents 3c91930f 4bc4bee4
...@@ -317,6 +317,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, ...@@ -317,6 +317,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
unsigned long src_ptr; unsigned long src_ptr;
unsigned long dst_ptr; unsigned long dst_ptr;
int overwrite_root = 0; int overwrite_root = 0;
bool inode_item = key->type == BTRFS_INODE_ITEM_KEY;
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
overwrite_root = 1; overwrite_root = 1;
...@@ -326,6 +327,9 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, ...@@ -326,6 +327,9 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
/* look for the key in the destination tree */ /* look for the key in the destination tree */
ret = btrfs_search_slot(NULL, root, key, path, 0, 0); ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
if (ret < 0)
return ret;
if (ret == 0) { if (ret == 0) {
char *src_copy; char *src_copy;
char *dst_copy; char *dst_copy;
...@@ -367,6 +371,30 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, ...@@ -367,6 +371,30 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
return 0; return 0;
} }
/*
* We need to load the old nbytes into the inode so when we
* replay the extents we've logged we get the right nbytes.
*/
if (inode_item) {
struct btrfs_inode_item *item;
u64 nbytes;
item = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_inode_item);
nbytes = btrfs_inode_nbytes(path->nodes[0], item);
item = btrfs_item_ptr(eb, slot,
struct btrfs_inode_item);
btrfs_set_inode_nbytes(eb, item, nbytes);
}
} else if (inode_item) {
struct btrfs_inode_item *item;
/*
* New inode, set nbytes to 0 so that the nbytes comes out
* properly when we replay the extents.
*/
item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
btrfs_set_inode_nbytes(eb, item, 0);
} }
insert: insert:
btrfs_release_path(path); btrfs_release_path(path);
...@@ -486,7 +514,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, ...@@ -486,7 +514,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
int found_type; int found_type;
u64 extent_end; u64 extent_end;
u64 start = key->offset; u64 start = key->offset;
u64 saved_nbytes; u64 nbytes = 0;
struct btrfs_file_extent_item *item; struct btrfs_file_extent_item *item;
struct inode *inode = NULL; struct inode *inode = NULL;
unsigned long size; unsigned long size;
...@@ -496,10 +524,19 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, ...@@ -496,10 +524,19 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
found_type = btrfs_file_extent_type(eb, item); found_type = btrfs_file_extent_type(eb, item);
if (found_type == BTRFS_FILE_EXTENT_REG || if (found_type == BTRFS_FILE_EXTENT_REG ||
found_type == BTRFS_FILE_EXTENT_PREALLOC) found_type == BTRFS_FILE_EXTENT_PREALLOC) {
extent_end = start + btrfs_file_extent_num_bytes(eb, item); nbytes = btrfs_file_extent_num_bytes(eb, item);
else if (found_type == BTRFS_FILE_EXTENT_INLINE) { extent_end = start + nbytes;
/*
* We don't add to the inodes nbytes if we are prealloc or a
* hole.
*/
if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
nbytes = 0;
} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
size = btrfs_file_extent_inline_len(eb, item); size = btrfs_file_extent_inline_len(eb, item);
nbytes = btrfs_file_extent_ram_bytes(eb, item);
extent_end = ALIGN(start + size, root->sectorsize); extent_end = ALIGN(start + size, root->sectorsize);
} else { } else {
ret = 0; ret = 0;
...@@ -548,7 +585,6 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, ...@@ -548,7 +585,6 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
} }
btrfs_release_path(path); btrfs_release_path(path);
saved_nbytes = inode_get_bytes(inode);
/* drop any overlapping extents */ /* drop any overlapping extents */
ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1); ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1);
BUG_ON(ret); BUG_ON(ret);
...@@ -635,7 +671,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, ...@@ -635,7 +671,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
BUG_ON(ret); BUG_ON(ret);
} }
inode_set_bytes(inode, saved_nbytes); inode_add_bytes(inode, nbytes);
ret = btrfs_update_inode(trans, root, inode); ret = btrfs_update_inode(trans, root, inode);
out: out:
if (inode) if (inode)
......
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