aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure2
-rw-r--r--configure.in2
-rw-r--r--lib/ext2fs/ext2_io.h1
-rw-r--r--lib/ext2fs/unix_io.c53
-rw-r--r--misc/mke2fs.c10
-rw-r--r--tests/f_resize_inode/script1
-rw-r--r--tests/m_bigjournal/script2
-rw-r--r--tests/run_mke2fs2
8 files changed, 59 insertions, 14 deletions
diff --git a/configure b/configure
index 6bac035d..215d0312 100755
--- a/configure
+++ b/configure
@@ -10314,7 +10314,7 @@ fi
done
fi
-for ac_header in dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h linux/fd.h linux/major.h net/if_dl.h netinet/in.h sys/disklabel.h sys/file.h sys/ioctl.h sys/mkdev.h sys/mman.h sys/prctl.h sys/queue.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h
+for ac_header in dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h linux/falloc.h linux/fd.h linux/major.h net/if_dl.h netinet/in.h sys/disklabel.h sys/file.h sys/ioctl.h sys/mkdev.h sys/mman.h sys/prctl.h sys/queue.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
diff --git a/configure.in b/configure.in
index 6b6c852c..8dc75a9b 100644
--- a/configure.in
+++ b/configure.in
@@ -802,7 +802,7 @@ if test $cross_compiling = no; then
else
AC_CHECK_PROGS(BUILD_CC, gcc cc)
fi
-AC_CHECK_HEADERS(dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h linux/fd.h linux/major.h net/if_dl.h netinet/in.h sys/disklabel.h sys/file.h sys/ioctl.h sys/mkdev.h sys/mman.h sys/prctl.h sys/queue.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h)
+AC_CHECK_HEADERS(dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h linux/falloc.h linux/fd.h linux/major.h net/if_dl.h netinet/in.h sys/disklabel.h sys/file.h sys/ioctl.h sys/mkdev.h sys/mman.h sys/prctl.h sys/queue.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h)
AC_CHECK_HEADERS(sys/disk.h sys/mount.h,,,
[[
#if HAVE_SYS_QUEUE_H
diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h
index e71ada99..bcc2f876 100644
--- a/lib/ext2fs/ext2_io.h
+++ b/lib/ext2fs/ext2_io.h
@@ -30,6 +30,7 @@ typedef struct struct_io_stats *io_stats;
#define CHANNEL_FLAGS_WRITETHROUGH 0x01
#define CHANNEL_FLAGS_DISCARD_ZEROES 0x02
+#define CHANNEL_FLAGS_BLOCK_DEVICE 0x04
#define io_channel_discard_zeroes_data(i) (i->flags & CHANNEL_FLAGS_DISCARD_ZEROES)
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index 21a273db..ecddfa6b 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -49,6 +49,9 @@
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
+#if HAVE_LINUX_FALLOC_H
+#include <linux/falloc.h>
+#endif
#if defined(__linux__) && defined(_IO) && !defined(BLKROGET)
#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */
@@ -488,6 +491,20 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel)
goto cleanup;
}
+ /*
+ * If the device is really a block device, then set the
+ * appropriate flag, otherwise we can set DISCARD_ZEROES flag
+ * because we are going to use punch hole instead of discard
+ * and if it succeed, subsequent read from sparse area returns
+ * zero.
+ */
+ if (ext2fs_stat(io->name, &st) == 0) {
+ if (S_ISBLK(st.st_mode))
+ io->flags |= CHANNEL_FLAGS_BLOCK_DEVICE;
+ else
+ io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES;
+ }
+
#ifdef BLKSSZGET
if (flags & IO_FLAG_DIRECT_IO) {
if (ioctl(data->dev, BLKSSZGET, &data->align) != 0)
@@ -853,13 +870,12 @@ static errcode_t unix_set_option(io_channel channel, const char *option,
}
#if defined(__linux__) && !defined(BLKDISCARD)
-#define BLKDISCARD _IO(0x12,119)
+#define BLKDISCARD _IO(0x12,119)
#endif
static errcode_t unix_discard(io_channel channel, unsigned long long block,
unsigned long long count)
{
-#ifdef BLKDISCARD
struct unix_private_data *data;
__uint64_t range[2];
int ret;
@@ -868,14 +884,35 @@ static errcode_t unix_discard(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);
- range[0] = (__uint64_t)(block) * channel->block_size;
- range[1] = (__uint64_t)(count) * channel->block_size;
+ if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) {
+#ifdef BLKDISCARD
+ range[0] = (__uint64_t)(block) * channel->block_size;
+ range[1] = (__uint64_t)(count) * channel->block_size;
- ret = ioctl(data->dev, BLKDISCARD, &range);
- if (ret < 0)
+ ret = ioctl(data->dev, BLKDISCARD, &range);
+#else
+ goto unimplemented;
+#endif
+ } else {
+#ifdef FALLOC_FL_PUNCH_HOLE
+ /*
+ * If we are not on block device, try to use punch hole
+ * to reclaim free space.
+ */
+ ret = fallocate(data->dev,
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ (off_t)(block) * channel->block_size,
+ (off_t)(count) * channel->block_size);
+#else
+ goto unimplemented;
+#endif
+ }
+ if (ret < 0) {
+ if (errno == EOPNOTSUPP)
+ goto unimplemented;
return errno;
+ }
return 0;
-#else
+unimplemented:
return EXT2_ET_UNIMPLEMENTED;
-#endif
}
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 63538cd9..abcfbf02 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -2077,12 +2077,18 @@ static int mke2fs_discard_device(ext2_filsys fs)
struct ext2fs_numeric_progress_struct progress;
blk64_t blocks = ext2fs_blocks_count(fs->super);
blk64_t count = DISCARD_STEP_MB;
- blk64_t cur = 0;
+ blk64_t cur;
int retval = 0;
- retval = io_channel_discard(fs->io, 0, 0);
+ /*
+ * Let's try if discard really works on the device, so
+ * we do not print numeric progress resulting in failure
+ * afterwards.
+ */
+ retval = io_channel_discard(fs->io, 0, fs->blocksize);
if (retval)
return retval;
+ cur = fs->blocksize;
count *= (1024 * 1024);
count /= fs->blocksize;
diff --git a/tests/f_resize_inode/script b/tests/f_resize_inode/script
index a010fd98..ca934e9e 100644
--- a/tests/f_resize_inode/script
+++ b/tests/f_resize_inode/script
@@ -17,6 +17,7 @@ dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
echo mke2fs -F -O resize_inode -o Linux -b 1024 -g 1024 test.img 16384 > $OUT
$MKE2FS -F -O resize_inode -o Linux -b 1024 -g 1024 $TMPFILE 16384 2>&1 \
| sed -e '1d' | grep -v "automatically checked" |
+ grep -v 'Discarding device blocks' |
grep -v "whichever comes first" >> $OUT
$FSCK $FSCK_OPT -N test_filesys $TMPFILE > $OUT.new 2>&1
diff --git a/tests/m_bigjournal/script b/tests/m_bigjournal/script
index 29e0a242..1e21fdfe 100644
--- a/tests/m_bigjournal/script
+++ b/tests/m_bigjournal/script
@@ -1,4 +1,4 @@
DESCRIPTION="journal over 4GB in size"
FS_SIZE=11000000
-MKE2FS_OPTS="-t ext4 -G 512 -N 1280 -J size=5000 -q -E lazy_journal_init,lazy_itable_init"
+MKE2FS_OPTS="-t ext4 -G 512 -N 1280 -J size=5000 -q -E lazy_journal_init,lazy_itable_init,nodiscard"
. $cmd_dir/run_mke2fs
diff --git a/tests/run_mke2fs b/tests/run_mke2fs
index a3a77432..f5249968 100644
--- a/tests/run_mke2fs
+++ b/tests/run_mke2fs
@@ -11,7 +11,7 @@ MKE2FS_SKIP_PROGRESS=true
MKE2FS_SKIP_CHECK_MSG=true
export MKE2FS_SKIP_PROGRESS MKE2FS_SKIP_CHECK_MSG
> $TMPFILE
-PREP_CMD='$MKE2FS -F -o Linux $MKE2FS_OPTS $TMPFILE $FS_SIZE 2>&1 | sed -e 1d | tr -d \\015 > $OUT1 ; $DEBUGFS -R features $TMPFILE 2>&1 | sed -e 1d | tr -d \\015 >> $OUT1 ; echo " " >> $OUT1'
+PREP_CMD='$MKE2FS -F -o Linux $MKE2FS_OPTS $TMPFILE $FS_SIZE 2>&1 | sed -e 1d | grep -v "Discarding device blocks" | tr -d \\015 > $OUT1 ; $DEBUGFS -R features $TMPFILE 2>&1 | sed -e 1d | tr -d \\015 >> $OUT1 ; echo " " >> $OUT1'
AFTER_CMD='$DUMPE2FS $TMPFILE 2>&1 | sed -f $cmd_dir/filter_dumpe2fs | tr -d \\015 >> $OUT1'
. $cmd_dir/run_e2fsck