Re: [PATCH] block: fallocate: avoid false positive on collision detection

From: Jan Kara
Date: Thu Jan 07 2021 - 10:39:05 EST


On Thu 07-01-21 14:40:22, Maxim Levitsky wrote:
> Align start and end on page boundaries before calling
> invalidate_inode_pages2_range.
>
> This might allow us to miss a collision if the write and the discard were done
> to the same page and do overlap but it is still better than returning -EBUSY
> if those writes didn't overlap.
>
> Signed-off-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx>

Thanks for getting back to this and I'm sorry I didn't get to this earlier
myself! I actually think the fix should be different as we discussed with
Darrick. Attached patch should fix the issue for you (I'll also post it
formally for inclusion).

Honza

> ---
> fs/block_dev.c | 20 ++++++++++++++++----
> 1 file changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/fs/block_dev.c b/fs/block_dev.c
> index 9e84b1928b94..97f0d16661b5 100644
> --- a/fs/block_dev.c
> +++ b/fs/block_dev.c
> @@ -1970,6 +1970,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
> loff_t end = start + len - 1;
> loff_t isize;
> int error;
> + pgoff_t invalidate_first_page, invalidate_last_page;
>
> /* Fail if we don't recognize the flags. */
> if (mode & ~BLKDEV_FALLOC_FL_SUPPORTED)
> @@ -2020,12 +2021,23 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
>
> /*
> * Invalidate again; if someone wandered in and dirtied a page,
> - * the caller will be given -EBUSY. The third argument is
> - * inclusive, so the rounding here is safe.
> + * the caller will be given -EBUSY.
> + *
> + * If the start/end of the range is not page aligned, exclude the
> + * non aligned regions to avoid false positives.
> */
> + invalidate_first_page = DIV_ROUND_UP(start, PAGE_SIZE);
> + invalidate_last_page = end >> PAGE_SHIFT;
> +
> + if ((end + 1) & PAGE_MASK)
> + invalidate_last_page--;
> +
> + if (invalidate_last_page < invalidate_first_page)
> + return 0;
> +
> return invalidate_inode_pages2_range(bdev->bd_inode->i_mapping,
> - start >> PAGE_SHIFT,
> - end >> PAGE_SHIFT);
> + invalidate_first_page,
> + invalidate_last_page);
> }
>
> const struct file_operations def_blk_fops = {
> --
> 2.26.2
>
--
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR