X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fext2fs%2Funix_io.c;h=628e60c39eaf1400ea2dbbd5898262f077ba127d;hb=336c440ccea8f94b0728f881cddee84f730e7cc7;hp=7a4c9bf5edfbbc0abac18ea4c46c681b90d9c7e0;hpb=fddc423dc6353552772969d70cec08e8378d8e57;p=tools%2Fe2fsprogs.git diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index 7a4c9bf..628e60c 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -166,7 +166,7 @@ static errcode_t raw_read_blk(io_channel channel, unsigned char *buf = bufv; ssize_t really_read = 0; - size = (count < 0) ? -count : count * channel->block_size; + size = (count < 0) ? -count : (ext2_loff_t) count * channel->block_size; data->io_stats.bytes_read += size; location = ((ext2_loff_t) block * channel->block_size) + data->offset; @@ -275,7 +275,7 @@ static errcode_t raw_write_blk(io_channel channel, if (count < 0) size = -count; else - size = count * channel->block_size; + size = (ext2_loff_t) count * channel->block_size; } data->io_stats.bytes_written += size; @@ -1126,6 +1126,31 @@ unimplemented: 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 */ #if __GNUC_PREREQ (4, 6) #pragma GCC diagnostic push @@ -1144,10 +1169,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; @@ -1167,26 +1189,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)