From: "Darrick J. Wong" <djwong@kernel.org>
To: tytso@mit.edu
Cc: linux-ext4@vger.kernel.org
Subject: [PATCH 1/4] libext2fs: add POSIX advisory locking to the unix IO manager
Date: Thu, 06 Nov 2025 14:30:16 -0800 [thread overview]
Message-ID: <176246793347.2862036.7225995759685117808.stgit@frogsfrogsfrogs> (raw)
In-Reply-To: <176246793314.2862036.15869840216751367735.stgit@frogsfrogsfrogs>
From: Darrick J. Wong <djwong@kernel.org>
Add support for using flock() to protect the files opened by the Unix IO
manager so that other fuse2fs servers cannot stomp all over the
filesystem. We may some day want to adopt this in e2fsck.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
lib/ext2fs/ext2_io.h | 12 +++++++
debian/libext2fs2t64.symbols | 2 +
lib/ext2fs/io_manager.c | 16 +++++++++
lib/ext2fs/unix_io.c | 71 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h
index 39a4e8fcf6b515..61865d54d82490 100644
--- a/lib/ext2fs/ext2_io.h
+++ b/lib/ext2fs/ext2_io.h
@@ -102,7 +102,8 @@ struct struct_io_manager {
unsigned long long count);
errcode_t (*zeroout)(io_channel channel, unsigned long long block,
unsigned long long count);
- long reserved[14];
+ errcode_t (*flock)(io_channel channel, unsigned int flock_flags);
+ long reserved[13];
};
#define IO_FLAG_RW 0x0001
@@ -112,6 +113,13 @@ struct struct_io_manager {
#define IO_FLAG_THREADS 0x0010
#define IO_FLAG_NOCACHE 0x0020
+/* Prevent other programs from reading or writing to underlying storage */
+#define IO_CHANNEL_FLOCK_EXCLUSIVE 0x1
+/* Prevent other programs from writing to underlying storage */
+#define IO_CHANNEL_FLOCK_SHARED 0x2
+/* Return EBUSY if the lock cannot be taken immediately */
+#define IO_CHANNEL_FLOCK_TRYLOCK 0x4
+
/*
* Convenience functions....
*/
@@ -145,6 +153,8 @@ extern errcode_t io_channel_alloc_buf(io_channel channel,
extern errcode_t io_channel_cache_readahead(io_channel io,
unsigned long long block,
unsigned long long count);
+extern errcode_t io_channel_flock(io_channel io, unsigned int flock_flags);
+extern errcode_t io_channel_funlock(io_channel io);
#ifdef _WIN32
/* windows_io.c */
diff --git a/debian/libext2fs2t64.symbols b/debian/libext2fs2t64.symbols
index a3042c3292da93..b4d80161f1e1b4 100644
--- a/debian/libext2fs2t64.symbols
+++ b/debian/libext2fs2t64.symbols
@@ -693,6 +693,8 @@ libext2fs.so.2 libext2fs2t64 #MINVER#
io_channel_alloc_buf@Base 1.42.3
io_channel_cache_readahead@Base 1.43
io_channel_discard@Base 1.42
+ io_channel_flock@Base 1.47.99
+ io_channel_funlock@Base 1.47.99
io_channel_read_blk64@Base 1.41.1
io_channel_set_options@Base 1.37
io_channel_write_blk64@Base 1.41.1
diff --git a/lib/ext2fs/io_manager.c b/lib/ext2fs/io_manager.c
index dca6af09996b70..791ec7d14adbba 100644
--- a/lib/ext2fs/io_manager.c
+++ b/lib/ext2fs/io_manager.c
@@ -150,3 +150,19 @@ errcode_t io_channel_cache_readahead(io_channel io, unsigned long long block,
return io->manager->cache_readahead(io, block, count);
}
+
+errcode_t io_channel_flock(io_channel io, unsigned int flock_flags)
+{
+ if (!io->manager->flock)
+ return EXT2_ET_OP_NOT_SUPPORTED;
+
+ return io->manager->flock(io, flock_flags);
+}
+
+errcode_t io_channel_funlock(io_channel io)
+{
+ if (!io->manager->flock)
+ return EXT2_ET_OP_NOT_SUPPORTED;
+
+ return io->manager->flock(io, 0);
+}
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index 1456b4d4bbe212..abd33ba839f7e9 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -64,6 +64,9 @@
#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
#if defined(__linux__) && defined(_IO) && !defined(BLKROGET)
#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */
@@ -135,6 +138,7 @@ struct unix_private_data {
int flags;
int align;
int access_time;
+ int unix_flock_flags;
ext2_loff_t offset;
struct unix_cache *cache;
unsigned int cache_size;
@@ -875,6 +879,68 @@ int ext2fs_fstat(int fd, ext2fs_struct_stat *buf)
#endif
}
+#ifdef HAVE_SYS_FILE_H
+static errcode_t unix_funlock(io_channel channel)
+{
+ struct unix_private_data *data;
+ int ret;
+
+ 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 (data->unix_flock_flags) {
+ ret = flock(data->dev, LOCK_UN);
+ if (ret)
+ return errno;
+
+ data->unix_flock_flags = 0;
+ }
+
+ return 0;
+}
+
+static errcode_t unix_flock(io_channel channel, unsigned int flock_flags)
+{
+ struct unix_private_data *data;
+ int unix_flock_flags = 0;
+ errcode_t ret;
+
+ 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);
+
+ ret = unix_funlock(channel);
+ if (ret)
+ return ret;
+
+ if (flock_flags & IO_CHANNEL_FLOCK_EXCLUSIVE)
+ unix_flock_flags |= LOCK_EX;
+
+ if (flock_flags & IO_CHANNEL_FLOCK_SHARED)
+ unix_flock_flags |= LOCK_SH;
+
+ if (flock_flags & IO_CHANNEL_FLOCK_TRYLOCK)
+ unix_flock_flags |= LOCK_NB;
+
+ if (!unix_flock_flags)
+ return 0;
+
+ ret = flock(data->dev, unix_flock_flags);
+ if (ret < 0)
+ return errno;
+
+ data->unix_flock_flags = unix_flock_flags & ~LOCK_NB;
+ return 0;
+}
+#else
+#define unix_flock NULL
+
+static errcode_t unix_funlock(io_channel channel)
+{
+ return 0;
+}
+#endif /* HAVE_SYS_FILE_H */
static errcode_t unix_open_channel(const char *name, int fd,
int flags, io_channel *channel,
@@ -1061,6 +1127,7 @@ static errcode_t unix_open_channel(const char *name, int fd,
cleanup:
if (data) {
+ unix_funlock(io);
if (io->manager != unixfd_io_manager && data->dev >= 0)
close(data->dev);
if (data->cache) {
@@ -1147,6 +1214,8 @@ static errcode_t unix_close(io_channel channel)
retval = flush_cached_blocks(channel, data, 0);
#endif
+ unix_funlock(channel);
+
if (channel->manager != unixfd_io_manager && close(data->dev) < 0)
retval = errno;
free_cache(data);
@@ -1683,6 +1752,7 @@ static struct struct_io_manager struct_unix_manager = {
.discard = unix_discard,
.cache_readahead = unix_cache_readahead,
.zeroout = unix_zeroout,
+ .flock = unix_flock,
};
io_manager unix_io_manager = &struct_unix_manager;
@@ -1704,6 +1774,7 @@ static struct struct_io_manager struct_unixfd_manager = {
.discard = unix_discard,
.cache_readahead = unix_cache_readahead,
.zeroout = unix_zeroout,
+ .flock = unix_flock,
};
io_manager unixfd_io_manager = &struct_unixfd_manager;
next prev parent reply other threads:[~2025-11-06 22:30 UTC|newest]
Thread overview: 84+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-06 22:14 [PATCHBOMB 1.48] fuse2fs: new features, new server Darrick J. Wong
2025-11-06 22:27 ` [PATCHSET 1/9] fuse2fs: fix locking problems Darrick J. Wong
2025-11-06 22:30 ` Darrick J. Wong [this message]
2025-11-06 22:30 ` [PATCH 2/4] fuse2fs: try to lock filesystem image files before using them Darrick J. Wong
2025-11-06 22:30 ` [PATCH 3/4] fuse2fs: quiet down write-protect warning Darrick J. Wong
2025-11-06 22:31 ` [PATCH 4/4] fuse2fs: try to grab block device O_EXCL repeatedly Darrick J. Wong
2025-11-06 22:28 ` [PATCHSET 2/9] fuse2fs: add some easy new features Darrick J. Wong
2025-11-06 22:31 ` [PATCH 01/19] libext2fs: initialize htree when expanding directory Darrick J. Wong
2025-11-06 22:31 ` [PATCH 02/19] libext2fs: create link count adjustment helpers for dir_nlink Darrick J. Wong
2025-11-06 22:31 ` [PATCH 03/19] libext2fs: fix ext2fs_mmp_update Darrick J. Wong
2025-11-06 22:32 ` [PATCH 04/19] libext2fs: refactor aligned MMP buffer allocation Darrick J. Wong
2025-11-06 22:32 ` [PATCH 05/19] libext2fs: always use ext2fs_mmp_get_mem to allocate fs->mmp_buf Darrick J. Wong
2025-11-06 22:32 ` [PATCH 06/19] fuse2fs: check root directory while mounting Darrick J. Wong
2025-11-06 22:32 ` [PATCH 07/19] fuse2fs: read bitmaps asynchronously during initialization Darrick J. Wong
2025-11-06 22:33 ` [PATCH 08/19] fuse2fs: use file handles when possible Darrick J. Wong
2025-11-06 22:33 ` [PATCH 09/19] fuse2fs: implement dir seeking Darrick J. Wong
2025-11-06 22:33 ` [PATCH 10/19] fuse2fs: implement readdirplus Darrick J. Wong
2025-11-06 22:34 ` [PATCH 11/19] fuse2fs: implement dirsync mode Darrick J. Wong
2025-11-06 22:34 ` [PATCH 12/19] fuse2fs: only flush O_SYNC files on close Darrick J. Wong
2025-11-06 22:34 ` [PATCH 13/19] fuse2fs: improve want_extra_isize handling Darrick J. Wong
2025-11-06 22:34 ` [PATCH 14/19] fuse2fs: cache symlink targets in the kernel Darrick J. Wong
2025-11-06 22:35 ` [PATCH 15/19] fuse2fs: constrain worker thread count Darrick J. Wong
2025-11-06 22:35 ` [PATCH 16/19] fuse2fs: improve error handling behaviors Darrick J. Wong
2025-11-06 22:35 ` [PATCH 17/19] fuse2fs: fix link count overflows on dir_nlink filesystems Darrick J. Wong
2025-11-06 22:35 ` [PATCH 18/19] libsupport: add background thread manager Darrick J. Wong
2025-11-06 22:36 ` [PATCH 19/19] fuse2fs: implement MMP updates Darrick J. Wong
2025-11-06 22:28 ` [PATCHSET 3/9] fuse2fs: clean up operation startup Darrick J. Wong
2025-11-06 22:36 ` [PATCH 1/9] fuse2fs: rework FUSE2FS_CHECK_CONTEXT not to rely on global_fs Darrick J. Wong
2025-11-06 22:36 ` [PATCH 2/9] fuse2fs: rework checking file handles Darrick J. Wong
2025-11-06 22:36 ` [PATCH 3/9] fuse2fs: rework fallocate file handle extraction Darrick J. Wong
2025-11-06 22:37 ` [PATCH 4/9] fuse2fs: consolidate file handle checking in op_ioctl Darrick J. Wong
2025-11-06 22:37 ` [PATCH 5/9] fuse2fs: move fs assignment closer to locking the bfl Darrick J. Wong
2025-11-06 22:37 ` [PATCH 6/9] fuse2fs: clean up operation startup Darrick J. Wong
2025-11-06 22:37 ` [PATCH 7/9] fuse2fs: clean up operation completion Darrick J. Wong
2025-11-06 22:38 ` [PATCH 8/9] fuse2fs: clean up more boilerplate Darrick J. Wong
2025-11-06 22:38 ` [PATCH 9/9] fuse2fs: collect runtime of various operations Darrick J. Wong
2025-11-06 22:28 ` [PATCHSET 4/9] fuse2fs: refactor unmount code Darrick J. Wong
2025-11-06 22:38 ` [PATCH 1/3] fuse2fs: get rid of the global_fs variable Darrick J. Wong
2025-11-06 22:39 ` [PATCH 2/3] fuse2fs: hoist lockfile code Darrick J. Wong
2025-11-06 22:39 ` [PATCH 3/3] fuse2fs: hoist unmount code from main Darrick J. Wong
2025-11-06 22:28 ` [PATCHSET 5/9] fuse2fs: refactor mount code Darrick J. Wong
2025-11-06 22:39 ` [PATCH 1/3] fuse2fs: split filesystem mounting into helper functions Darrick J. Wong
2025-11-06 22:39 ` [PATCH 2/3] fuse2fs: register as an IO flusher thread Darrick J. Wong
2025-11-06 22:40 ` [PATCH 3/3] fuse2fs: adjust OOM killer score if possible Darrick J. Wong
2025-11-06 22:29 ` [PATCHSET 6/9] fuse2fs: improve operation tracing Darrick J. Wong
2025-11-06 22:40 ` [PATCH 1/4] fuse2fs: hook library error message printing Darrick J. Wong
2025-11-06 22:40 ` [PATCH 2/4] fuse2fs: print the function name in error messages, not the file name Darrick J. Wong
2025-11-06 22:40 ` [PATCH 3/4] fuse2fs: improve tracing for file range operations Darrick J. Wong
2025-11-06 22:41 ` [PATCH 4/4] fuse2fs: record thread id in debug trace data Darrick J. Wong
2025-11-06 22:29 ` [PATCHSET 7/9] fuse2fs: better tracking of writable state Darrick J. Wong
2025-11-06 22:41 ` [PATCH 1/3] fuse2fs: pass a struct fuse2fs to fs_writeable Darrick J. Wong
2025-11-06 22:41 ` [PATCH 2/3] fuse2fs: track our own writable state Darrick J. Wong
2025-11-06 22:41 ` [PATCH 3/3] fuse2fs: enable the shutdown ioctl Darrick J. Wong
2025-11-06 22:29 ` [PATCHSET 8/9] fuse2fs: upgrade to libfuse 3.17 Darrick J. Wong
2025-11-06 22:42 ` [PATCH 1/4] fuse2fs: bump library version Darrick J. Wong
2025-11-06 22:42 ` [PATCH 2/4] fuse2fs: wrap the fuse_set_feature_flag helper for older libfuse Darrick J. Wong
2025-11-06 22:42 ` [PATCH 3/4] fuse2fs: disable nfs exports Darrick J. Wong
2025-11-06 22:43 ` [PATCH 4/4] fuse2fs: drop fuse 2.x support code Darrick J. Wong
2025-11-06 22:30 ` [PATCHSET 9/9] fuse4fs: fork a low level fuse server Darrick J. Wong
2025-11-06 22:43 ` [PATCH 01/23] fuse2fs: separate libfuse3 and fuse2fs detection in configure Darrick J. Wong
2025-11-06 22:43 ` [PATCH 02/23] fuse2fs: start porting fuse2fs to lowlevel libfuse API Darrick J. Wong
2025-11-06 22:43 ` [PATCH 03/23] debian: create new package for fuse4fs Darrick J. Wong
2025-11-06 22:44 ` [PATCH 04/23] fuse4fs: namespace some helpers Darrick J. Wong
2025-11-07 8:09 ` Amir Goldstein
2025-11-08 0:25 ` Darrick J. Wong
2025-11-06 22:44 ` [PATCH 05/23] fuse4fs: convert to low level API Darrick J. Wong
2025-11-06 22:44 ` [PATCH 06/23] libsupport: port the kernel list.h to libsupport Darrick J. Wong
2025-11-06 22:44 ` [PATCH 07/23] libsupport: add a cache Darrick J. Wong
2025-11-06 22:45 ` [PATCH 08/23] cache: disable debugging Darrick J. Wong
2025-11-06 22:45 ` [PATCH 09/23] cache: use modern list iterator macros Darrick J. Wong
2025-11-06 22:45 ` [PATCH 10/23] cache: embed struct cache in the owner Darrick J. Wong
2025-11-06 22:45 ` [PATCH 11/23] cache: pass cache pointer to callbacks Darrick J. Wong
2025-11-06 22:46 ` [PATCH 12/23] cache: pass a private data pointer through cache_walk Darrick J. Wong
2025-11-06 22:46 ` [PATCH 13/23] cache: add a helper to grab a new refcount for a cache_node Darrick J. Wong
2025-11-06 22:46 ` [PATCH 14/23] cache: return results of a cache flush Darrick J. Wong
2025-11-06 22:47 ` [PATCH 15/23] cache: add a "get only if incore" flag to cache_node_get Darrick J. Wong
2025-11-06 22:47 ` [PATCH 16/23] cache: support gradual expansion Darrick J. Wong
2025-11-06 22:47 ` [PATCH 17/23] cache: support updating maxcount and flags Darrick J. Wong
2025-11-06 22:47 ` [PATCH 18/23] cache: support channging flags Darrick J. Wong
2025-11-06 22:48 ` [PATCH 19/23] cache: implement automatic shrinking Darrick J. Wong
2025-11-06 22:48 ` [PATCH 20/23] fuse4fs: add cache to track open files Darrick J. Wong
2025-11-06 22:48 ` [PATCH 21/23] fuse4fs: use the orphaned inode list Darrick J. Wong
2025-11-06 22:48 ` [PATCH 22/23] fuse4fs: implement FUSE_TMPFILE Darrick J. Wong
2025-11-06 22:49 ` [PATCH 23/23] fuse4fs: create incore reverse orphan list Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=176246793347.2862036.7225995759685117808.stgit@frogsfrogsfrogs \
--to=djwong@kernel.org \
--cc=linux-ext4@vger.kernel.org \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox