Commit 5a1d7843 authored by Jan Schmidt's avatar Jan Schmidt Committed by Chris Mason

btrfs: improved readablity for add_inode_ref

Moved part of the code into a sub function and replaced most of the gotos
by ifs, hoping that it will be easier to read now.
Signed-off-by: default avatarJan Schmidt <list.btrfs@jan-o-sch.net>
Signed-off-by: default avatarMark Fasheh <mfasheh@suse.de>
parent 0aa4a17d
...@@ -785,76 +785,18 @@ static noinline int backref_in_log(struct btrfs_root *log, ...@@ -785,76 +785,18 @@ static noinline int backref_in_log(struct btrfs_root *log,
return match; return match;
} }
static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
/*
* replay one inode back reference item found in the log tree.
* eb, slot and key refer to the buffer and key found in the log tree.
* root is the destination we are replaying into, and path is for temp
* use by this function. (it should be released on return).
*/
static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct btrfs_root *log,
struct btrfs_path *path, struct btrfs_path *path,
struct extent_buffer *eb, int slot, struct btrfs_root *log_root,
struct btrfs_key *key) struct inode *dir, struct inode *inode,
struct btrfs_key *key,
struct extent_buffer *eb,
struct btrfs_inode_ref *ref,
char *name, int namelen, int *search_done)
{ {
struct btrfs_inode_ref *ref;
struct btrfs_dir_item *di;
struct inode *dir;
struct inode *inode;
unsigned long ref_ptr;
unsigned long ref_end;
char *name;
int namelen;
int ret; int ret;
int search_done = 0; struct btrfs_dir_item *di;
/*
* it is possible that we didn't log all the parent directories
* for a given inode. If we don't find the dir, just don't
* copy the back ref in. The link count fixup code will take
* care of the rest
*/
dir = read_one_inode(root, key->offset);
if (!dir)
return -ENOENT;
inode = read_one_inode(root, key->objectid);
if (!inode) {
iput(dir);
return -EIO;
}
ref_ptr = btrfs_item_ptr_offset(eb, slot);
ref_end = ref_ptr + btrfs_item_size_nr(eb, slot);
again:
ref = (struct btrfs_inode_ref *)ref_ptr;
namelen = btrfs_inode_ref_name_len(eb, ref);
name = kmalloc(namelen, GFP_NOFS);
BUG_ON(!name);
read_extent_buffer(eb, name, (unsigned long)(ref + 1), namelen);
/* if we already have a perfect match, we're done */
if (inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode),
btrfs_inode_ref_index(eb, ref),
name, namelen)) {
goto out;
}
/*
* look for a conflicting back reference in the metadata.
* if we find one we have to unlink that name of the file
* before we add our new link. Later on, we overwrite any
* existing back reference, and we don't want to create
* dangling pointers in the directory.
*/
if (search_done)
goto insert;
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) {
...@@ -869,7 +811,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, ...@@ -869,7 +811,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
* if so, just jump out, we're done * if so, just jump out, we're done
*/ */
if (key->objectid == key->offset) if (key->objectid == key->offset)
goto out_nowrite; return 1;
/* check all the names in this back reference to see /* check all the names in this back reference to see
* if they are in the log. if so, we allow them to stay * if they are in the log. if so, we allow them to stay
...@@ -888,7 +830,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, ...@@ -888,7 +830,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
(unsigned long)(victim_ref + 1), (unsigned long)(victim_ref + 1),
victim_name_len); victim_name_len);
if (!backref_in_log(log, key, victim_name, if (!backref_in_log(log_root, key, victim_name,
victim_name_len)) { victim_name_len)) {
btrfs_inc_nlink(inode); btrfs_inc_nlink(inode);
btrfs_release_path(path); btrfs_release_path(path);
...@@ -907,7 +849,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, ...@@ -907,7 +849,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
* NOTE: we have searched root tree and checked the * NOTE: we have searched root tree and checked the
* coresponding ref, it does not need to check again. * coresponding ref, it does not need to check again.
*/ */
search_done = 1; *search_done = 1;
} }
btrfs_release_path(path); btrfs_release_path(path);
...@@ -930,25 +872,99 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, ...@@ -930,25 +872,99 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
} }
btrfs_release_path(path); btrfs_release_path(path);
insert: return 0;
}
/*
* replay one inode back reference item found in the log tree.
* eb, slot and key refer to the buffer and key found in the log tree.
* root is the destination we are replaying into, and path is for temp
* use by this function. (it should be released on return).
*/
static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_root *log,
struct btrfs_path *path,
struct extent_buffer *eb, int slot,
struct btrfs_key *key)
{
struct btrfs_inode_ref *ref;
struct inode *dir;
struct inode *inode;
unsigned long ref_ptr;
unsigned long ref_end;
char *name;
int namelen;
int ret;
int search_done = 0;
/*
* it is possible that we didn't log all the parent directories
* for a given inode. If we don't find the dir, just don't
* copy the back ref in. The link count fixup code will take
* care of the rest
*/
dir = read_one_inode(root, key->offset);
if (!dir)
return -ENOENT;
inode = read_one_inode(root, key->objectid);
if (!inode) {
iput(dir);
return -EIO;
}
ref_ptr = btrfs_item_ptr_offset(eb, slot);
ref_end = ref_ptr + btrfs_item_size_nr(eb, slot);
while (ref_ptr < ref_end) {
ref = (struct btrfs_inode_ref *)ref_ptr;
namelen = btrfs_inode_ref_name_len(eb, ref);
name = kmalloc(namelen, GFP_NOFS);
BUG_ON(!name);
read_extent_buffer(eb, name, (unsigned long)(ref + 1), namelen);
/* if we already have a perfect match, we're done */
if (!inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode),
btrfs_inode_ref_index(eb, ref),
name, namelen)) {
/*
* look for a conflicting back reference in the
* metadata. if we find one we have to unlink that name
* of the file before we add our new link. Later on, we
* overwrite any existing back reference, and we don't
* want to create dangling pointers in the directory.
*/
if (!search_done) {
ret = __add_inode_ref(trans, root, path, log,
dir, inode, key, eb, ref,
name, namelen,
&search_done);
if (ret == 1)
goto out;
BUG_ON(ret);
}
/* insert our name */ /* insert our name */
ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, ret = btrfs_add_link(trans, dir, inode, name, namelen,
btrfs_inode_ref_index(eb, ref)); 0, btrfs_inode_ref_index(eb, ref));
BUG_ON(ret); BUG_ON(ret);
btrfs_update_inode(trans, root, inode); btrfs_update_inode(trans, root, inode);
}
out:
ref_ptr = (unsigned long)(ref + 1) + namelen; ref_ptr = (unsigned long)(ref + 1) + namelen;
kfree(name); kfree(name);
if (ref_ptr < ref_end) }
goto again;
/* finally write the back reference in the inode */ /* finally write the back reference in the inode */
ret = overwrite_item(trans, root, path, eb, slot, key); ret = overwrite_item(trans, root, path, eb, slot, key);
BUG_ON(ret); BUG_ON(ret);
out_nowrite: out:
btrfs_release_path(path); btrfs_release_path(path);
iput(dir); iput(dir);
iput(inode); iput(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