diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
| -rw-r--r-- | fs/btrfs/ordered-data.c | 56 | 
1 files changed, 31 insertions, 25 deletions
| diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 041c3326d109..9a46878ba60f 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -432,7 +432,7 @@ out:  }  /* Needs to either be called under a log transaction or the log_mutex */ -void btrfs_get_logged_extents(struct inode *inode, +void btrfs_get_logged_extents(struct btrfs_inode *inode,  			      struct list_head *logged_list,  			      const loff_t start,  			      const loff_t end) @@ -442,7 +442,7 @@ void btrfs_get_logged_extents(struct inode *inode,  	struct rb_node *n;  	struct rb_node *prev; -	tree = &BTRFS_I(inode)->ordered_tree; +	tree = &inode->ordered_tree;  	spin_lock_irq(&tree->lock);  	n = __tree_search(&tree->tree, end, &prev);  	if (!n) @@ -879,15 +879,14 @@ out:  /* Since the DIO code tries to lock a wide area we need to look for any ordered   * extents that exist in the range, rather than just the start of the range.   */ -struct btrfs_ordered_extent *btrfs_lookup_ordered_range(struct inode *inode, -							u64 file_offset, -							u64 len) +struct btrfs_ordered_extent *btrfs_lookup_ordered_range( +		struct btrfs_inode *inode, u64 file_offset, u64 len)  {  	struct btrfs_ordered_inode_tree *tree;  	struct rb_node *node;  	struct btrfs_ordered_extent *entry = NULL; -	tree = &BTRFS_I(inode)->ordered_tree; +	tree = &inode->ordered_tree;  	spin_lock_irq(&tree->lock);  	node = tree_search(tree, file_offset);  	if (!node) { @@ -923,7 +922,7 @@ bool btrfs_have_ordered_extents_in_range(struct inode *inode,  {  	struct btrfs_ordered_extent *oe; -	oe = btrfs_lookup_ordered_range(inode, file_offset, len); +	oe = btrfs_lookup_ordered_range(BTRFS_I(inode), file_offset, len);  	if (oe) {  		btrfs_put_ordered_extent(oe);  		return true; @@ -984,8 +983,18 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,  	}  	disk_i_size = BTRFS_I(inode)->disk_i_size; -	/* truncate file */ -	if (disk_i_size > i_size) { +	/* +	 * truncate file. +	 * If ordered is not NULL, then this is called from endio and +	 * disk_i_size will be updated by either truncate itself or any +	 * in-flight IOs which are inside the disk_i_size. +	 * +	 * Because btrfs_setsize() may set i_size with disk_i_size if truncate +	 * fails somehow, we need to make sure we have a precise disk_i_size by +	 * updating it as usual. +	 * +	 */ +	if (!ordered && disk_i_size > i_size) {  		BTRFS_I(inode)->disk_i_size = orig_offset;  		ret = 0;  		goto out; @@ -1032,25 +1041,22 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,  		/* We treat this entry as if it doesn't exist */  		if (test_bit(BTRFS_ORDERED_UPDATED_ISIZE, &test->flags))  			continue; -		if (test->file_offset + test->len <= disk_i_size) + +		if (entry_end(test) <= disk_i_size)  			break;  		if (test->file_offset >= i_size)  			break; -		if (entry_end(test) > disk_i_size) { -			/* -			 * we don't update disk_i_size now, so record this -			 * undealt i_size. Or we will not know the real -			 * i_size. -			 */ -			if (test->outstanding_isize < offset) -				test->outstanding_isize = offset; -			if (ordered && -			    ordered->outstanding_isize > -			    test->outstanding_isize) -				test->outstanding_isize = -						ordered->outstanding_isize; -			goto out; -		} + +		/* +		 * We don't update disk_i_size now, so record this undealt +		 * i_size. Or we will not know the real i_size. +		 */ +		if (test->outstanding_isize < offset) +			test->outstanding_isize = offset; +		if (ordered && +		    ordered->outstanding_isize > test->outstanding_isize) +			test->outstanding_isize = ordered->outstanding_isize; +		goto out;  	}  	new_i_size = min_t(u64, offset, i_size); | 
