mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 08:33:17 +02:00
zonefs fixes for 6.3-rc5
* Make sure to always invalidate the last page of an inode straddling
inode->i_size to avoid data inconsistencies with appended data when
the device zone write granularity does not match the page size.
* Do not propagate iomap -ENOBLK error to userspace and use -EBUSY
instead.
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQSRPv8tYSvhwAzJdzjdoc3SxdoYdgUCZCV+vgAKCRDdoc3SxdoY
dhtrAQCYLbuQPHM5WwO9oJPnKYGgDjOBQbcDC0hjTG3rLjquHgD+O16QHO02raDk
++C5sl6r22jK1m8GqOckfJ/wdESgCQM=
=Lmth
-----END PGP SIGNATURE-----
Merge tag 'zonefs-6.3-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs
Pull zonefs fixes from Damien Le Moal:
- Make sure to always invalidate the last page of an inode straddling
inode->i_size to avoid data inconsistencies with appended data when
the device zone write granularity does not match the page size.
- Do not propagate iomap -ENOBLK error to userspace and use -EBUSY
instead.
* tag 'zonefs-6.3-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs:
zonefs: Do not propagate iomap_dio_rw() ENOTBLK error to user space
zonefs: Always invalidate last cached page on append write
This commit is contained in:
commit
4ee772243a
|
|
@ -382,6 +382,7 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
|
|||
struct zonefs_zone *z = zonefs_inode_zone(inode);
|
||||
struct block_device *bdev = inode->i_sb->s_bdev;
|
||||
unsigned int max = bdev_max_zone_append_sectors(bdev);
|
||||
pgoff_t start, end;
|
||||
struct bio *bio;
|
||||
ssize_t size = 0;
|
||||
int nr_pages;
|
||||
|
|
@ -390,6 +391,19 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
|
|||
max = ALIGN_DOWN(max << SECTOR_SHIFT, inode->i_sb->s_blocksize);
|
||||
iov_iter_truncate(from, max);
|
||||
|
||||
/*
|
||||
* If the inode block size (zone write granularity) is smaller than the
|
||||
* page size, we may be appending data belonging to the last page of the
|
||||
* inode straddling inode->i_size, with that page already cached due to
|
||||
* a buffered read or readahead. So make sure to invalidate that page.
|
||||
* This will always be a no-op for the case where the block size is
|
||||
* equal to the page size.
|
||||
*/
|
||||
start = iocb->ki_pos >> PAGE_SHIFT;
|
||||
end = (iocb->ki_pos + iov_iter_count(from) - 1) >> PAGE_SHIFT;
|
||||
if (invalidate_inode_pages2_range(inode->i_mapping, start, end))
|
||||
return -EBUSY;
|
||||
|
||||
nr_pages = iov_iter_npages(from, BIO_MAX_VECS);
|
||||
if (!nr_pages)
|
||||
return 0;
|
||||
|
|
@ -567,11 +581,21 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
|
|||
append = sync;
|
||||
}
|
||||
|
||||
if (append)
|
||||
if (append) {
|
||||
ret = zonefs_file_dio_append(iocb, from);
|
||||
else
|
||||
} else {
|
||||
/*
|
||||
* iomap_dio_rw() may return ENOTBLK if there was an issue with
|
||||
* page invalidation. Overwrite that error code with EBUSY to
|
||||
* be consistent with zonefs_file_dio_append() return value for
|
||||
* similar issues.
|
||||
*/
|
||||
ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops,
|
||||
&zonefs_write_dio_ops, 0, NULL, 0);
|
||||
if (ret == -ENOTBLK)
|
||||
ret = -EBUSY;
|
||||
}
|
||||
|
||||
if (zonefs_zone_is_seq(z) &&
|
||||
(ret > 0 || ret == -EIOCBQUEUED)) {
|
||||
if (ret > 0)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user