|
@@ -3209,115 +3209,6 @@ static int extent_cmp(void *priv, struct list_head *a, struct list_head *b)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int drop_adjacent_extents(struct btrfs_trans_handle *trans,
|
|
|
|
- struct btrfs_root *root, struct inode *inode,
|
|
|
|
- struct extent_map *em,
|
|
|
|
- struct btrfs_path *path)
|
|
|
|
-{
|
|
|
|
- struct btrfs_file_extent_item *fi;
|
|
|
|
- struct extent_buffer *leaf;
|
|
|
|
- struct btrfs_key key, new_key;
|
|
|
|
- struct btrfs_map_token token;
|
|
|
|
- u64 extent_end;
|
|
|
|
- u64 extent_offset = 0;
|
|
|
|
- int extent_type;
|
|
|
|
- int del_slot = 0;
|
|
|
|
- int del_nr = 0;
|
|
|
|
- int ret = 0;
|
|
|
|
-
|
|
|
|
- while (1) {
|
|
|
|
- btrfs_init_map_token(&token);
|
|
|
|
- leaf = path->nodes[0];
|
|
|
|
- path->slots[0]++;
|
|
|
|
- if (path->slots[0] >= btrfs_header_nritems(leaf)) {
|
|
|
|
- if (del_nr) {
|
|
|
|
- ret = btrfs_del_items(trans, root, path,
|
|
|
|
- del_slot, del_nr);
|
|
|
|
- if (ret)
|
|
|
|
- return ret;
|
|
|
|
- del_nr = 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- ret = btrfs_next_leaf_write(trans, root, path, 1);
|
|
|
|
- if (ret < 0)
|
|
|
|
- return ret;
|
|
|
|
- if (ret > 0)
|
|
|
|
- return 0;
|
|
|
|
- leaf = path->nodes[0];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
|
|
|
|
- if (key.objectid != btrfs_ino(inode) ||
|
|
|
|
- key.type != BTRFS_EXTENT_DATA_KEY ||
|
|
|
|
- key.offset >= em->start + em->len)
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- fi = btrfs_item_ptr(leaf, path->slots[0],
|
|
|
|
- struct btrfs_file_extent_item);
|
|
|
|
- extent_type = btrfs_token_file_extent_type(leaf, fi, &token);
|
|
|
|
- if (extent_type == BTRFS_FILE_EXTENT_REG ||
|
|
|
|
- extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
|
|
|
|
- extent_offset = btrfs_token_file_extent_offset(leaf,
|
|
|
|
- fi, &token);
|
|
|
|
- extent_end = key.offset +
|
|
|
|
- btrfs_token_file_extent_num_bytes(leaf, fi,
|
|
|
|
- &token);
|
|
|
|
- } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
|
|
|
|
- extent_end = key.offset +
|
|
|
|
- btrfs_file_extent_inline_len(leaf, fi);
|
|
|
|
- } else {
|
|
|
|
- BUG();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (extent_end <= em->len + em->start) {
|
|
|
|
- if (!del_nr) {
|
|
|
|
- del_slot = path->slots[0];
|
|
|
|
- }
|
|
|
|
- del_nr++;
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Ok so we'll ignore previous items if we log a new extent,
|
|
|
|
- * which can lead to overlapping extents, so if we have an
|
|
|
|
- * existing extent we want to adjust we _have_ to check the next
|
|
|
|
- * guy to make sure we even need this extent anymore, this keeps
|
|
|
|
- * us from panicing in set_item_key_safe.
|
|
|
|
- */
|
|
|
|
- if (path->slots[0] < btrfs_header_nritems(leaf) - 1) {
|
|
|
|
- struct btrfs_key tmp_key;
|
|
|
|
-
|
|
|
|
- btrfs_item_key_to_cpu(leaf, &tmp_key,
|
|
|
|
- path->slots[0] + 1);
|
|
|
|
- if (tmp_key.objectid == btrfs_ino(inode) &&
|
|
|
|
- tmp_key.type == BTRFS_EXTENT_DATA_KEY &&
|
|
|
|
- tmp_key.offset <= em->start + em->len) {
|
|
|
|
- if (!del_nr)
|
|
|
|
- del_slot = path->slots[0];
|
|
|
|
- del_nr++;
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
|
|
|
|
- memcpy(&new_key, &key, sizeof(new_key));
|
|
|
|
- new_key.offset = em->start + em->len;
|
|
|
|
- btrfs_set_item_key_safe(trans, root, path, &new_key);
|
|
|
|
- extent_offset += em->start + em->len - key.offset;
|
|
|
|
- btrfs_set_token_file_extent_offset(leaf, fi, extent_offset,
|
|
|
|
- &token);
|
|
|
|
- btrfs_set_token_file_extent_num_bytes(leaf, fi, extent_end -
|
|
|
|
- (em->start + em->len),
|
|
|
|
- &token);
|
|
|
|
- btrfs_mark_buffer_dirty(leaf);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (del_nr)
|
|
|
|
- ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int log_one_extent(struct btrfs_trans_handle *trans,
|
|
static int log_one_extent(struct btrfs_trans_handle *trans,
|
|
struct inode *inode, struct btrfs_root *root,
|
|
struct inode *inode, struct btrfs_root *root,
|
|
struct extent_map *em, struct btrfs_path *path)
|
|
struct extent_map *em, struct btrfs_path *path)
|
|
@@ -3339,39 +3230,24 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
|
|
int index = log->log_transid % 2;
|
|
int index = log->log_transid % 2;
|
|
bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
|
|
bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
|
|
|
|
|
|
-insert:
|
|
|
|
|
|
+ ret = __btrfs_drop_extents(trans, log, inode, path, em->start,
|
|
|
|
+ em->start + em->len, NULL, 0);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
INIT_LIST_HEAD(&ordered_sums);
|
|
INIT_LIST_HEAD(&ordered_sums);
|
|
btrfs_init_map_token(&token);
|
|
btrfs_init_map_token(&token);
|
|
key.objectid = btrfs_ino(inode);
|
|
key.objectid = btrfs_ino(inode);
|
|
key.type = BTRFS_EXTENT_DATA_KEY;
|
|
key.type = BTRFS_EXTENT_DATA_KEY;
|
|
key.offset = em->start;
|
|
key.offset = em->start;
|
|
- path->really_keep_locks = 1;
|
|
|
|
|
|
|
|
ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*fi));
|
|
ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*fi));
|
|
- if (ret && ret != -EEXIST) {
|
|
|
|
- path->really_keep_locks = 0;
|
|
|
|
|
|
+ if (ret)
|
|
return ret;
|
|
return ret;
|
|
- }
|
|
|
|
leaf = path->nodes[0];
|
|
leaf = path->nodes[0];
|
|
fi = btrfs_item_ptr(leaf, path->slots[0],
|
|
fi = btrfs_item_ptr(leaf, path->slots[0],
|
|
struct btrfs_file_extent_item);
|
|
struct btrfs_file_extent_item);
|
|
|
|
|
|
- /*
|
|
|
|
- * If we are overwriting an inline extent with a real one then we need
|
|
|
|
- * to just delete the inline extent as it may not be large enough to
|
|
|
|
- * have the entire file_extent_item.
|
|
|
|
- */
|
|
|
|
- if (ret && btrfs_token_file_extent_type(leaf, fi, &token) ==
|
|
|
|
- BTRFS_FILE_EXTENT_INLINE) {
|
|
|
|
- ret = btrfs_del_item(trans, log, path);
|
|
|
|
- btrfs_release_path(path);
|
|
|
|
- if (ret) {
|
|
|
|
- path->really_keep_locks = 0;
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
- goto insert;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
btrfs_set_token_file_extent_generation(leaf, fi, em->generation,
|
|
btrfs_set_token_file_extent_generation(leaf, fi, em->generation,
|
|
&token);
|
|
&token);
|
|
if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
|
|
if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
|
|
@@ -3417,15 +3293,7 @@ insert:
|
|
btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token);
|
|
btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token);
|
|
btrfs_mark_buffer_dirty(leaf);
|
|
btrfs_mark_buffer_dirty(leaf);
|
|
|
|
|
|
- /*
|
|
|
|
- * Have to check the extent to the right of us to make sure it doesn't
|
|
|
|
- * fall in our current range. We're ok if the previous extent is in our
|
|
|
|
- * range since the recovery stuff will run us in key order and thus just
|
|
|
|
- * drop the part we overwrote.
|
|
|
|
- */
|
|
|
|
- ret = drop_adjacent_extents(trans, log, inode, em, path);
|
|
|
|
btrfs_release_path(path);
|
|
btrfs_release_path(path);
|
|
- path->really_keep_locks = 0;
|
|
|
|
if (ret) {
|
|
if (ret) {
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|