Commit 1448959fe3d0 for kernel
commit 1448959fe3d013ffdb8302d17e4a8fdad2d2da95
Author: Christian Brauner <brauner@kernel.org>
Date: Fri Nov 6 14:14:35 2026 +0100
fs: fix the SEEK_CUR f_lock condition
Commit da06e3c51794 ("fs: don't needlessly acquire f_lock") wanted to
skip f_lock for SEEK_CUR on files that already serialize f_pos through
f_pos_lock, i.e. FMODE_ATOMIC_POS files and directories, and keep it
for everything else. The condition it added does the opposite:
file_seek_cur_needs_f_lock() returns false exactly for the files that
never take f_pos_lock and true for the ones that do.
So since v6.15 a SEEK_CUR on a shared block device or on a character
device that uses fixed_size_llseek() updates f_pos without any lock and
two concurrent calls can lose an update, while regular files and
directories pay for a spinlock they don't need.
Invert the condition.
Fixes: da06e3c51794 ("fs: don't needlessly acquire f_lock")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261106-work-file-seek_f_lock-v1-1-5b9a6c2928d4@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
diff --git a/fs/file.c b/fs/file.c
index 4cd40dfa6129..fd08d34874ac 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -1387,14 +1387,18 @@ static inline bool file_needs_f_pos_lock(struct file *file)
bool file_seek_cur_needs_f_lock(struct file *file)
{
- if (!(file->f_mode & FMODE_ATOMIC_POS) && !file->f_op->iterate_shared)
- return false;
-
/*
+ * Files that go through f_pos_lock when they are shared, i.e.
+ * FMODE_ATOMIC_POS files and directories, don't need f_lock for a
+ * SEEK_CUR. Everything else does, since nothing else serializes
+ * the f_pos update.
+ *
* Note that we are not guaranteed to be called after fdget_pos() on
* this file obj, in which case the caller is expected to provide the
* appropriate locking.
*/
+ if ((file->f_mode & FMODE_ATOMIC_POS) || file->f_op->iterate_shared)
+ return false;
return true;
}