diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 144 | 
1 files changed, 6 insertions, 138 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 592aa654b5f..b069fafbc3d 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3209,115 +3209,6 @@ static int extent_cmp(void *priv, struct list_head *a, struct list_head *b)  	return 0;  } -static int drop_adjacent_extents(struct btrfs_trans_handle *trans, -				 struct btrfs_root *root, struct inode *inode, -				 struct extent_map *em, -				 struct btrfs_path *path) -{ -	struct btrfs_file_extent_item *fi; -	struct extent_buffer *leaf; -	struct btrfs_key key, new_key; -	struct btrfs_map_token token; -	u64 extent_end; -	u64 extent_offset = 0; -	int extent_type; -	int del_slot = 0; -	int del_nr = 0; -	int ret = 0; - -	while (1) { -		btrfs_init_map_token(&token); -		leaf = path->nodes[0]; -		path->slots[0]++; -		if (path->slots[0] >= btrfs_header_nritems(leaf)) { -			if (del_nr) { -				ret = btrfs_del_items(trans, root, path, -						      del_slot, del_nr); -				if (ret) -					return ret; -				del_nr = 0; -			} - -			ret = btrfs_next_leaf_write(trans, root, path, 1); -			if (ret < 0) -				return ret; -			if (ret > 0) -				return 0; -			leaf = path->nodes[0]; -		} - -		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); -		if (key.objectid != btrfs_ino(inode) || -		    key.type != BTRFS_EXTENT_DATA_KEY || -		    key.offset >= em->start + em->len) -			break; - -		fi = btrfs_item_ptr(leaf, path->slots[0], -				    struct btrfs_file_extent_item); -		extent_type = btrfs_token_file_extent_type(leaf, fi, &token); -		if (extent_type == BTRFS_FILE_EXTENT_REG || -		    extent_type == BTRFS_FILE_EXTENT_PREALLOC) { -			extent_offset = btrfs_token_file_extent_offset(leaf, -								fi, &token); -			extent_end = key.offset + -				btrfs_token_file_extent_num_bytes(leaf, fi, -								  &token); -		} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { -			extent_end = key.offset + -				btrfs_file_extent_inline_len(leaf, fi); -		} else { -			BUG(); -		} - -		if (extent_end <= em->len + em->start) { -			if (!del_nr) { -				del_slot = path->slots[0]; -			} -			del_nr++; -			continue; -		} - -		/* -		 * Ok so we'll ignore previous items if we log a new extent, -		 * which can lead to overlapping extents, so if we have an -		 * existing extent we want to adjust we _have_ to check the next -		 * guy to make sure we even need this extent anymore, this keeps -		 * us from panicing in set_item_key_safe. -		 */ -		if (path->slots[0] < btrfs_header_nritems(leaf) - 1) { -			struct btrfs_key tmp_key; - -			btrfs_item_key_to_cpu(leaf, &tmp_key, -					      path->slots[0] + 1); -			if (tmp_key.objectid == btrfs_ino(inode) && -			    tmp_key.type == BTRFS_EXTENT_DATA_KEY && -			    tmp_key.offset <= em->start + em->len) { -				if (!del_nr) -					del_slot = path->slots[0]; -				del_nr++; -				continue; -			} -		} - -		BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); -		memcpy(&new_key, &key, sizeof(new_key)); -		new_key.offset = em->start + em->len; -		btrfs_set_item_key_safe(trans, root, path, &new_key); -		extent_offset += em->start + em->len - key.offset; -		btrfs_set_token_file_extent_offset(leaf, fi, extent_offset, -						   &token); -		btrfs_set_token_file_extent_num_bytes(leaf, fi, extent_end - -						      (em->start + em->len), -						      &token); -		btrfs_mark_buffer_dirty(leaf); -	} - -	if (del_nr) -		ret = btrfs_del_items(trans, root, path, del_slot, del_nr); - -	return ret; -} -  static int log_one_extent(struct btrfs_trans_handle *trans,  			  struct inode *inode, struct btrfs_root *root,  			  struct extent_map *em, struct btrfs_path *path) @@ -3339,39 +3230,24 @@ static int log_one_extent(struct btrfs_trans_handle *trans,  	int index = log->log_transid % 2;  	bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; -insert: +	ret = __btrfs_drop_extents(trans, log, inode, path, em->start, +				   em->start + em->len, NULL, 0); +	if (ret) +		return ret; +  	INIT_LIST_HEAD(&ordered_sums);  	btrfs_init_map_token(&token);  	key.objectid = btrfs_ino(inode);  	key.type = BTRFS_EXTENT_DATA_KEY;  	key.offset = em->start; -	path->really_keep_locks = 1;  	ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*fi)); -	if (ret && ret != -EEXIST) { -		path->really_keep_locks = 0; +	if (ret)  		return ret; -	}  	leaf = path->nodes[0];  	fi = btrfs_item_ptr(leaf, path->slots[0],  			    struct btrfs_file_extent_item); -	/* -	 * If we are overwriting an inline extent with a real one then we need -	 * to just delete the inline extent as it may not be large enough to -	 * have the entire file_extent_item. -	 */ -	if (ret && btrfs_token_file_extent_type(leaf, fi, &token) == -	    BTRFS_FILE_EXTENT_INLINE) { -		ret = btrfs_del_item(trans, log, path); -		btrfs_release_path(path); -		if (ret) { -			path->really_keep_locks = 0; -			return ret; -		} -		goto insert; -	} -  	btrfs_set_token_file_extent_generation(leaf, fi, em->generation,  					       &token);  	if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) { @@ -3417,15 +3293,7 @@ insert:  	btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token);  	btrfs_mark_buffer_dirty(leaf); -	/* -	 * Have to check the extent to the right of us to make sure it doesn't -	 * fall in our current range.  We're ok if the previous extent is in our -	 * range since the recovery stuff will run us in key order and thus just -	 * drop the part we overwrote. -	 */ -	ret = drop_adjacent_extents(trans, log, inode, em, path);  	btrfs_release_path(path); -	path->really_keep_locks = 0;  	if (ret) {  		return ret;  	}  |