* [PATCHSET] fuse2fs: round 6 bug fixes
@ 2025-10-16 15:39 Darrick J. Wong
2025-10-16 15:40 ` [PATCH 01/16] debian/rules: remove extra pkg-config Darrick J. Wong
` (19 more replies)
0 siblings, 20 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:39 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
Hi all,
This series fixes more bugs in libext2fs and fuse2fs.
If you're going to start using this code, I strongly recommend pulling
from my git trees, which are linked below.
Comments and questions are, as always, welcome.
e2fsprogs git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/e2fsprogs.git/log/?h=fuse2fs-fixes
---
Commits in this patchset:
* debian/rules: remove extra pkg-config
* libext2fs: use F_GETFL, not F_GETFD, in unixfd_open
* libext2fs: don't look for O_EXCL in the F_GETFL output
* libext2fs: fix ind_punch recursive block computation
* libext2fs: the unixfd IO manager shouldn't close its fd
* fuse2fs: update manpage
* fuse2fs: quiet down EXT2_ET_RO_FILSYS errors
* fuse2fs: free global_fs after a failed ext2fs_close call
* fuse2fs: fix memory corruption when parsing mount options
* fuse2fs: fix fssetxattr flags updates
* fuse2fs: fix default acls propagating to non-dir children
* fuse2fs: don't update atime when reading executable file content
* fuse2fs: fix in_file_group missing the primary process gid
* fuse2fs: work around EBUSY discard returns from dm-thinp
* fuse2fs: check free space when creating a symlink
* fuse2fs: spot check clean journals
---
debugfs/journal.h | 2 +
debian/rules | 2 +
debugfs/journal.c | 2 +
lib/ext2fs/punch.c | 12 +++++-
lib/ext2fs/unix_io.c | 11 +++---
misc/fuse2fs.1.in | 42 ++++++++++++++-------
misc/fuse2fs.c | 100 +++++++++++++++++++++++++++++++++++++++-----------
7 files changed, 124 insertions(+), 47 deletions(-)
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/16] debian/rules: remove extra pkg-config
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
@ 2025-10-16 15:40 ` Darrick J. Wong
2025-10-16 15:40 ` [PATCH 02/16] libext2fs: use F_GETFL, not F_GETFD, in unixfd_open Darrick J. Wong
` (18 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:40 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
Not sure why the definition for deb_udevudevdir calls pkg-config with
the string "pkg-config" as its first argument. Even more crazily, this
happens on Debian 12:
$ pkg-config --variable=udevdir udev
/lib/udev
$ pkg-config pkg-config --variable=udevdir udev
/lib/udev
Note the leading space! Given the sed script in the same definition,
I'm guessing that the extra space is NOT the desired behavior.
Cc: <linux-ext4@vger.kernel.org> # v1.47.1
Fixes: 288de9fb396811 ("debian: acknowledge NMU'ed changes to 1.47.0-2.4")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
debian/rules | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/debian/rules b/debian/rules
index 4cb80652115317..c88675c9228bd0 100755
--- a/debian/rules
+++ b/debian/rules
@@ -16,7 +16,7 @@ endif
ifeq ($(DEB_HOST_ARCH_OS), linux)
export deb_systemdsystemunitdir = $(shell pkg-config --variable=systemdsystemunitdir systemd | sed s,^/,,)
-export deb_udevudevdir = $(shell pkg-config pkg-config --variable=udevdir udev | sed s,^/,,)
+export deb_udevudevdir = $(shell pkg-config --variable=udevdir udev | sed s,^/,,)
endif
ifneq ($(filter pkg.e2fsprogs.no-fuse2fs,$(DEB_BUILD_PROFILES)),)
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 02/16] libext2fs: use F_GETFL, not F_GETFD, in unixfd_open
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
2025-10-16 15:40 ` [PATCH 01/16] debian/rules: remove extra pkg-config Darrick J. Wong
@ 2025-10-16 15:40 ` Darrick J. Wong
2025-10-16 15:40 ` [PATCH 03/16] libext2fs: don't look for O_EXCL in the F_GETFL output Darrick J. Wong
` (17 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:40 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
F_GETFD is the fcntl command that returns FD_* flags, but the callsite
wants to look at the O_* flags. F_GETFL is the fcntl command that
returns the O_* flags, so change the subcommand to be correct.
Cc: <linux-ext4@vger.kernel.org> # v1.43.2
Fixes: 4ccf9e4fe165cf ("libext2fs: add unixfd_io_manager")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
lib/ext2fs/unix_io.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index cb408f51779aa7..adbdd5f6603d74 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -1086,7 +1086,7 @@ static errcode_t unixfd_open(const char *str_fd, int flags,
fd = atoi(str_fd);
#if defined(HAVE_FCNTL)
- fd_flags = fcntl(fd, F_GETFD);
+ fd_flags = fcntl(fd, F_GETFL);
if (fd_flags == -1)
return EBADF;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 03/16] libext2fs: don't look for O_EXCL in the F_GETFL output
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
2025-10-16 15:40 ` [PATCH 01/16] debian/rules: remove extra pkg-config Darrick J. Wong
2025-10-16 15:40 ` [PATCH 02/16] libext2fs: use F_GETFL, not F_GETFD, in unixfd_open Darrick J. Wong
@ 2025-10-16 15:40 ` Darrick J. Wong
2025-10-16 15:40 ` [PATCH 04/16] libext2fs: fix ind_punch recursive block computation Darrick J. Wong
` (16 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:40 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
For decades, Linux has never propagated O_EXCL into the user-visible
file flags in do_dentry_open:
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
Therefore, one cannot use F_GETFL to determine if the file was opened
with O_EXCL. The unixfd IO manager will have to trust that the caller
opened the file in O_EXCL mode. Without this patch, the upcoming flock
patch will not work correctly in determining the lock mode to keep other
copies of fuse4fs and/or systemd from touching a fuse4fs mounted
filesystem.
Cc: <linux-ext4@vger.kernel.org> # v1.43.2
Fixes: 4ccf9e4fe165cf ("libext2fs: add unixfd_io_manager")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
lib/ext2fs/unix_io.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index adbdd5f6603d74..723a5c2474cdd5 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -1090,11 +1090,10 @@ static errcode_t unixfd_open(const char *str_fd, int flags,
if (fd_flags == -1)
return EBADF;
- flags = 0;
+ /* O_EXCL is cleared by Linux at open and not returned by F_GETFL */
+ flags &= IO_FLAG_EXCLUSIVE;
if (fd_flags & O_RDWR)
flags |= IO_FLAG_RW;
- if (fd_flags & O_EXCL)
- flags |= IO_FLAG_EXCLUSIVE;
#if defined(O_DIRECT)
if (fd_flags & O_DIRECT)
flags |= IO_FLAG_DIRECT_IO;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 04/16] libext2fs: fix ind_punch recursive block computation
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (2 preceding siblings ...)
2025-10-16 15:40 ` [PATCH 03/16] libext2fs: don't look for O_EXCL in the F_GETFL output Darrick J. Wong
@ 2025-10-16 15:40 ` Darrick J. Wong
2025-10-16 15:41 ` [PATCH 05/16] libext2fs: the unixfd IO manager shouldn't close its fd Darrick J. Wong
` (15 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:40 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
generic/742 writes a large file and calls punch-alternating to punch out
every other block in the file. Unfortunately, there's a bug in
ind_punch that causes it to turn a request to punch out file block 2060
into punching out every file block *starting* at block 2060. The
emptying out of the block mapping causes a FIEMAP call in that test to
loop forever, which causes fuse4fs testing of ext3 to halt.
ext2fs_punch_ind recursively calls ind_punch on each level of the
indirect map to unmap file blocks. The start and count parameters to
ind_punch are (I think) the file range to punch given a particular block
and level within the indirect map, but shifted down by the start of the
logical file range mapped by that level in the indirect tree. To call
ind_punch for the next level down, we need to compute the new range.
But first, a diversion back to the failing testcase:
Note that file block 2060 is the first block mapped by the second
double-indirect block in the file:
(0-11):935-946, (IND):947, (12-1035):948-1971, (DIND):1972, (IND):1973,
(1036-2059):1974-2997, (IND):2998, (2060-3083):2999-4022, (IND):4023,
(3084-4107):4024-5047, (IND):5048, (4108-5131):5049-6072, (IND):6073,
(5132-6155):6074-7097, (IND):7098, (6156-7179):7099-8122, (IND):8123,
(7180-8203):8124-9147, (IND):9148, (8204-9227):9149-10172, (IND):10173,
(9228-9999):10174-10945 TOTAL: 10011
At this point, enabling PUNCH_DEBUG produces the following:
FUSE4FS (sda): tid=72529 fuse4fs_punch_range: ino=53 mode=0x3 offset=0x80c000 len=0x1000 start=0x80c end=0x80d
Main loop level 0, start 2060 count 1 max 12 num 12
Main loop level 1, start 2048 count 1 max 1024 num 1
Main loop level 2, start 1024 count 1 max 1048576 num 1
Entering ind_punch, level 2, start 1024, count 1, max 1
Reading indirect block 1972
start 1024 offset 0 start2 1024 count 1 count2 1
Entering ind_punch, level 1, start 1024, count 1, max 1024
Reading indirect block 2998
start 1024 offset 1024 start2 0 count 1 count2 1
Entering ind_punch, level 0, start 0, count 18446744073709550593, max 1024
This is wrong, because we want to punch *one* block, not some gigantic
number of blocks! This huge value is actually -1023, which is the
result of the expression (count - offset). Ooops, that's why we unmap
every block in this indirect block!
Note the suspicious 7th argument to the nested ind_punch call:
count - offset
This doesn't smell right, because we're subtracting a position from a
length. The end of the range for the next level down should be the
difference between the end and the start of the range in the current
level after accounting for our current position within that level. In
other words, the smaller of end - start and end - offset.
Cc: <linux-ext4@vger.kernel.org> # v1.42
Fixes: 3adb9374fb9273 ("libext2fs: Add new function ext2fs_punch()")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
lib/ext2fs/punch.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/lib/ext2fs/punch.c b/lib/ext2fs/punch.c
index 19b6a37824c589..c48e74ef799a82 100644
--- a/lib/ext2fs/punch.c
+++ b/lib/ext2fs/punch.c
@@ -54,6 +54,7 @@ static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode,
blk_t b;
int i;
blk64_t offset, incr;
+ const blk64_t end = start + count;
int freed = 0;
#ifdef PUNCH_DEBUG
@@ -62,13 +63,14 @@ static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode,
#endif
incr = 1ULL << ((EXT2_BLOCK_SIZE_BITS(fs->super) - 2) * level);
for (i = 0, offset = 0; i < max; i++, p++, offset += incr) {
- if (offset >= start + count)
+ if (offset >= end)
break;
if (*p == 0 || (offset+incr) <= start)
continue;
b = *p;
if (level > 0) {
blk_t start2;
+ blk_t count2;
#ifdef PUNCH_DEBUG
printf("Reading indirect block %u\n", b);
#endif
@@ -76,9 +78,15 @@ static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode,
if (retval)
return retval;
start2 = (start > offset) ? start - offset : 0;
+ count2 = end - ((start > offset) ? start : offset);
+#ifdef PUNCH_DEBUG
+ printf("start %llu offset %llu count %llu end %llu "
+ "incr %llu start2 %u count2 %u\n", start,
+ offset, count, end, incr, start2, count2);
+#endif
retval = ind_punch(fs, inode, block_buf + fs->blocksize,
(blk_t *) block_buf, level - 1,
- start2, count - offset,
+ start2, count2,
fs->blocksize >> 2);
if (retval)
return retval;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 05/16] libext2fs: the unixfd IO manager shouldn't close its fd
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (3 preceding siblings ...)
2025-10-16 15:40 ` [PATCH 04/16] libext2fs: fix ind_punch recursive block computation Darrick J. Wong
@ 2025-10-16 15:41 ` Darrick J. Wong
2025-10-16 15:41 ` [PATCH 06/16] fuse2fs: update manpage Darrick J. Wong
` (14 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:41 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
The unixfd IO manager didn't create the fd that was passed in, so it
should not close the fd when the io channel closes.
Cc: <linux-ext4@vger.kernel.org> # v1.43.2
Fixes: 4ccf9e4fe165cf ("libext2fs: add unixfd_io_manager")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
lib/ext2fs/unix_io.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index 723a5c2474cdd5..1456b4d4bbe212 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -1061,7 +1061,7 @@ static errcode_t unix_open_channel(const char *name, int fd,
cleanup:
if (data) {
- if (data->dev >= 0)
+ if (io->manager != unixfd_io_manager && data->dev >= 0)
close(data->dev);
if (data->cache) {
free_cache(data);
@@ -1147,7 +1147,7 @@ static errcode_t unix_close(io_channel channel)
retval = flush_cached_blocks(channel, data, 0);
#endif
- if (close(data->dev) < 0)
+ if (channel->manager != unixfd_io_manager && close(data->dev) < 0)
retval = errno;
free_cache(data);
free(data->cache);
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 06/16] fuse2fs: update manpage
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (4 preceding siblings ...)
2025-10-16 15:41 ` [PATCH 05/16] libext2fs: the unixfd IO manager shouldn't close its fd Darrick J. Wong
@ 2025-10-16 15:41 ` Darrick J. Wong
2025-10-16 15:41 ` [PATCH 07/16] fuse2fs: quiet down EXT2_ET_RO_FILSYS errors Darrick J. Wong
` (13 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:41 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
Update the manpage to list current options for fuse2fs. While we're at
it, alphabetize the non-grouped mount options (e.g. rw/ro, *df).
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.1.in | 42 +++++++++++++++++++++++++++---------------
1 file changed, 27 insertions(+), 15 deletions(-)
diff --git a/misc/fuse2fs.1.in b/misc/fuse2fs.1.in
index 21f5760742c639..69fc6b01d7b639 100644
--- a/misc/fuse2fs.1.in
+++ b/misc/fuse2fs.1.in
@@ -36,21 +36,33 @@ .SS "fuse2fs options:"
\fB-o\fR ro
read-only mount
.TP
-\fB-o\fR errors=panic
-dump core on error
+\fB-o\fR rw
+read-write mount (default)
+.TP
+\fB-o\fR bsddf
+bsd-style df (default)
.TP
\fB-o\fR minixdf
minix-style df
.TP
+\fB-o\fR acl
+enable file access control lists
+.TP
+\fB-o\fR cache_size
+Set the disk cache size to this quantity.
+The quantity may contain the suffixes k, m, or g.
+By default, the size is 32MB.
+The size may not be larger than 2GB.
+.TP
+\fB-o\fR direct
+Use O_DIRECT to access the block device.
+.TP
+\fB-o\fR errors=panic
+dump core on error
+.TP
\fB-o\fR fakeroot
pretend to be root for permission checks
.TP
-\fB-o\fR no_default_opts
-do not include default fuse options
-.TP
-\fB-o\fR norecovery
-do not replay the journal and mount the file system read-only
-.TP
\fB-o\fR fuse2fs_debug
enable fuse2fs debugging
.TP
@@ -63,14 +75,14 @@ .SS "fuse2fs options:"
.I nosuid
) later.
.TP
-\fB-o\fR direct
-Use O_DIRECT to access the block device.
+\fB-o\fR lockfile=path
+use this file to control access to the filesystem
.TP
-\fB-o\fR cache_size
-Set the disk cache size to this quantity.
-The quantity may contain the suffixes k, m, or g.
-By default, the size is 32MB.
-The size may not be larger than 2GB.
+\fB-o\fR no_default_opts
+do not include default fuse options
+.TP
+\fB-o\fR norecovery
+do not replay the journal and mount the file system read-only
.SS "FUSE options:"
.TP
\fB-d -o\fR debug
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 07/16] fuse2fs: quiet down EXT2_ET_RO_FILSYS errors
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (5 preceding siblings ...)
2025-10-16 15:41 ` [PATCH 06/16] fuse2fs: update manpage Darrick J. Wong
@ 2025-10-16 15:41 ` Darrick J. Wong
2025-10-16 15:41 ` [PATCH 08/16] fuse2fs: free global_fs after a failed ext2fs_close call Darrick J. Wong
` (12 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:41 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
If an fs update fails because the ext2_filsys is opened in readonly
mode, just return EROFS and don't log that. This prevents unnecessary
spew for norecovery mounts.
Cc: <linux-ext4@vger.kernel.org> # v1.43
Fixes: 81cbf1ef4f5dab ("misc: add fuse2fs, a FUSE server for e2fsprogs")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index cb5620c7e2ee33..4d92e1e818b1c4 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -4983,6 +4983,9 @@ static int __translate_error(ext2_filsys fs, ext2_ino_t ino, errcode_t err,
case EXT2_ET_UNIMPLEMENTED:
ret = -EOPNOTSUPP;
break;
+ case EXT2_ET_RO_FILSYS:
+ ret = -EROFS;
+ break;
case EXT2_ET_MAGIC_EXT2FS_FILSYS:
case EXT2_ET_MAGIC_BADBLOCKS_LIST:
case EXT2_ET_MAGIC_BADBLOCKS_ITERATE:
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 08/16] fuse2fs: free global_fs after a failed ext2fs_close call
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (6 preceding siblings ...)
2025-10-16 15:41 ` [PATCH 07/16] fuse2fs: quiet down EXT2_ET_RO_FILSYS errors Darrick J. Wong
@ 2025-10-16 15:41 ` Darrick J. Wong
2025-10-16 15:42 ` [PATCH 09/16] fuse2fs: fix memory corruption when parsing mount options Darrick J. Wong
` (11 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:41 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
If ext2fs_close fails for any reason, it won't free the ext2_filsys
object or any of the other things that hang off of it, like the io
managers and whatnot. Right now this results in a memory leak of
global_fs, which is mostly benign because we're nearly to the end of
main() anyway.
However, a future patch will move the ext2fs_close call to op_destroy
prior to introducing iomap support, which means that we won't close
the (O_EXCL) block device before returning from umount, which will cause
problems with fstests and the user expectation that block devices are
closed when umount(8) returns.
Therefore, free the context after a failed close.
Cc: <linux-ext4@vger.kernel.org> # v1.43.7
Fixes: 6ae16a6814f47c ("misc: clean up error handling for ext2fs_run_ext3_journal()")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 4d92e1e818b1c4..0a862ea086cbde 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -4904,10 +4904,9 @@ int main(int argc, char *argv[])
fflush(orig_stderr);
}
if (global_fs) {
- err = ext2fs_close(global_fs);
+ err = ext2fs_close_free(&global_fs);
if (err)
com_err(argv[0], err, "while closing fs");
- global_fs = NULL;
}
if (fctx.lockfile) {
if (unlink(fctx.lockfile)) {
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 09/16] fuse2fs: fix memory corruption when parsing mount options
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (7 preceding siblings ...)
2025-10-16 15:41 ` [PATCH 08/16] fuse2fs: free global_fs after a failed ext2fs_close call Darrick J. Wong
@ 2025-10-16 15:42 ` Darrick J. Wong
2025-10-16 15:42 ` [PATCH 10/16] fuse2fs: fix fssetxattr flags updates Darrick J. Wong
` (10 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:42 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
struct fuse_opt has this interesting behavior -- if you set the offset
field to a non-negative value, then it will treat that value as a byte
offset into the data parameter that is passed to fuse_opt_parse.
Unfortnately, process_opt computes a pointer from ((char *)data +
offset), casts that to an int pointer(!), and dereferences the int
pointer to set the value. Therefore, we cannot have uint8_t fields in
struct fuse2fs because that will lead to subtle memory corruption.
Cc: <linux-ext4@vger.kernel.org> # v1.47.3
Fixes: c7f2688540d95e ("fuse2fs: compact all the boolean flags in struct fuse2fs")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 0a862ea086cbde..868b889912857d 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -217,17 +217,19 @@ struct fuse2fs {
pthread_mutex_t bfl;
char *device;
char *shortdev;
- uint8_t ro;
- uint8_t debug;
- uint8_t no_default_opts;
- uint8_t panic_on_error;
- uint8_t minixdf;
- uint8_t fakeroot;
- uint8_t alloc_all_blocks;
- uint8_t norecovery;
- uint8_t kernel;
- uint8_t directio;
- uint8_t acl;
+
+ /* options set by fuse_opt_parse must be of type int */
+ int ro;
+ int debug;
+ int no_default_opts;
+ int panic_on_error;
+ int minixdf;
+ int fakeroot;
+ int alloc_all_blocks;
+ int norecovery;
+ int kernel;
+ int directio;
+ int acl;
int logfd;
int blocklog;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 10/16] fuse2fs: fix fssetxattr flags updates
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (8 preceding siblings ...)
2025-10-16 15:42 ` [PATCH 09/16] fuse2fs: fix memory corruption when parsing mount options Darrick J. Wong
@ 2025-10-16 15:42 ` Darrick J. Wong
2025-10-16 15:42 ` [PATCH 11/16] fuse2fs: fix default acls propagating to non-dir children Darrick J. Wong
` (9 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:42 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
Fix flags setting so that it actually works -- we need to preserve the
iflags bits that don't exist in xflags.
Cc: <linux-ext4@vger.kernel.org> # v1.47.3
Fixes: 9b5012c1569d4e ("fuse2fs: support getting and setting via struct fsxattr")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 868b889912857d..5e610be2760a5a 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -3891,6 +3891,33 @@ static __u32 fsxflags_to_iflags(__u32 xflags)
return iflags;
}
+#define FUSE2FS_MODIFIABLE_XFLAGS (FS_XFLAG_IMMUTABLE | \
+ FS_XFLAG_APPEND | \
+ FS_XFLAG_SYNC | \
+ FS_XFLAG_NOATIME | \
+ FS_XFLAG_NODUMP | \
+ FS_XFLAG_PROJINHERIT)
+
+#define FUSE2FS_MODIFIABLE_IXFLAGS (FS_IMMUTABLE_FL | \
+ FS_APPEND_FL | \
+ FS_SYNC_FL | \
+ FS_NOATIME_FL | \
+ FS_NODUMP_FL | \
+ FS_PROJINHERIT_FL)
+
+static inline int set_xflags(struct ext2_inode_large *inode, __u32 xflags)
+{
+ __u32 iflags;
+
+ if (xflags & ~FUSE2FS_MODIFIABLE_XFLAGS)
+ return -EINVAL;
+
+ iflags = fsxflags_to_iflags(xflags);
+ inode->i_flags = (inode->i_flags & ~FUSE2FS_MODIFIABLE_IXFLAGS) |
+ (iflags & FUSE2FS_MODIFIABLE_IXFLAGS);
+ return 0;
+}
+
static int ioctl_fssetxattr(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
void *data)
{
@@ -3900,7 +3927,6 @@ static int ioctl_fssetxattr(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
int ret;
struct fuse_context *ctxt = fuse_get_context();
struct fsxattr *fsx = data;
- __u32 flags = fsxflags_to_iflags(fsx->fsx_xflags);
unsigned int inode_size;
FUSE2FS_CHECK_MAGIC(fs, fh, FUSE2FS_FILE_MAGIC);
@@ -3912,7 +3938,7 @@ static int ioctl_fssetxattr(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid)
return -EPERM;
- ret = set_iflags(&inode, flags);
+ ret = set_xflags(&inode, fsx->fsx_xflags);
if (ret)
return ret;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 11/16] fuse2fs: fix default acls propagating to non-dir children
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (9 preceding siblings ...)
2025-10-16 15:42 ` [PATCH 10/16] fuse2fs: fix fssetxattr flags updates Darrick J. Wong
@ 2025-10-16 15:42 ` Darrick J. Wong
2025-10-16 15:42 ` [PATCH 12/16] fuse2fs: don't update atime when reading executable file content Darrick J. Wong
` (8 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:42 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
New non-directory children should not be copying the default ACLs of the
parents. Caught by generic/099 in fuseblk/iomap mode.
Cc: <linux-ext4@vger.kernel.org> # v1.47.3
Fixes: 2c7900387620a6 ("fuse2fs: propagate default ACLs to new children")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 5e610be2760a5a..0f655c41372cc7 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -1167,13 +1167,13 @@ static int __setxattr(struct fuse2fs *ff, ext2_ino_t ino, const char *name,
}
static int propagate_default_acls(struct fuse2fs *ff, ext2_ino_t parent,
- ext2_ino_t child)
+ ext2_ino_t child, mode_t mode)
{
void *def;
size_t deflen;
int ret;
- if (!ff->acl)
+ if (!ff->acl || S_ISDIR(mode))
return 0;
ret = __getxattr(ff, parent, XATTR_NAME_POSIX_ACL_DEFAULT, &def,
@@ -1346,7 +1346,7 @@ static int op_mknod(const char *path, mode_t mode, dev_t dev)
ext2fs_inode_alloc_stats2(fs, child, 1, 0);
- ret = propagate_default_acls(ff, parent, child);
+ ret = propagate_default_acls(ff, parent, child, inode.i_mode);
if (ret)
goto out2;
out2:
@@ -1474,7 +1474,7 @@ static int op_mkdir(const char *path, mode_t mode)
goto out3;
}
- ret = propagate_default_acls(ff, parent, child);
+ ret = propagate_default_acls(ff, parent, child, inode.i_mode);
if (ret)
goto out3;
@@ -3543,7 +3543,7 @@ static int op_create(const char *path, mode_t mode, struct fuse_file_info *fp)
ext2fs_inode_alloc_stats2(fs, child, 1, 0);
- ret = propagate_default_acls(ff, parent, child);
+ ret = propagate_default_acls(ff, parent, child, inode.i_mode);
if (ret)
goto out2;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 12/16] fuse2fs: don't update atime when reading executable file content
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (10 preceding siblings ...)
2025-10-16 15:42 ` [PATCH 11/16] fuse2fs: fix default acls propagating to non-dir children Darrick J. Wong
@ 2025-10-16 15:42 ` Darrick J. Wong
2025-10-16 15:43 ` [PATCH 13/16] fuse2fs: fix in_file_group missing the primary process gid Darrick J. Wong
` (7 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:42 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
The kernel doesn't update the atime of program files when it's paging
their content into memory, so fuse2fs shouldn't either. Found by
generic/120.
Cc: <linux-ext4@vger.kernel.org> # v1.43
Fixes: 81cbf1ef4f5dab ("misc: add fuse2fs, a FUSE server for e2fsprogs")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 0f655c41372cc7..0ecdd4f9e93225 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -207,6 +207,7 @@ struct fuse2fs_file_handle {
unsigned long magic;
ext2_ino_t ino;
int open_flags;
+ int check_flags;
};
/* Main program context */
@@ -2672,6 +2673,7 @@ static int __op_open(struct fuse2fs *ff, const char *path,
ret = check_inum_access(ff, file->ino, X_OK);
if (ret)
goto out;
+ check = X_OK;
} else
goto out;
}
@@ -2682,6 +2684,7 @@ static int __op_open(struct fuse2fs *ff, const char *path,
goto out;
}
+ file->check_flags = check;
fp->fh = (uintptr_t)file;
out:
@@ -2750,7 +2753,7 @@ static int op_read(const char *path EXT2FS_ATTR((unused)), char *buf,
goto out;
}
- if (fs_writeable(fs)) {
+ if (fh->check_flags != X_OK && fs_writeable(fs)) {
ret = update_atime(fs, fh->ino);
if (ret)
goto out;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 13/16] fuse2fs: fix in_file_group missing the primary process gid
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (11 preceding siblings ...)
2025-10-16 15:42 ` [PATCH 12/16] fuse2fs: don't update atime when reading executable file content Darrick J. Wong
@ 2025-10-16 15:43 ` Darrick J. Wong
2025-10-16 15:43 ` [PATCH 14/16] fuse2fs: work around EBUSY discard returns from dm-thinp Darrick J. Wong
` (6 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:43 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
I forgot that Unix processes have both a primary group id and a list of
supplementary group ids. The primary is provided by the fuse client;
the supplemental groups are noted by the Groups: field of
/proc/self/status.
If a process does not have /any/ supplemental group ids, then
in_file_group returns the wrong answer if the inode gid matches the
group id provided by the fuse client because it doesn't check that
anymore. Make it so the primary group id check always happens.
Found by generic/375.
Cc: <linux-ext4@vger.kernel.org> # v1.47.3
Fixes: 3469e6ff606af8 ("fuse2fs: fix group membership checking in op_chmod")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 0ecdd4f9e93225..b8db298cde202f 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -2303,10 +2303,14 @@ static int in_file_group(struct fuse_context *ctxt,
gid_t gid = inode_gid(*inode);
int ret;
+ /* If the inode gid matches the process' primary group, we're done. */
+ if (ctxt->gid == gid)
+ return 1;
+
ret = get_req_groups(ff, &gids, &nr_gids);
if (ret == -ENOENT) {
/* magic return code for "could not get caller group info" */
- return ctxt->gid == inode_gid(*inode);
+ return 0;
}
if (ret < 0)
return ret;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 14/16] fuse2fs: work around EBUSY discard returns from dm-thinp
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (12 preceding siblings ...)
2025-10-16 15:43 ` [PATCH 13/16] fuse2fs: fix in_file_group missing the primary process gid Darrick J. Wong
@ 2025-10-16 15:43 ` Darrick J. Wong
2025-10-16 15:43 ` [PATCH 15/16] fuse2fs: check free space when creating a symlink Darrick J. Wong
` (5 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:43 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
generic/500 has this interesting failure mode when fuse2fs is running in
fuseblk mode:
--- /run/fstests/bin/tests/generic/500.out 2025-07-15 14:45:15.092576090 -0700
+++ /var/tmp/fstests/generic/500.out.bad 2025-09-05 15:09:35.211499883 -0700
@@ -1,2 +1,22 @@
QA output created by 500
+fstrim: /opt: FITRIM ioctl failed: Device or resource busy
Apparently you can overwhelm dm-thinp with a large number of discard
requests, at which point it starts returning EBUSY. This is unexpected
behavior but let's mask that off because discard is advisory anyways.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index b8db298cde202f..6864466435abfb 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -4038,6 +4038,14 @@ static int ioctl_fitrim(struct fuse2fs *ff, struct fuse2fs_file_handle *fh,
if (b - start >= minlen) {
err = io_channel_discard(fs->io, start, b - start);
+ if (err == EBUSY) {
+ /*
+ * Apparently dm-thinp can return EBUSY when
+ * it's too busy deallocating thinp units to
+ * deallocate more. Swallow these errors.
+ */
+ err = 0;
+ }
if (err)
return translate_error(fs, fh->ino, err);
cleared += b - start;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 15/16] fuse2fs: check free space when creating a symlink
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (13 preceding siblings ...)
2025-10-16 15:43 ` [PATCH 14/16] fuse2fs: work around EBUSY discard returns from dm-thinp Darrick J. Wong
@ 2025-10-16 15:43 ` Darrick J. Wong
2025-10-16 15:43 ` [PATCH 16/16] fuse2fs: spot check clean journals Darrick J. Wong
` (4 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:43 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
Make sure we have enough space to create the symlink and its remote
block.
Cc: <linux-ext4@vger.kernel.org> # v1.43
Fixes: 81cbf1ef4f5dab ("misc: add fuse2fs, a FUSE server for e2fsprogs")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 6864466435abfb..210807ea493f51 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -1825,6 +1825,10 @@ static int op_symlink(const char *src, const char *dest)
*node_name = 0;
pthread_mutex_lock(&ff->bfl);
+ if (!fs_can_allocate(ff, 1)) {
+ ret = -ENOSPC;
+ goto out2;
+ }
err = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, temp_path,
&parent);
*node_name = a;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 16/16] fuse2fs: spot check clean journals
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (14 preceding siblings ...)
2025-10-16 15:43 ` [PATCH 15/16] fuse2fs: check free space when creating a symlink Darrick J. Wong
@ 2025-10-16 15:43 ` Darrick J. Wong
2025-10-20 20:26 ` [PATCH 17/16] fuse2fs: recheck support after replaying journal Darrick J. Wong
` (3 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-16 15:43 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
Even though fuse2fs doesn't (yet) support writing new transactions to
the journal, we ought at least to check that the superblock is ok when
we mount a clean filesystem. This fixes complaints by ext4/012 about
mount failing to notice a corrupt journal.
Cc: <linux-ext4@vger.kernel.org> # v1.43
Fixes: 81cbf1ef4f5dab ("misc: add fuse2fs, a FUSE server for e2fsprogs")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
debugfs/journal.h | 2 ++
debugfs/journal.c | 2 +-
misc/fuse2fs.c | 7 +++++++
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/debugfs/journal.h b/debugfs/journal.h
index 10b638ebaab5db..67b8c99828bb0d 100644
--- a/debugfs/journal.h
+++ b/debugfs/journal.h
@@ -18,6 +18,8 @@
errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j);
errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j);
errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
+errcode_t ext2fs_check_ext3_journal(ext2_filsys fs);
+
void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh);
void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh);
void jbd2_descr_block_csum_set(journal_t *j, struct buffer_head *bh);
diff --git a/debugfs/journal.c b/debugfs/journal.c
index a6d8d4c5adf9cf..f79abcccf6adea 100644
--- a/debugfs/journal.c
+++ b/debugfs/journal.c
@@ -681,7 +681,7 @@ static void ext2fs_journal_release(ext2_filsys fs, journal_t *journal,
* This function makes sure that the superblock fields regarding the
* journal are consistent.
*/
-static errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
+errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
{
struct ext2_super_block *sb = fs->super;
journal_t *journal;
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 210807ea493f51..e33b09de08a11f 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -192,6 +192,7 @@ static inline uint64_t round_down(uint64_t b, unsigned int align)
# define FL_ZERO_RANGE_FLAG (0)
#endif
+errcode_t ext2fs_check_ext3_journal(ext2_filsys fs);
errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
#ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jbd-debug */
@@ -4819,6 +4820,12 @@ int main(int argc, char *argv[])
ext2fs_clear_feature_journal_needs_recovery(global_fs->super);
ext2fs_mark_super_dirty(global_fs);
}
+ } else if (ext2fs_has_feature_journal(global_fs->super)) {
+ err = ext2fs_check_ext3_journal(global_fs);
+ if (err) {
+ translate_error(global_fs, 0, err);
+ goto out;
+ }
}
if (global_fs->flags & EXT2_FLAG_RW) {
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 17/16] fuse2fs: recheck support after replaying journal
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (15 preceding siblings ...)
2025-10-16 15:43 ` [PATCH 16/16] fuse2fs: spot check clean journals Darrick J. Wong
@ 2025-10-20 20:26 ` Darrick J. Wong
2025-10-20 20:26 ` [PATCH 18/16] fuse2fs: make norecovery behavior consistent with the kernel Darrick J. Wong
` (2 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-20 20:26 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
The journal could have contained a new primary superblock, so we need to
recheck feature support after recovering it, because otherwise fuse2fs
could blow up on an unsupported feature that was enabled by a journal
transaction.
We also don't need to clear needsrecovery or dirty the superblock after
recovering the journal because ext2fs_run_ext3_journal does that for us.
Remove those lines.
Cc: <linux-ext4@vger.kernel.org> # v1.43
Fixes: 81cbf1ef4f5dab ("misc: add fuse2fs, a FUSE server for e2fsprogs")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 60 ++++++++++++++++++++++++++++++++++----------------------
1 file changed, 36 insertions(+), 24 deletions(-)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index e33b09de08a11f..931e60f61e85b6 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -744,6 +744,36 @@ static int check_inum_access(struct fuse2fs *ff, ext2_ino_t ino, int mask)
return -EACCES;
}
+static errcode_t fuse2fs_check_support(struct fuse2fs *ff)
+{
+ ext2_filsys fs = ff->fs;
+
+ if (ext2fs_has_feature_quota(fs->super)) {
+ err_printf(ff, "%s\n", _("quotas not supported."));
+ return EXT2_ET_UNSUPP_FEATURE;
+ }
+ if (ext2fs_has_feature_verity(fs->super)) {
+ err_printf(ff, "%s\n", _("verity not supported."));
+ return EXT2_ET_UNSUPP_FEATURE;
+ }
+ if (ext2fs_has_feature_encrypt(fs->super)) {
+ err_printf(ff, "%s\n", _("encryption not supported."));
+ return EXT2_ET_UNSUPP_FEATURE;
+ }
+ if (ext2fs_has_feature_casefold(fs->super)) {
+ err_printf(ff, "%s\n", _("casefolding not supported."));
+ return EXT2_ET_UNSUPP_FEATURE;
+ }
+
+ if (fs->super->s_state & EXT2_ERROR_FS) {
+ err_printf(ff, "%s\n",
+ _("Errors detected; running e2fsck is required."));
+ return EXT2_ET_FILESYSTEM_CORRUPTED;
+ }
+
+ return 0;
+}
+
static void op_destroy(void *p EXT2FS_ATTR((unused)))
{
struct fuse_context *ctxt = fuse_get_context();
@@ -4771,29 +4801,9 @@ int main(int argc, char *argv[])
}
ret = 3;
-
- if (ext2fs_has_feature_quota(global_fs->super)) {
- err_printf(&fctx, "%s", _("quotas not supported."));
+ err = fuse2fs_check_support(&fctx);
+ if (err)
goto out;
- }
- if (ext2fs_has_feature_verity(global_fs->super)) {
- err_printf(&fctx, "%s", _("verity not supported."));
- goto out;
- }
- if (ext2fs_has_feature_encrypt(global_fs->super)) {
- err_printf(&fctx, "%s", _("encryption not supported."));
- goto out;
- }
- if (ext2fs_has_feature_casefold(global_fs->super)) {
- err_printf(&fctx, "%s", _("casefolding not supported."));
- goto out;
- }
-
- if (global_fs->super->s_state & EXT2_ERROR_FS) {
- err_printf(&fctx, "%s\n",
- _("Errors detected; running e2fsck is required."));
- goto out;
- }
/*
* ext4 can't do COW of shared blocks, so if the feature is enabled,
@@ -4817,8 +4827,10 @@ int main(int argc, char *argv[])
_("Please run e2fsck -fy."));
goto out;
}
- ext2fs_clear_feature_journal_needs_recovery(global_fs->super);
- ext2fs_mark_super_dirty(global_fs);
+
+ err = fuse2fs_check_support(&fctx);
+ if (err)
+ goto out;
}
} else if (ext2fs_has_feature_journal(global_fs->super)) {
err = ext2fs_check_ext3_journal(global_fs);
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 18/16] fuse2fs: make norecovery behavior consistent with the kernel
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (16 preceding siblings ...)
2025-10-20 20:26 ` [PATCH 17/16] fuse2fs: recheck support after replaying journal Darrick J. Wong
@ 2025-10-20 20:26 ` Darrick J. Wong
2025-10-20 20:27 ` [PATCH 19/16] fuse2fs: mount norecovery if main block device is readonly Darrick J. Wong
2025-10-21 13:22 ` [PATCHSET] fuse2fs: round 6 bug fixes Theodore Tso
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-20 20:26 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
Amazingly, norecovery/noload on the kernel ext4 driver allows a
read-write mount even for journalled filesystems. The one case where
mounting fails is if there's a journal and it's dirty AND you didn't
specify norecovery. Make the fuse2fs option behave the same as the
kernel.
Also, ext2fs_run_ext3_journal doesn't explicitly check EXT2_FILE_RW
state, which means fuse2fs must do that.
Found via ext4/271.
Cc: <linux-ext4@vger.kernel.org> # v1.43
Fixes: 81cbf1ef4f5dab ("misc: add fuse2fs, a FUSE server for e2fsprogs")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 931e60f61e85b6..9922747728a438 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -4818,6 +4818,11 @@ int main(int argc, char *argv[])
_("Mounting read-only without recovering journal."));
fctx.ro = 1;
global_fs->flags &= ~EXT2_FLAG_RW;
+ } else if (!(global_fs->flags & EXT2_FLAG_RW)) {
+ err_printf(&fctx, "%s\n",
+ _("Cannot replay journal on read-only device."));
+ ret = 32;
+ goto out;
} else {
log_printf(&fctx, "%s\n", _("Recovering journal."));
err = ext2fs_run_ext3_journal(&global_fs);
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 19/16] fuse2fs: mount norecovery if main block device is readonly
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (17 preceding siblings ...)
2025-10-20 20:26 ` [PATCH 18/16] fuse2fs: make norecovery behavior consistent with the kernel Darrick J. Wong
@ 2025-10-20 20:27 ` Darrick J. Wong
2025-10-21 13:22 ` [PATCHSET] fuse2fs: round 6 bug fixes Theodore Tso
19 siblings, 0 replies; 21+ messages in thread
From: Darrick J. Wong @ 2025-10-20 20:27 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4
From: Darrick J. Wong <djwong@kernel.org>
If the main block device is read-only, downgrade the mount to an ro
norecovery mount to match what the kernel does. This will make
generic/050 somewhat less grouchy.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
misc/fuse2fs.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 9922747728a438..83886faf2eada8 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -4773,6 +4773,19 @@ int main(int argc, char *argv[])
flags |= EXT2_FLAG_DIRECT_IO;
err = ext2fs_open2(fctx.device, options, flags, 0, 0, unix_io_manager,
&global_fs);
+ if (err == EPERM || err == EACCES) {
+ /*
+ * Source device cannot be opened for write. Under these
+ * circumstances, mount(8) will try again with a ro mount,
+ * and the kernel will open the block device readonly.
+ */
+ log_printf(&fctx, "%s\n",
+ _("WARNING: source write-protected, mounted read-only."));
+ flags &= ~EXT2_FLAG_RW;
+ fctx.ro = 1;
+ err = ext2fs_open2(fctx.device, options, flags, 0, 0,
+ unix_io_manager, &global_fs);
+ }
if (err) {
err_printf(&fctx, "%s.\n", error_message(err));
err_printf(&fctx, "%s\n", _("Please run e2fsck -fy."));
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCHSET] fuse2fs: round 6 bug fixes
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
` (18 preceding siblings ...)
2025-10-20 20:27 ` [PATCH 19/16] fuse2fs: mount norecovery if main block device is readonly Darrick J. Wong
@ 2025-10-21 13:22 ` Theodore Tso
19 siblings, 0 replies; 21+ messages in thread
From: Theodore Tso @ 2025-10-21 13:22 UTC (permalink / raw)
To: Darrick J. Wong; +Cc: linux-ext4
On Thu, Oct 16, 2025 at 08:39:57AM -0700, Darrick J. Wong wrote:
> Hi all,
>
> This series fixes more bugs in libext2fs and fuse2fs.
>
> If you're going to start using this code, I strongly recommend pulling
> from my git trees, which are linked below.
>
> Comments and questions are, as always, welcome.
>
> e2fsprogs git tree:
> https://git.kernel.org/cgit/linux/kernel/git/djwong/e2fsprogs.git/log/?h=fuse2fs-fixes
Thanks, I've merged fuse2fs-fixes_2025-10-17 from your tree.
- Ted
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2025-10-21 13:22 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-16 15:39 [PATCHSET] fuse2fs: round 6 bug fixes Darrick J. Wong
2025-10-16 15:40 ` [PATCH 01/16] debian/rules: remove extra pkg-config Darrick J. Wong
2025-10-16 15:40 ` [PATCH 02/16] libext2fs: use F_GETFL, not F_GETFD, in unixfd_open Darrick J. Wong
2025-10-16 15:40 ` [PATCH 03/16] libext2fs: don't look for O_EXCL in the F_GETFL output Darrick J. Wong
2025-10-16 15:40 ` [PATCH 04/16] libext2fs: fix ind_punch recursive block computation Darrick J. Wong
2025-10-16 15:41 ` [PATCH 05/16] libext2fs: the unixfd IO manager shouldn't close its fd Darrick J. Wong
2025-10-16 15:41 ` [PATCH 06/16] fuse2fs: update manpage Darrick J. Wong
2025-10-16 15:41 ` [PATCH 07/16] fuse2fs: quiet down EXT2_ET_RO_FILSYS errors Darrick J. Wong
2025-10-16 15:41 ` [PATCH 08/16] fuse2fs: free global_fs after a failed ext2fs_close call Darrick J. Wong
2025-10-16 15:42 ` [PATCH 09/16] fuse2fs: fix memory corruption when parsing mount options Darrick J. Wong
2025-10-16 15:42 ` [PATCH 10/16] fuse2fs: fix fssetxattr flags updates Darrick J. Wong
2025-10-16 15:42 ` [PATCH 11/16] fuse2fs: fix default acls propagating to non-dir children Darrick J. Wong
2025-10-16 15:42 ` [PATCH 12/16] fuse2fs: don't update atime when reading executable file content Darrick J. Wong
2025-10-16 15:43 ` [PATCH 13/16] fuse2fs: fix in_file_group missing the primary process gid Darrick J. Wong
2025-10-16 15:43 ` [PATCH 14/16] fuse2fs: work around EBUSY discard returns from dm-thinp Darrick J. Wong
2025-10-16 15:43 ` [PATCH 15/16] fuse2fs: check free space when creating a symlink Darrick J. Wong
2025-10-16 15:43 ` [PATCH 16/16] fuse2fs: spot check clean journals Darrick J. Wong
2025-10-20 20:26 ` [PATCH 17/16] fuse2fs: recheck support after replaying journal Darrick J. Wong
2025-10-20 20:26 ` [PATCH 18/16] fuse2fs: make norecovery behavior consistent with the kernel Darrick J. Wong
2025-10-20 20:27 ` [PATCH 19/16] fuse2fs: mount norecovery if main block device is readonly Darrick J. Wong
2025-10-21 13:22 ` [PATCHSET] fuse2fs: round 6 bug fixes Theodore Tso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).