mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 11:21:26 -04:00
xfs: factor out isize updates from xfs_dio_write_end_io
This is the only code needed for zoned inodes, so factor it out so we can move zoned inodes ioend to its own callback. Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
@@ -560,6 +560,42 @@ xfs_zoned_write_space_reserve(
|
||||
flags, ac);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to lock the test/set EOF update as we can be racing with
|
||||
* other IO completions here to update the EOF. Failing to serialise
|
||||
* here can result in EOF moving backwards and Bad Things Happen when
|
||||
* that occurs.
|
||||
*
|
||||
* As IO completion only ever extends EOF, we can do an unlocked check
|
||||
* here to avoid taking the spinlock. If we land within the current EOF,
|
||||
* then we do not need to do an extending update at all, and we don't
|
||||
* need to take the lock to check this. If we race with an update moving
|
||||
* EOF, then we'll either still be beyond EOF and need to take the lock,
|
||||
* or we'll be within EOF and we don't need to take it at all.
|
||||
*/
|
||||
static int
|
||||
xfs_dio_endio_set_isize(
|
||||
struct inode *inode,
|
||||
loff_t offset,
|
||||
ssize_t size)
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
|
||||
if (offset + size <= i_size_read(inode))
|
||||
return 0;
|
||||
|
||||
spin_lock(&ip->i_flags_lock);
|
||||
if (offset + size <= i_size_read(inode)) {
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i_size_write(inode, offset + size);
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
|
||||
return xfs_setfilesize(ip, offset, size);
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_dio_write_end_io(
|
||||
struct kiocb *iocb,
|
||||
@@ -623,30 +659,8 @@ xfs_dio_write_end_io(
|
||||
* with the on-disk inode size being outside the in-core inode size. We
|
||||
* have no other method of updating EOF for AIO, so always do it here
|
||||
* if necessary.
|
||||
*
|
||||
* We need to lock the test/set EOF update as we can be racing with
|
||||
* other IO completions here to update the EOF. Failing to serialise
|
||||
* here can result in EOF moving backwards and Bad Things Happen when
|
||||
* that occurs.
|
||||
*
|
||||
* As IO completion only ever extends EOF, we can do an unlocked check
|
||||
* here to avoid taking the spinlock. If we land within the current EOF,
|
||||
* then we do not need to do an extending update at all, and we don't
|
||||
* need to take the lock to check this. If we race with an update moving
|
||||
* EOF, then we'll either still be beyond EOF and need to take the lock,
|
||||
* or we'll be within EOF and we don't need to take it at all.
|
||||
*/
|
||||
if (offset + size <= i_size_read(inode))
|
||||
goto out;
|
||||
|
||||
spin_lock(&ip->i_flags_lock);
|
||||
if (offset + size > i_size_read(inode)) {
|
||||
i_size_write(inode, offset + size);
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
error = xfs_setfilesize(ip, offset, size);
|
||||
} else {
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
}
|
||||
error = xfs_dio_endio_set_isize(inode, offset, size);
|
||||
|
||||
out:
|
||||
memalloc_nofs_restore(nofs_flag);
|
||||
|
||||
Reference in New Issue
Block a user