From: Andreas Dilger Date: Wed, 10 May 2023 04:26:39 +0000 (-0600) Subject: ext2fs: don't retry discard/zeroout repeatedly X-Git-Tag: v1.47.0-wc4~3 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=9cd756fb8c83d389662dc0c3a9ea8fece949b196;p=tools%2Fe2fsprogs.git ext2fs: don't retry discard/zeroout repeatedly Call safe_getenv(UNIX_IO_NOZEROOUT) once when the device is opened and set CHANNEL_FLAG_NOZEROOUT if present instead of getting uid/euid/getenv every time unix_zeroout() is called. For unix_discard() and unix_zeroout() don't continue to call them if the block device doesn't support these operations. Change-Id: I3b3b79cf49a6f1cf9b254eb32103f174bacdfbd2 Signed-off-by: Andreas Dilger Reviewed-on: https://review.whamcloud.com/c/tools/e2fsprogs/+/51294 Tested-by: jenkins Tested-by: Maloo --- diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h index e747c12..52eea4d 100644 --- a/lib/ext2fs/ext2_io.h +++ b/lib/ext2fs/ext2_io.h @@ -34,6 +34,8 @@ typedef struct struct_io_stats *io_stats; #define CHANNEL_FLAGS_DISCARD_ZEROES 0x02 #define CHANNEL_FLAGS_BLOCK_DEVICE 0x04 #define CHANNEL_FLAGS_THREADS 0x08 +#define CHANNEL_FLAGS_NODISCARD 0x10 +#define CHANNEL_FLAGS_NOZEROOUT 0x20 #define io_channel_discard_zeroes_data(i) (i->flags & CHANNEL_FLAGS_DISCARD_ZEROES) @@ -57,7 +59,7 @@ struct struct_io_channel { int actual_bytes_written, errcode_t error); int refcount; - int flags; + unsigned int flags; long reserved[14]; void *private_data; void *app_data; diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index ff95e8d..81cf879 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -761,6 +761,9 @@ static errcode_t unix_open_channel(const char *name, int fd, io->refcount = 1; io->flags = 0; + if (safe_getenv("UNIX_IO_NOZEROOUT")) + io->flags |= CHANNEL_FLAGS_NOZEROOUT; + memset(data, 0, sizeof(struct unix_private_data)); data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; data->io_stats.num_fields = 2; @@ -783,21 +786,20 @@ static errcode_t unix_open_channel(const char *name, int fd, * zero. */ if (ext2fs_fstat(data->dev, &st) == 0) { - if (ext2fsP_is_disk_device(st.st_mode)) + if (ext2fsP_is_disk_device(st.st_mode)) { +#ifdef BLKDISCARDZEROES + int zeroes = 0; + + if (ioctl(data->dev, BLKDISCARDZEROES, &zeroes) == 0 && + zeroes) + io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; +#endif io->flags |= CHANNEL_FLAGS_BLOCK_DEVICE; - else + } else { io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; + } } -#ifdef BLKDISCARDZEROES - { - int zeroes = 0; - if (ioctl(data->dev, BLKDISCARDZEROES, &zeroes) == 0 && - zeroes) - io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; - } -#endif - #if defined(__CYGWIN__) /* * Some operating systems require that the buffers be aligned, @@ -1360,12 +1362,15 @@ static errcode_t unix_discard(io_channel channel, unsigned long long block, unsigned long long count) { struct unix_private_data *data; - int ret; + int ret = EOPNOTSUPP; EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + if (channel->flags & CHANNEL_FLAGS_NODISCARD) + goto unimplemented; + if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) { #ifdef BLKDISCARD __u64 range[2]; @@ -1392,8 +1397,10 @@ static errcode_t unix_discard(io_channel channel, unsigned long long block, #endif } if (ret < 0) { - if (errno == EOPNOTSUPP) + if (errno == EOPNOTSUPP) { + channel->flags |= CHANNEL_FLAGS_NODISCARD; goto unimplemented; + } return errno; } return 0; @@ -1441,9 +1448,6 @@ static errcode_t unix_zeroout(io_channel channel, unsigned long long block, data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - if (safe_getenv("UNIX_IO_NOZEROOUT")) - goto unimplemented; - if (!(channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE)) { /* Regular file, try to use truncate/punch/zero. */ struct stat statbuf; @@ -1466,13 +1470,18 @@ static errcode_t unix_zeroout(io_channel channel, unsigned long long block, } } + if (channel->flags & CHANNEL_FLAGS_NOZEROOUT) + goto unimplemented; + 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) + if (errno == EOPNOTSUPP) { + channel->flags |= CHANNEL_FLAGS_NOZEROOUT; goto unimplemented; + } return errno; } return 0;