[PATCH] erofs-utils: avoid flushing the image file on closing
Gao Xiang
hsiangkao at linux.alibaba.com
Thu Sep 14 15:32:11 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>
---
configure.ac | 2 ++
lib/io.c | 40 ++++++++++++++++++++++++++++++++++------
2 files changed, 36 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..eb9d876 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"
@@ -55,9 +57,11 @@ void dev_close(struct erofs_sb_info *sbi)
int dev_open(struct erofs_sb_info *sbi, const char *dev)
{
+ bool again = false;
struct stat st;
int fd, ret;
+repeat:
fd = open(dev, O_RDWR | O_CREAT | O_BINARY, 0644);
if (fd < 0) {
erofs_err("failed to open(%s).", dev);
@@ -82,11 +86,35 @@ 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) {
+#ifdef HAVE_SYS_STATFS_H
+ struct statfs stfs;
+
+ if (again)
+ return -ENOTEMPTY;
+
+#ifdef HAVE_FSTATFS
+ /*
+ * 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
+#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