diff mbox series

[RFC,06/20] fs: add must_set_pos()

Message ID 20240830-vfs-file-f_version-v1-6-6d3e4816aa7b@kernel.org (mailing list archive)
State New
Headers show
Series file: remove f_version | expand

Commit Message

Christian Brauner Aug. 30, 2024, 1:04 p.m. UTC
Add a new must_set_pos() helper. We will use it in follow-up patches.
Temporarily mark it as unused. This is only done to keep the diff small
and reviewable.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/read_write.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

Comments

Jan Kara Sept. 3, 2024, 11:32 a.m. UTC | #1
On Fri 30-08-24 15:04:47, Christian Brauner wrote:
> Add a new must_set_pos() helper. We will use it in follow-up patches.
> Temporarily mark it as unused. This is only done to keep the diff small
> and reviewable.
> 
> Signed-off-by: Christian Brauner <brauner@kernel.org>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/read_write.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/fs/read_write.c b/fs/read_write.c
> index 66ff52860496..acee26989d95 100644
> --- a/fs/read_write.c
> +++ b/fs/read_write.c
> @@ -85,6 +85,58 @@ loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize)
>  }
>  EXPORT_SYMBOL(vfs_setpos);
>  
> +/**
> + * must_set_pos - check whether f_pos has to be updated
> + * @offset: offset to use
> + * @whence: type of seek operation
> + * @eof: end of file
> + *
> + * Check whether f_pos needs to be updated and update @offset according
> + * to @whence.
> + *
> + * 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)
> +{
> +	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) {
> +			*offset = file->f_pos;
> +			return 0;
> +		}
> +		break;
> +	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:
> +		/*
> +		 * 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.
> +		 */
> +		if ((unsigned long long)*offset >= eof)
> +			return -ENXIO;
> +		*offset = eof;
> +		break;
> +	}
> +
> +	return 1;
> +}
> +
>  /**
>   * generic_file_llseek_size - generic llseek implementation for regular files
>   * @file:	file structure to seek on
> 
> -- 
> 2.45.2
>
diff mbox series

Patch

diff --git a/fs/read_write.c b/fs/read_write.c
index 66ff52860496..acee26989d95 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -85,6 +85,58 @@  loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize)
 }
 EXPORT_SYMBOL(vfs_setpos);
 
+/**
+ * must_set_pos - check whether f_pos has to be updated
+ * @offset: offset to use
+ * @whence: type of seek operation
+ * @eof: end of file
+ *
+ * Check whether f_pos needs to be updated and update @offset according
+ * to @whence.
+ *
+ * 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)
+{
+	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) {
+			*offset = file->f_pos;
+			return 0;
+		}
+		break;
+	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:
+		/*
+		 * 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.
+		 */
+		if ((unsigned long long)*offset >= eof)
+			return -ENXIO;
+		*offset = eof;
+		break;
+	}
+
+	return 1;
+}
+
 /**
  * generic_file_llseek_size - generic llseek implementation for regular files
  * @file:	file structure to seek on