|
@@ -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,
|
|
|
|
|
|
/* 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,
|
|
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,
|
|
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,
|
|
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)
|
|
|
|
- extent_end = start + btrfs_file_extent_num_bytes(eb, item);
|
|
|
|
- else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
|
|
|
|
|
|
+ found_type == BTRFS_FILE_EXTENT_PREALLOC) {
|
|
|
|
+ nbytes = btrfs_file_extent_num_bytes(eb, item);
|
|
|
|
+ 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,
|
|
}
|
|
}
|
|
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,
|
|
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)
|