Re: xfs_alloc_file_space() rounds len independently of offset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 26.09.19 14:59, Brian Foster wrote:
> On Thu, Sep 26, 2019 at 12:57:49PM +0200, Max Reitz wrote:
>> Hi,
>>
>> I’ve noticed that fallocating some range on XFS sometimes does not
>> include the last block covered by the range, when the start offset is
>> unaligned.
>>
>> (Tested on 5.3.0-gf41def397.)
>>
>> This happens whenever ceil((offset + len) / block_size) - floor(offset /
>> block_size) > ceil(len / block_size), for example:
>>
>> Let block_size be 4096.  Then (on XFS):
>>
>> $ fallocate -o 2048 -l 4096 foo   # Range [2048, 6144)
>> $ xfs_bmap foo
>> foo:
>>         0: [0..7]: 80..87
>>         1: [8..15]: hole
>>
>> There should not be a hole there.  Both of the first two blocks should
>> be allocated.  XFS will do that if I just let the range start one byte
>> sooner and increase the length by one byte:
>>
>> $ rm -f foo
>> $ fallocate -o 2047 -l 4097 foo   # Range [2047, 6144)
>> $ xfs_bmap foo
>> foo:
>>         0: [0..15]: 88..103
>>
>>
>> (See [1] for a more extensive reasoning why this is a bug.)
>>
>>
>> The problem is (as far as I can see) that xfs_alloc_file_space() rounds
>> count (which equals len) independently of the offset.  So in the
>> examples above, 4096 is rounded to one block and 4097 is rounded to two;
>> even though the first example actually touches two blocks because of the
>> misaligned offset.
>>
>> Therefore, this should fix the problem (and does fix it for me):
>>
>> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
>> index 0910cb75b..4f4437030 100644
>> --- a/fs/xfs/xfs_bmap_util.c
>> +++ b/fs/xfs/xfs_bmap_util.c
>> @@ -864,6 +864,7 @@ xfs_alloc_file_space(
>>  	xfs_filblks_t		allocatesize_fsb;
>>  	xfs_extlen_t		extsz, temp;
>>  	xfs_fileoff_t		startoffset_fsb;
>> +	xfs_fileoff_t		endoffset_fsb;
>>  	int			nimaps;
>>  	int			quota_flag;
>>  	int			rt;
>> @@ -891,7 +892,8 @@ xfs_alloc_file_space(
>>  	imapp = &imaps[0];
>>  	nimaps = 1;
>>  	startoffset_fsb	= XFS_B_TO_FSBT(mp, offset);
>> -	allocatesize_fsb = XFS_B_TO_FSB(mp, count);
>> +	endoffset_fsb = XFS_B_TO_FSB(mp, offset + count);
>> +	allocatesize_fsb = endoffset_fsb - startoffset_fsb;
>>
>>  	/*
>>  	 * Allocate file space until done or until there is an error
>>
> 
> That looks like a reasonable fix to me and it's in the spirit of how
> xfs_free_file_space() works as well (outside of the obvious difference
> in how unaligned boundary blocks are handled). Care to send a proper
> patch?

I’ve never sent a kernel patch before, but I’ll give it a go.

Max

Attachment: signature.asc
Description: OpenPGP digital signature


[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux