diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 148 | 
1 files changed, 76 insertions, 72 deletions
| diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 79f057c0619a..744553c83fe2 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -26,7 +26,6 @@  #include "locking.h"  #include "print-tree.h"  #include "backref.h" -#include "compat.h"  #include "tree-log.h"  #include "hash.h" @@ -936,7 +935,7 @@ again:  					    parent_objectid,  					    victim_name,  					    victim_name_len)) { -				btrfs_inc_nlink(inode); +				inc_nlink(inode);  				btrfs_release_path(path);  				ret = btrfs_unlink_inode(trans, root, dir, @@ -1006,7 +1005,7 @@ again:  				victim_parent = read_one_inode(root,  							       parent_objectid);  				if (victim_parent) { -					btrfs_inc_nlink(inode); +					inc_nlink(inode);  					btrfs_release_path(path);  					ret = btrfs_unlink_inode(trans, root, @@ -1113,11 +1112,11 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,  				  struct extent_buffer *eb, int slot,  				  struct btrfs_key *key)  { -	struct inode *dir; -	struct inode *inode; +	struct inode *dir = NULL; +	struct inode *inode = NULL;  	unsigned long ref_ptr;  	unsigned long ref_end; -	char *name; +	char *name = NULL;  	int namelen;  	int ret;  	int search_done = 0; @@ -1150,13 +1149,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,  	 * care of the rest  	 */  	dir = read_one_inode(root, parent_objectid); -	if (!dir) -		return -ENOENT; +	if (!dir) { +		ret = -ENOENT; +		goto out; +	}  	inode = read_one_inode(root, inode_objectid);  	if (!inode) { -		iput(dir); -		return -EIO; +		ret = -EIO; +		goto out;  	}  	while (ref_ptr < ref_end) { @@ -1169,14 +1170,16 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,  			 */  			if (!dir)  				dir = read_one_inode(root, parent_objectid); -			if (!dir) -				return -ENOENT; +			if (!dir) { +				ret = -ENOENT; +				goto out; +			}  		} else {  			ret = ref_get_fields(eb, ref_ptr, &namelen, &name,  					     &ref_index);  		}  		if (ret) -			return ret; +			goto out;  		/* if we already have a perfect match, we're done */  		if (!inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode), @@ -1196,12 +1199,11 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,  						      parent_objectid,  						      ref_index, name, namelen,  						      &search_done); -				if (ret == 1) { -					ret = 0; +				if (ret) { +					if (ret == 1) +						ret = 0;  					goto out;  				} -				if (ret) -					goto out;  			}  			/* insert our name */ @@ -1215,6 +1217,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,  		ref_ptr = (unsigned long)(ref_ptr + ref_struct_size) + namelen;  		kfree(name); +		name = NULL;  		if (log_ref_ver) {  			iput(dir);  			dir = NULL; @@ -1225,6 +1228,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,  	ret = overwrite_item(trans, root, path, eb, slot, key);  out:  	btrfs_release_path(path); +	kfree(name);  	iput(dir);  	iput(inode);  	return ret; @@ -1307,6 +1311,7 @@ static int count_inode_refs(struct btrfs_root *root,  				break;  			path->slots[0]--;  		} +process_slot:  		btrfs_item_key_to_cpu(path->nodes[0], &key,  				      path->slots[0]);  		if (key.objectid != ino || @@ -1327,6 +1332,10 @@ static int count_inode_refs(struct btrfs_root *root,  		if (key.offset == 0)  			break; +		if (path->slots[0] > 0) { +			path->slots[0]--; +			goto process_slot; +		}  		key.offset--;  		btrfs_release_path(path);  	} @@ -1480,7 +1489,7 @@ static noinline int link_to_fixup_dir(struct btrfs_trans_handle *trans,  		if (!inode->i_nlink)  			set_nlink(inode, 1);  		else -			btrfs_inc_nlink(inode); +			inc_nlink(inode);  		ret = btrfs_update_inode(trans, root, inode);  	} else if (ret == -EEXIST) {  		ret = 0; @@ -1823,7 +1832,7 @@ again:  						     dir_key->offset,  						     name, name_len, 0);  		} -		if (IS_ERR_OR_NULL(log_di)) { +		if (!log_di || (IS_ERR(log_di) && PTR_ERR(log_di) == -ENOENT)) {  			btrfs_dir_item_key_to_cpu(eb, di, &location);  			btrfs_release_path(path);  			btrfs_release_path(log_path); @@ -1841,7 +1850,7 @@ again:  				goto out;  			} -			btrfs_inc_nlink(inode); +			inc_nlink(inode);  			ret = btrfs_unlink_inode(trans, root, dir, inode,  						 name, name_len);  			if (!ret) @@ -1860,6 +1869,9 @@ again:  				goto again;  			ret = 0;  			goto out; +		} else if (IS_ERR(log_di)) { +			kfree(name); +			return PTR_ERR(log_di);  		}  		btrfs_release_path(log_path);  		kfree(name); @@ -2118,8 +2130,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,  		WARN_ON(*level >= BTRFS_MAX_LEVEL);  		cur = path->nodes[*level]; -		if (btrfs_header_level(cur) != *level) -			WARN_ON(1); +		WARN_ON(btrfs_header_level(cur) != *level);  		if (path->slots[*level] >=  		    btrfs_header_nritems(cur)) @@ -2151,11 +2162,13 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,  					return ret;  				} -				btrfs_tree_lock(next); -				btrfs_set_lock_blocking(next); -				clean_tree_block(trans, root, next); -				btrfs_wait_tree_block_writeback(next); -				btrfs_tree_unlock(next); +				if (trans) { +					btrfs_tree_lock(next); +					btrfs_set_lock_blocking(next); +					clean_tree_block(trans, root, next); +					btrfs_wait_tree_block_writeback(next); +					btrfs_tree_unlock(next); +				}  				WARN_ON(root_owner !=  					BTRFS_TREE_LOG_OBJECTID); @@ -2227,11 +2240,13 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,  				next = path->nodes[*level]; -				btrfs_tree_lock(next); -				btrfs_set_lock_blocking(next); -				clean_tree_block(trans, root, next); -				btrfs_wait_tree_block_writeback(next); -				btrfs_tree_unlock(next); +				if (trans) { +					btrfs_tree_lock(next); +					btrfs_set_lock_blocking(next); +					clean_tree_block(trans, root, next); +					btrfs_wait_tree_block_writeback(next); +					btrfs_tree_unlock(next); +				}  				WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID);  				ret = btrfs_free_and_pin_reserved_extent(root, @@ -2301,11 +2316,13 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,  			next = path->nodes[orig_level]; -			btrfs_tree_lock(next); -			btrfs_set_lock_blocking(next); -			clean_tree_block(trans, log, next); -			btrfs_wait_tree_block_writeback(next); -			btrfs_tree_unlock(next); +			if (trans) { +				btrfs_tree_lock(next); +				btrfs_set_lock_blocking(next); +				clean_tree_block(trans, log, next); +				btrfs_wait_tree_block_writeback(next); +				btrfs_tree_unlock(next); +			}  			WARN_ON(log->root_key.objectid !=  				BTRFS_TREE_LOG_OBJECTID); @@ -2571,9 +2588,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,  	 * the running transaction open, so a full commit can't hop  	 * in and cause problems either.  	 */ -	btrfs_scrub_pause_super(root);  	ret = write_ctree_super(trans, root->fs_info->tree_root, 1); -	btrfs_scrub_continue_super(root);  	if (ret) {  		btrfs_abort_transaction(trans, root, ret);  		goto out_wake_log_root; @@ -2608,13 +2623,10 @@ static void free_log_tree(struct btrfs_trans_handle *trans,  		.process_func = process_one_buffer  	}; -	if (trans) { -		ret = walk_log_tree(trans, log, &wc); - -		/* I don't think this can happen but just in case */ -		if (ret) -			btrfs_abort_transaction(trans, log, ret); -	} +	ret = walk_log_tree(trans, log, &wc); +	/* I don't think this can happen but just in case */ +	if (ret) +		btrfs_abort_transaction(trans, log, ret);  	while (1) {  		ret = find_first_extent_bit(&log->dirty_log_pages, @@ -2867,7 +2879,6 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,  			  u64 min_offset, u64 *last_offset_ret)  {  	struct btrfs_key min_key; -	struct btrfs_key max_key;  	struct btrfs_root *log = root->log_root;  	struct extent_buffer *src;  	int err = 0; @@ -2879,9 +2890,6 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,  	u64 ino = btrfs_ino(inode);  	log = root->log_root; -	max_key.objectid = ino; -	max_key.offset = (u64)-1; -	max_key.type = key_type;  	min_key.objectid = ino;  	min_key.type = key_type; @@ -2889,8 +2897,7 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,  	path->keep_locks = 1; -	ret = btrfs_search_forward(root, &min_key, &max_key, -				   path, trans->transid); +	ret = btrfs_search_forward(root, &min_key, path, trans->transid);  	/*  	 * we didn't find anything from this transaction, see if there @@ -2943,10 +2950,8 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,  	/* find the first key from this transaction again */  	ret = btrfs_search_slot(NULL, root, &min_key, path, 0, 0); -	if (ret != 0) { -		WARN_ON(1); +	if (WARN_ON(ret != 0))  		goto done; -	}  	/*  	 * we have a block from this transaction, log every item in it @@ -3172,11 +3177,10 @@ static int log_inode_item(struct btrfs_trans_handle *trans,  			  struct inode *inode)  {  	struct btrfs_inode_item *inode_item; -	struct btrfs_key key;  	int ret; -	memcpy(&key, &BTRFS_I(inode)->location, sizeof(key)); -	ret = btrfs_insert_empty_item(trans, log, path, &key, +	ret = btrfs_insert_empty_item(trans, log, path, +				      &BTRFS_I(inode)->location,  				      sizeof(*inode_item));  	if (ret && ret != -EEXIST)  		return ret; @@ -3375,7 +3379,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans,  		btrfs_set_token_file_extent_type(leaf, fi,  						 BTRFS_FILE_EXTENT_REG,  						 &token); -		if (em->block_start == 0) +		if (em->block_start == EXTENT_MAP_HOLE)  			skip_csum = true;  	} @@ -3417,11 +3421,6 @@ static int log_one_extent(struct btrfs_trans_handle *trans,  	if (skip_csum)  		return 0; -	if (em->compress_type) { -		csum_offset = 0; -		csum_len = block_len; -	} -  	/*  	 * First check and see if our csums are on our outstanding ordered  	 * extents. @@ -3505,8 +3504,13 @@ unlocked:  	if (!mod_len || ret)  		return ret; -	csum_offset = mod_start - em->start; -	csum_len = mod_len; +	if (em->compress_type) { +		csum_offset = 0; +		csum_len = block_len; +	} else { +		csum_offset = mod_start - em->start; +		csum_len = mod_len; +	}  	/* block start is already adjusted for the file extent offset. */  	ret = btrfs_lookup_csums_range(log->fs_info->csum_root, @@ -3719,7 +3723,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,  	while (1) {  		ins_nr = 0; -		ret = btrfs_search_forward(root, &min_key, &max_key, +		ret = btrfs_search_forward(root, &min_key,  					   path, trans->transid);  		if (ret != 0)  			break; @@ -3769,14 +3773,14 @@ next_slot:  		}  		btrfs_release_path(path); -		if (min_key.offset < (u64)-1) +		if (min_key.offset < (u64)-1) {  			min_key.offset++; -		else if (min_key.type < (u8)-1) +		} else if (min_key.type < max_key.type) {  			min_key.type++; -		else if (min_key.objectid < (u64)-1) -			min_key.objectid++; -		else +			min_key.offset = 0; +		} else {  			break; +		}  	}  	if (ins_nr) {  		ret = copy_items(trans, inode, dst_path, src, ins_start_slot, | 
