diff options
Diffstat (limited to 'fs/btrfs/file.c')
| -rw-r--r-- | fs/btrfs/file.c | 28 | 
1 files changed, 16 insertions, 12 deletions
| diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 5842423f8f47..fea31a4a6e36 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2070,7 +2070,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)  	}  	trans->sync = true; -	btrfs_init_log_ctx(&ctx); +	btrfs_init_log_ctx(&ctx, inode);  	ret = btrfs_log_dentry_safe(trans, root, dentry, start, end, &ctx);  	if (ret < 0) { @@ -2675,6 +2675,7 @@ static long btrfs_fallocate(struct file *file, int mode,  	alloc_start = round_down(offset, blocksize);  	alloc_end = round_up(offset + len, blocksize); +	cur_offset = alloc_start;  	/* Make sure we aren't being give some crap mode */  	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) @@ -2767,7 +2768,6 @@ static long btrfs_fallocate(struct file *file, int mode,  	/* First, check if we exceed the qgroup limit */  	INIT_LIST_HEAD(&reserve_list); -	cur_offset = alloc_start;  	while (1) {  		em = btrfs_get_extent(inode, NULL, 0, cur_offset,  				      alloc_end - cur_offset, 0); @@ -2794,6 +2794,14 @@ static long btrfs_fallocate(struct file *file, int mode,  					last_byte - cur_offset);  			if (ret < 0)  				break; +		} else { +			/* +			 * Do not need to reserve unwritten extent for this +			 * range, free reserved data space first, otherwise +			 * it'll result in false ENOSPC error. +			 */ +			btrfs_free_reserved_data_space(inode, cur_offset, +				last_byte - cur_offset);  		}  		free_extent_map(em);  		cur_offset = last_byte; @@ -2811,6 +2819,9 @@ static long btrfs_fallocate(struct file *file, int mode,  					range->start,  					range->len, 1 << inode->i_blkbits,  					offset + len, &alloc_hint); +		else +			btrfs_free_reserved_data_space(inode, range->start, +						       range->len);  		list_del(&range->list);  		kfree(range);  	} @@ -2845,18 +2856,11 @@ out_unlock:  	unlock_extent_cached(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,  			     &cached_state, GFP_KERNEL);  out: -	/* -	 * As we waited the extent range, the data_rsv_map must be empty -	 * in the range, as written data range will be released from it. -	 * And for prealloacted extent, it will also be released when -	 * its metadata is written. -	 * So this is completely used as cleanup. -	 */ -	btrfs_qgroup_free_data(inode, alloc_start, alloc_end - alloc_start);  	inode_unlock(inode);  	/* Let go of our reservation. */ -	btrfs_free_reserved_data_space(inode, alloc_start, -				       alloc_end - alloc_start); +	if (ret != 0) +		btrfs_free_reserved_data_space(inode, alloc_start, +				       alloc_end - cur_offset);  	return ret;  } |