diff options
author | Christian Brauner <brauner@kernel.org> | 2024-08-30 15:04:48 +0200 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2024-09-09 11:58:07 +0200 |
commit | ed904935c3992ec4178a38f61eca8ce7303ae1a0 (patch) | |
tree | 7cedd353d8252443915b0b4c7a25cc9b3bcff199 /fs/read_write.c | |
parent | b8c7451928ab2698653966a54ab5fff2fce484ff (diff) |
fs: use must_set_pos()
Make generic_file_llseek_size() use must_set_pos(). We'll use
must_set_pos() in another helper in a minutes. Remove __maybe_unused
from must_set_pos() now that it's used.
Link: https://lore.kernel.org/r/20240830-vfs-file-f_version-v1-7-6d3e4816aa7b@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/read_write.c')
-rw-r--r-- | fs/read_write.c | 52 |
1 files changed, 14 insertions, 38 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index 5434467f5c05..b07e48cd81d1 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -98,8 +98,7 @@ EXPORT_SYMBOL(vfs_setpos); * Return: 0 if f_pos doesn't need to be updated, 1 if f_pos has to be * updated, and negative error code on failure. */ -static __maybe_unused int must_set_pos(struct file *file, loff_t *offset, - int whence, loff_t eof) +static int must_set_pos(struct file *file, loff_t *offset, int whence, loff_t eof) { switch (whence) { case SEEK_END: @@ -159,45 +158,22 @@ loff_t generic_file_llseek_size(struct file *file, loff_t offset, int whence, loff_t maxsize, loff_t eof) { - switch (whence) { - case SEEK_END: - offset += eof; - break; - case SEEK_CUR: - /* - * Here we special-case the lseek(fd, 0, SEEK_CUR) - * position-querying operation. Avoid rewriting the "same" - * f_pos value back to the file because a concurrent read(), - * write() or lseek() might have altered it - */ - if (offset == 0) - return file->f_pos; - /* - * f_lock protects against read/modify/write race with other - * SEEK_CURs. Note that parallel writes and reads behave - * like SEEK_SET. - */ - spin_lock(&file->f_lock); - offset = vfs_setpos(file, file->f_pos + offset, maxsize); - spin_unlock(&file->f_lock); + int ret; + + ret = must_set_pos(file, &offset, whence, eof); + if (ret < 0) + return ret; + if (ret == 0) return offset; - case SEEK_DATA: - /* - * In the generic case the entire file is data, so as long as - * offset isn't at the end of the file then the offset is data. - */ - if ((unsigned long long)offset >= eof) - return -ENXIO; - break; - case SEEK_HOLE: + + if (whence == SEEK_CUR) { /* - * There is a virtual hole at the end of the file, so as long as - * offset isn't i_size or larger, return i_size. + * f_lock protects against read/modify/write race with + * other SEEK_CURs. Note that parallel writes and reads + * behave like SEEK_SET. */ - if ((unsigned long long)offset >= eof) - return -ENXIO; - offset = eof; - break; + guard(spinlock)(&file->f_lock); + return vfs_setpos(file, file->f_pos + offset, maxsize); } return vfs_setpos(file, offset, maxsize); |