diff options
author | Christian Brauner <brauner@kernel.org> | 2025-02-07 15:10:33 +0100 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2025-02-21 10:25:32 +0100 |
commit | da06e3c5179467f9ef7caffb512ef111a70afde1 (patch) | |
tree | ef35a14c19b2d3f2d364d1ef5b9740e1208c187c /fs/file.c | |
parent | 1bb772565f327291b0a463b125c7646dc45ae8b4 (diff) |
fs: don't needlessly acquire f_lock
Before 2011 there was no meaningful synchronization between
read/readdir/write/seek. Only in commit
ef3d0fd27e90 ("vfs: do (nearly) lockless generic_file_llseek")
synchronization was added for SEEK_CUR by taking f_lock around
vfs_setpos().
Then in 2014 full synchronization between read/readdir/write/seek was
added in commit 9c225f2655e3 ("vfs: atomic f_pos accesses as per POSIX")
by introducing f_pos_lock for regular files with FMODE_ATOMIC_POS and
for directories. At that point taking f_lock became unnecessary for such
files.
So only acquire f_lock for SEEK_CUR if this isn't a file that would have
acquired f_pos_lock if necessary.
Link: https://lore.kernel.org/r/20250207-daten-mahlzeit-99d2079864fb@brauner
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/file.c')
-rw-r--r-- | fs/file.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/file.c b/fs/file.c index d868cdb95d1e..44efdc8c1e27 100644 --- a/fs/file.c +++ b/fs/file.c @@ -1182,6 +1182,16 @@ static inline bool file_needs_f_pos_lock(struct file *file) (file_count(file) > 1 || file->f_op->iterate_shared); } +bool file_seek_cur_needs_f_lock(struct file *file) +{ + if (!(file->f_mode & FMODE_ATOMIC_POS) && !file->f_op->iterate_shared) + return false; + + VFS_WARN_ON_ONCE((file_count(file) > 1) && + !mutex_is_locked(&file->f_pos_lock)); + return true; +} + struct fd fdget_pos(unsigned int fd) { struct fd f = fdget(fd); |