On Apr 17, 2018, at 1:19 PM, Darrick J. Wong <darrick.wong@xxxxxxxxxx> wrote: > > From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > In unix_zeroout() for files, we should try a ZERO_RANGE before we try > PUNCH_HOLE because the former will not cause us to lose preallocated > blocks. Since block devices have supported fallocate for a few years > now, refactor the fallocate calls into a helper and call it from either > case. > > Reported-by: Andreas Dilger <adilger@xxxxxxxxx> > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> The patch was a bit confusing to read (I thought it skipped zero-out for block devices), but looking at the whole code it is clear that the __unix_zeroout() is always being called, and the truncate() code block is only being called for regular files. Reviewed-by: Andreas Dilger <adilger@xxxxxxxxx> > --- > lib/ext2fs/unix_io.c | 53 ++++++++++++++++++++++++++++---------------------- > 1 file changed, 30 insertions(+), 23 deletions(-) > > > diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c > index c6b058d..1fb6279 100644 > --- a/lib/ext2fs/unix_io.c > +++ b/lib/ext2fs/unix_io.c > @@ -1118,6 +1118,31 @@ static errcode_t unix_discard(io_channel channel, unsigned long long block, > return EXT2_ET_UNIMPLEMENTED; > } > > +/* > + * If we know about ZERO_RANGE, try that before we try PUNCH_HOLE because > + * ZERO_RANGE doesn't unmap preallocated blocks. We prefer fallocate because > + * it always invalidates page cache, and libext2fs requires that reads after > + * ZERO_RANGE return zeroes. > + */ > +static int __unix_zeroout(int fd, off_t offset, off_t len) > +{ > + int ret = -1; > + > +#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_ZERO_RANGE) > + ret = fallocate(fd, FALLOC_FL_ZERO_RANGE, offset, len); > + if (ret == 0) > + return 0; > +#endif > +#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE) > + ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, > + offset, len); > + if (ret == 0) > + return 0; > +#endif > + errno = EOPNOTSUPP; > + return ret; > +} > + > /* parameters might not be used if OS doesn't support zeroout */ > #pragma GCC diagnostic push > #pragma GCC diagnostic ignored "-Wunused-parameter" > @@ -1134,10 +1159,7 @@ static errcode_t unix_zeroout(io_channel channel, unsigned long long block, > if (safe_getenv("UNIX_IO_NOZEROOUT")) > goto unimplemented; > > - if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) { > - /* Not implemented until the BLKZEROOUT mess is fixed */ > - goto unimplemented; > - } else { > + if (!(channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE)) { > /* Regular file, try to use truncate/punch/zero. */ > struct stat statbuf; > > @@ -1157,26 +1179,11 @@ static errcode_t unix_zeroout(io_channel channel, unsigned long long block, > if (ret) > goto err; > } > -#if defined(HAVE_FALLOCATE) && (defined(FALLOC_FL_ZERO_RANGE) || \ > - (defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE))) > -#if defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE) > - ret = fallocate(data->dev, > - FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, > - (off_t)(block) * channel->block_size + data->offset, > - (off_t)(count) * channel->block_size); > - if (ret == 0) > - goto err; > -#endif > -#ifdef FALLOC_FL_ZERO_RANGE > - ret = fallocate(data->dev, > - FALLOC_FL_ZERO_RANGE, > - (off_t)(block) * channel->block_size + data->offset, > - (off_t)(count) * channel->block_size); > -#endif > -#else > - goto unimplemented; > -#endif /* HAVE_FALLOCATE && (ZERO_RANGE || (PUNCH_HOLE && KEEP_SIZE)) */ > } > + > + ret = __unix_zeroout(data->dev, > + (off_t)(block) * channel->block_size + data->offset, > + (off_t)(count) * channel->block_size); > err: > if (ret < 0) { > if (errno == EOPNOTSUPP) > Cheers, Andreas
Attachment:
signature.asc
Description: Message signed with OpenPGP