Commit 0aa4a17d authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

Btrfs: handle not finding the extent exactly when logging changed extents

I started hitting warnings when running xfstest 68 in a loop because there
were EM's that were not lined up properly with the physical extents.  This
is ok, if we do something like punch a hole or write to a preallocated space
or something like that we can have an EM that doesn't cover the entire
physical extent.  So fix the tree logging stuff to cope with this case so we
don't just commit the transaction.  With this patch I no longer see the
warnings from the tree logging code.  Thanks,
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
parent 005d6427
...@@ -2833,6 +2833,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, ...@@ -2833,6 +2833,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
struct btrfs_file_extent_item *fi; struct btrfs_file_extent_item *fi;
struct btrfs_key key; struct btrfs_key key;
u64 start = em->mod_start; u64 start = em->mod_start;
u64 search_start = start;
u64 len = em->mod_len; u64 len = em->mod_len;
u64 num_bytes; u64 num_bytes;
int nritems; int nritems;
...@@ -2848,23 +2849,55 @@ static int log_one_extent(struct btrfs_trans_handle *trans, ...@@ -2848,23 +2849,55 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
while (len) { while (len) {
if (args->nr) if (args->nr)
goto next_slot; goto next_slot;
again:
key.objectid = btrfs_ino(inode); key.objectid = btrfs_ino(inode);
key.type = BTRFS_EXTENT_DATA_KEY; key.type = BTRFS_EXTENT_DATA_KEY;
key.offset = start; key.offset = search_start;
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ret) { if (ret) {
/* /*
* This shouldn't happen, but it might so warn and * A rare case were we can have an em for a section of a
* return an error. * larger extent so we need to make sure that this em
* falls within the extent we've found. If not we just
* bail and go back to ye-olde way of doing things but
* it happens often enough in testing that we need to do
* this dance to make sure.
*/ */
WARN_ON(1); do {
if (path->slots[0] == 0) {
btrfs_release_path(path);
if (search_start == 0)
return -ENOENT;
search_start--;
goto again;
}
path->slots[0]--;
btrfs_item_key_to_cpu(path->nodes[0], &key,
path->slots[0]);
if (key.objectid != btrfs_ino(inode) ||
key.type != BTRFS_EXTENT_DATA_KEY) {
btrfs_release_path(path);
return -ENOENT;
}
} while (key.offset > start);
fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_file_extent_item);
num_bytes = btrfs_file_extent_num_bytes(path->nodes[0],
fi);
if (key.offset + num_bytes <= start) {
btrfs_release_path(path);
return -ENOENT; return -ENOENT;
} }
}
args->src = path->nodes[0]; args->src = path->nodes[0];
next_slot: next_slot:
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
fi = btrfs_item_ptr(args->src, path->slots[0], fi = btrfs_item_ptr(args->src, path->slots[0],
struct btrfs_file_extent_item); struct btrfs_file_extent_item);
if (args->nr && if (args->nr &&
...@@ -2898,8 +2931,9 @@ static int log_one_extent(struct btrfs_trans_handle *trans, ...@@ -2898,8 +2931,9 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
} else { } else {
len -= num_bytes; len -= num_bytes;
} }
start += btrfs_file_extent_num_bytes(args->src, fi); start = key.offset + num_bytes;
args->next_offset = start; args->next_offset = start;
search_start = start;
if (path->slots[0] < nritems) { if (path->slots[0] < nritems) {
if (len) if (len)
......
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