diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 46 | 
1 files changed, 36 insertions, 10 deletions
| diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 4ce8a9f41d1..786639fca06 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -799,14 +799,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,  				  struct extent_buffer *eb, int slot,  				  struct btrfs_key *key)  { -	struct inode *dir; -	int ret;  	struct btrfs_inode_ref *ref; +	struct btrfs_dir_item *di; +	struct inode *dir;  	struct inode *inode; -	char *name; -	int namelen;  	unsigned long ref_ptr;  	unsigned long ref_end; +	char *name; +	int namelen; +	int ret;  	int search_done = 0;  	/* @@ -909,6 +910,25 @@ again:  	}  	btrfs_release_path(path); +	/* look for a conflicting sequence number */ +	di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), +					 btrfs_inode_ref_index(eb, ref), +					 name, namelen, 0); +	if (di && !IS_ERR(di)) { +		ret = drop_one_dir_item(trans, root, path, dir, di); +		BUG_ON(ret); +	} +	btrfs_release_path(path); + +	/* look for a conflicing name */ +	di = btrfs_lookup_dir_item(trans, root, path, btrfs_ino(dir), +				   name, namelen, 0); +	if (di && !IS_ERR(di)) { +		ret = drop_one_dir_item(trans, root, path, dir, di); +		BUG_ON(ret); +	} +	btrfs_release_path(path); +  insert:  	/* insert our name */  	ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, @@ -1617,7 +1637,8 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,  		return 0;  	path = btrfs_alloc_path(); -	BUG_ON(!path); +	if (!path) +		return -ENOMEM;  	nritems = btrfs_header_nritems(eb);  	for (i = 0; i < nritems; i++) { @@ -1723,15 +1744,17 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,  			return -ENOMEM;  		if (*level == 1) { -			wc->process_func(root, next, wc, ptr_gen); +			ret = wc->process_func(root, next, wc, ptr_gen); +			if (ret) +				return ret;  			path->slots[*level]++;  			if (wc->free) {  				btrfs_read_buffer(next, ptr_gen);  				btrfs_tree_lock(next); -				clean_tree_block(trans, root, next);  				btrfs_set_lock_blocking(next); +				clean_tree_block(trans, root, next);  				btrfs_wait_tree_block_writeback(next);  				btrfs_tree_unlock(next); @@ -1788,16 +1811,19 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,  				parent = path->nodes[*level + 1];  			root_owner = btrfs_header_owner(parent); -			wc->process_func(root, path->nodes[*level], wc, +			ret = wc->process_func(root, path->nodes[*level], wc,  				 btrfs_header_generation(path->nodes[*level])); +			if (ret) +				return ret; +  			if (wc->free) {  				struct extent_buffer *next;  				next = path->nodes[*level];  				btrfs_tree_lock(next); -				clean_tree_block(trans, root, next);  				btrfs_set_lock_blocking(next); +				clean_tree_block(trans, root, next);  				btrfs_wait_tree_block_writeback(next);  				btrfs_tree_unlock(next); @@ -1864,8 +1890,8 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,  			next = path->nodes[orig_level];  			btrfs_tree_lock(next); -			clean_tree_block(trans, log, next);  			btrfs_set_lock_blocking(next); +			clean_tree_block(trans, log, next);  			btrfs_wait_tree_block_writeback(next);  			btrfs_tree_unlock(next); | 
