Skip to content

Commit

Permalink
block/file-posix: Reduce xfsctl() use
Browse files Browse the repository at this point in the history
This patch removes xfs_write_zeroes() and xfs_discard().  Both functions
have been added just before the same feature was present through
fallocate():

- fallocate() has supported PUNCH_HOLE for XFS since Linux 2.6.38 (March
  2011); xfs_discard() was added in December 2010.

- fallocate() has supported ZERO_RANGE for XFS since Linux 3.15 (June
  2014); xfs_write_zeroes() was added in November 2013.

Nowadays, all systems that qemu runs on should support both fallocate()
features (RHEL 7's kernel does).

xfsctl() is still useful for getting the request alignment for O_DIRECT,
so this patch does not remove our dependency on it completely.

Note that xfs_write_zeroes() had a bug: It calls ftruncate() when the
file is shorter than the specified range (because ZERO_RANGE does not
increase the file length).  ftruncate() may yield and then discard data
that parallel write requests have written past the EOF in the meantime.
Dropping the function altogether fixes the bug.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Fixes: 50ba5b2
Reported-by: Lukáš Doktor <ldoktor@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Tested-by: Stefano Garzarella <sgarzare@redhat.com>
Tested-by: John Snow <jsnow@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
  • Loading branch information
XanClic authored and kevmw committed Sep 10, 2019
1 parent bb0c940 commit b2c6f23
Showing 1 changed file with 1 addition and 76 deletions.
77 changes: 1 addition & 76 deletions block/file-posix.c
Expand Up @@ -1459,59 +1459,6 @@ static int handle_aiocb_rw(void *opaque)
}
}

#ifdef CONFIG_XFS
static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes)
{
int64_t len;
struct xfs_flock64 fl;
int err;

len = lseek(s->fd, 0, SEEK_END);
if (len < 0) {
return -errno;
}

if (offset + bytes > len) {
/* XFS_IOC_ZERO_RANGE does not increase the file length */
if (ftruncate(s->fd, offset + bytes) < 0) {
return -errno;
}
}

memset(&fl, 0, sizeof(fl));
fl.l_whence = SEEK_SET;
fl.l_start = offset;
fl.l_len = bytes;

if (xfsctl(NULL, s->fd, XFS_IOC_ZERO_RANGE, &fl) < 0) {
err = errno;
trace_file_xfs_write_zeroes(strerror(errno));
return -err;
}

return 0;
}

static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes)
{
struct xfs_flock64 fl;
int err;

memset(&fl, 0, sizeof(fl));
fl.l_whence = SEEK_SET;
fl.l_start = offset;
fl.l_len = bytes;

if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
err = errno;
trace_file_xfs_discard(strerror(errno));
return -err;
}

return 0;
}
#endif

static int translate_err(int err)
{
if (err == -ENODEV || err == -ENOSYS || err == -EOPNOTSUPP ||
Expand Down Expand Up @@ -1567,23 +1514,15 @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb)
static int handle_aiocb_write_zeroes(void *opaque)
{
RawPosixAIOData *aiocb = opaque;
#if defined(CONFIG_FALLOCATE) || defined(CONFIG_XFS)
BDRVRawState *s = aiocb->bs->opaque;
#endif
#ifdef CONFIG_FALLOCATE
BDRVRawState *s = aiocb->bs->opaque;
int64_t len;
#endif

if (aiocb->aio_type & QEMU_AIO_BLKDEV) {
return handle_aiocb_write_zeroes_block(aiocb);
}

#ifdef CONFIG_XFS
if (s->is_xfs) {
return xfs_write_zeroes(s, aiocb->aio_offset, aiocb->aio_nbytes);
}
#endif

#ifdef CONFIG_FALLOCATE_ZERO_RANGE
if (s->has_write_zeroes) {
int ret = do_fallocate(s->fd, FALLOC_FL_ZERO_RANGE,
Expand Down Expand Up @@ -1653,14 +1592,6 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque)
}
#endif

#ifdef CONFIG_XFS
if (s->is_xfs) {
/* xfs_discard() guarantees that the discarded area reads as all-zero
* afterwards, so we can use it here. */
return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes);
}
#endif

/* If we couldn't manage to unmap while guaranteed that the area reads as
* all-zero afterwards, just write zeroes without unmapping */
ret = handle_aiocb_write_zeroes(aiocb);
Expand Down Expand Up @@ -1737,12 +1668,6 @@ static int handle_aiocb_discard(void *opaque)
ret = -errno;
#endif
} else {
#ifdef CONFIG_XFS
if (s->is_xfs) {
return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes);
}
#endif

#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
aiocb->aio_offset, aiocb->aio_nbytes);
Expand Down

0 comments on commit b2c6f23

Please sign in to comment.