[PATCH v2] erofs-utils: avoid flushing the image file on closing
Gao Xiang
hsiangkao at linux.alibaba.com
Thu Sep 14 19:39:05 AEST 2023
Traditionally, truncating to small sizes will trigger some
flush-on-close semantics to avoid the notorious NULL files.
I'm not sure if it's our use case since:
1) we're creating new image files instead of reusing old ones;
2) it kills end-to-end performance in practice;
3) other programs like GNU TAR doesn't work as this too for
such meaningless comparsion;
Let's work around it now.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
change since v1:
- fix macOS build error:
configure.ac | 2 ++
lib/io.c | 41 +++++++++++++++++++++++++++++++++++------
2 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/configure.ac b/configure.ac
index a8cecd0..51ace67 100644
--- a/configure.ac
+++ b/configure.ac
@@ -190,6 +190,7 @@ AC_CHECK_HEADERS(m4_flatten([
sys/mman.h
sys/random.h
sys/stat.h
+ sys/statfs.h
sys/sysmacros.h
sys/time.h
unistd.h
@@ -249,6 +250,7 @@ AC_CHECK_FUNCS(m4_flatten([
ftello64
pread64
pwrite64
+ fstatfs
strdup
strerror
strrchr
diff --git a/lib/io.c b/lib/io.c
index 1545436..602ac68 100644
--- a/lib/io.c
+++ b/lib/io.c
@@ -20,7 +20,9 @@
#ifdef HAVE_LINUX_FALLOC_H
#include <linux/falloc.h>
#endif
-
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
#define EROFS_MODNAME "erofs_io"
#include "erofs/print.h"
@@ -58,6 +60,11 @@ int dev_open(struct erofs_sb_info *sbi, const char *dev)
struct stat st;
int fd, ret;
+#if defined(HAVE_SYS_STATFS_H) && defined(HAVE_FSTATFS)
+ bool again = false;
+
+repeat:
+#endif
fd = open(dev, O_RDWR | O_CREAT | O_BINARY, 0644);
if (fd < 0) {
erofs_err("failed to open(%s).", dev);
@@ -82,11 +89,33 @@ int dev_open(struct erofs_sb_info *sbi, const char *dev)
sbi->devsz = round_down(sbi->devsz, erofs_blksiz(sbi));
break;
case S_IFREG:
- ret = ftruncate(fd, 0);
- if (ret) {
- erofs_err("failed to ftruncate(%s).", dev);
- close(fd);
- return -errno;
+ if (st.st_size) {
+#if defined(HAVE_SYS_STATFS_H) && defined(HAVE_FSTATFS)
+ struct statfs stfs;
+
+ if (again)
+ return -ENOTEMPTY;
+
+ /*
+ * fses like EXT4 and BTRFS will flush dirty blocks
+ * after truncate(0) even after the writeback happens
+ * (see kernel commit 7d8f9f7d150d and ccd2506bd431),
+ * which is NOT our intention. Let's work around this.
+ */
+ if (!fstatfs(fd, &stfs) && (stfs.f_type == 0xEF53 ||
+ stfs.f_type == 0x9123683E)) {
+ close(fd);
+ unlink(dev);
+ again = true;
+ goto repeat;
+ }
+#endif
+ ret = ftruncate(fd, 0);
+ if (ret) {
+ erofs_err("failed to ftruncate(%s).", dev);
+ close(fd);
+ return -errno;
+ }
}
/* INT64_MAX is the limit of kernel vfs */
sbi->devsz = INT64_MAX;
--
2.39.3
More information about the Linux-erofs
mailing list