Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 128992
b: refs/heads/master
c: 80ff385
h: refs/heads/master
v: v3
  • Loading branch information
Yan Zheng authored and Chris Mason committed Oct 30, 2008
1 parent b3e426b commit e995f07
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 214 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6643558db29006825dbb10012b3f8890aca4bcd5
refs/heads/master: 80ff385665b7fca29fefe358a60ab0d09f9b8e87
8 changes: 5 additions & 3 deletions trunk/fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ struct btrfs_root_item {
__le64 bytenr;
__le64 byte_limit;
__le64 bytes_used;
__le64 last_snapshot;
__le32 flags;
__le32 refs;
struct btrfs_disk_key drop_progress;
Expand Down Expand Up @@ -1413,6 +1414,8 @@ BTRFS_SETGET_STACK_FUNCS(root_refs, struct btrfs_root_item, refs, 32);
BTRFS_SETGET_STACK_FUNCS(root_flags, struct btrfs_root_item, flags, 32);
BTRFS_SETGET_STACK_FUNCS(root_used, struct btrfs_root_item, bytes_used, 64);
BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64);
BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item,
last_snapshot, 64);

/* struct btrfs_super_block */
BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
Expand Down Expand Up @@ -1564,9 +1567,8 @@ int btrfs_update_pinned_extents(struct btrfs_root *root,
u64 bytenr, u64 num, int pin);
int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *leaf);
int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_key *key, u64 bytenr);
int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytenr);
int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy);
Expand Down
131 changes: 18 additions & 113 deletions trunk/fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -848,18 +848,17 @@ int btrfs_lookup_extent_ref(struct btrfs_trans_handle *trans,
return 0;
}

static int get_reference_status(struct btrfs_root *root, u64 bytenr,
u64 parent_gen, u64 ref_objectid,
u64 *min_generation, u32 *ref_count)
int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytenr)
{
struct btrfs_root *extent_root = root->fs_info->extent_root;
struct btrfs_path *path;
struct extent_buffer *leaf;
struct btrfs_extent_ref *ref_item;
struct btrfs_key key;
struct btrfs_key found_key;
u64 root_objectid = root->root_key.objectid;
u64 ref_generation;
u64 ref_root;
u64 last_snapshot;
u32 nritems;
int ret;

Expand All @@ -872,22 +871,20 @@ static int get_reference_status(struct btrfs_root *root, u64 bytenr,
if (ret < 0)
goto out;
BUG_ON(ret == 0);
if (ret < 0 || path->slots[0] == 0)

ret = -ENOENT;
if (path->slots[0] == 0)
goto out;

path->slots[0]--;
leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);

if (found_key.objectid != bytenr ||
found_key.type != BTRFS_EXTENT_ITEM_KEY) {
ret = 1;
found_key.type != BTRFS_EXTENT_ITEM_KEY)
goto out;
}

*ref_count = 0;
*min_generation = (u64)-1;

last_snapshot = btrfs_root_last_snapshot(&root->root_item);
while (1) {
leaf = path->nodes[0];
nritems = btrfs_header_nritems(leaf);
Expand All @@ -910,114 +907,22 @@ static int get_reference_status(struct btrfs_root *root, u64 bytenr,

ref_item = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_extent_ref);
ref_generation = btrfs_ref_generation(leaf, ref_item);
/*
* For (parent_gen > 0 && parent_gen > ref_generation):
*
* we reach here through the oldest root, therefore
* all other reference from same snapshot should have
* a larger generation.
*/
if ((root_objectid != btrfs_ref_root(leaf, ref_item)) ||
(parent_gen > 0 && parent_gen > ref_generation) ||
(ref_objectid >= BTRFS_FIRST_FREE_OBJECTID &&
ref_objectid != btrfs_ref_objectid(leaf, ref_item))) {
*ref_count = 2;
break;
}

*ref_count = 1;
if (*min_generation > ref_generation)
*min_generation = ref_generation;

path->slots[0]++;
}
ret = 0;
out:
btrfs_free_path(path);
return ret;
}

int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_key *key, u64 bytenr)
{
struct btrfs_root *old_root;
struct btrfs_path *path = NULL;
struct extent_buffer *eb;
struct btrfs_file_extent_item *item;
u64 ref_generation;
u64 min_generation;
u64 extent_start;
u32 ref_count;
int level;
int ret;

BUG_ON(trans == NULL);
BUG_ON(key->type != BTRFS_EXTENT_DATA_KEY);
ret = get_reference_status(root, bytenr, 0, key->objectid,
&min_generation, &ref_count);
if (ret)
return ret;

if (ref_count != 1)
return 1;

old_root = root->dirty_root->root;
ref_generation = old_root->root_key.offset;

/* all references are created in running transaction */
if (min_generation > ref_generation) {
ret = 0;
goto out;
}

path = btrfs_alloc_path();
if (!path) {
ret = -ENOMEM;
goto out;
}

path->skip_locking = 1;
/* if no item found, the extent is referenced by other snapshot */
ret = btrfs_search_slot(NULL, old_root, key, path, 0, 0);
if (ret)
goto out;

eb = path->nodes[0];
item = btrfs_item_ptr(eb, path->slots[0],
struct btrfs_file_extent_item);
if (btrfs_file_extent_type(eb, item) != BTRFS_FILE_EXTENT_REG ||
btrfs_file_extent_disk_bytenr(eb, item) != bytenr) {
ret = 1;
goto out;
}

for (level = BTRFS_MAX_LEVEL - 1; level >= -1; level--) {
if (level >= 0) {
eb = path->nodes[level];
if (!eb)
continue;
extent_start = eb->start;
} else
extent_start = bytenr;

ret = get_reference_status(root, extent_start, ref_generation,
0, &min_generation, &ref_count);
if (ret)
ref_root = btrfs_ref_root(leaf, ref_item);
if (ref_root != root->root_key.objectid &&
ref_root != BTRFS_TREE_LOG_OBJECTID) {
ret = 1;
goto out;

if (ref_count != 1) {
}
if (btrfs_ref_generation(leaf, ref_item) <= last_snapshot) {
ret = 1;
goto out;
}
if (level >= 0)
ref_generation = btrfs_header_generation(eb);

path->slots[0]++;
}
ret = 0;
out:
if (path)
btrfs_free_path(path);
btrfs_free_path(path);
return ret;
}

Expand Down
Loading

0 comments on commit e995f07

Please sign in to comment.