mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-28 18:10:32 +00:00
fs: don't needlessly acquire f_lock
Before 2011 there was no meaningful synchronization between read/readdir/write/seek. Only in commitef3d0fd27e
("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 commit9c225f2655
("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>
This commit is contained in:
parent
1bb772565f
commit
da06e3c517
10
fs/file.c
10
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);
|
(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 fdget_pos(unsigned int fd)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
struct fd f = fdget(fd);
|
||||||
|
@ -338,3 +338,4 @@ static inline bool path_mounted(const struct path *path)
|
|||||||
return path->mnt->mnt_root == path->dentry;
|
return path->mnt->mnt_root == path->dentry;
|
||||||
}
|
}
|
||||||
void file_f_owner_release(struct file *file);
|
void file_f_owner_release(struct file *file);
|
||||||
|
bool file_seek_cur_needs_f_lock(struct file *file);
|
||||||
|
@ -169,13 +169,18 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
|
|||||||
|
|
||||||
if (whence == SEEK_CUR) {
|
if (whence == SEEK_CUR) {
|
||||||
/*
|
/*
|
||||||
* f_lock protects against read/modify/write race with
|
* If the file requires locking via f_pos_lock we know
|
||||||
* other SEEK_CURs. Note that parallel writes and reads
|
* that mutual exclusion for SEEK_CUR on the same file
|
||||||
* behave like SEEK_SET.
|
* is guaranteed. If the file isn't locked, we take
|
||||||
|
* f_lock to protect against f_pos races with other
|
||||||
|
* SEEK_CURs.
|
||||||
*/
|
*/
|
||||||
|
if (file_seek_cur_needs_f_lock(file)) {
|
||||||
guard(spinlock)(&file->f_lock);
|
guard(spinlock)(&file->f_lock);
|
||||||
return vfs_setpos(file, file->f_pos + offset, maxsize);
|
return vfs_setpos(file, file->f_pos + offset, maxsize);
|
||||||
}
|
}
|
||||||
|
return vfs_setpos(file, file->f_pos + offset, maxsize);
|
||||||
|
}
|
||||||
|
|
||||||
return vfs_setpos(file, offset, maxsize);
|
return vfs_setpos(file, offset, maxsize);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user