diff mbox series

[RFC,18/20] fs: add f_pipe

Message ID 20240830-vfs-file-f_version-v1-18-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
Only regular files with FMODE_ATOMIC_POS and directories need
f_pos_lock. Place a new f_pipe member in a union with f_pos_lock
that they can use and make them stop abusing f_version in follow-up
patches.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 include/linux/fs.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

Comments

Jan Kara Sept. 3, 2024, 1:50 p.m. UTC | #1
On Fri 30-08-24 15:04:59, Christian Brauner wrote:
> Only regular files with FMODE_ATOMIC_POS and directories need
> f_pos_lock. Place a new f_pipe member in a union with f_pos_lock
> that they can use and make them stop abusing f_version in follow-up
> patches.
> 
> Signed-off-by: Christian Brauner <brauner@kernel.org>

What makes me a bit uneasy is that we do mutex_init() on the space in
struct file and then pipe_open() will clobber it. And then we eventually
call mutex_destroy() on the clobbered mutex. I think so far this does no
harm but mostly by luck. I think we need to make sure that when f_pos_lock
is unused, we don't even call mutex_init() / mutex_destroy() on it.

								Honza

> ---
>  include/linux/fs.h | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 3e6b3c1afb31..ca4925008244 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1001,6 +1001,7 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
>   * @f_cred: stashed credentials of creator/opener
>   * @f_path: path of the file
>   * @f_pos_lock: lock protecting file position
> + * @f_pipe: specific to pipes
>   * @f_pos: file position
>   * @f_version: file version
>   * @f_security: LSM security context of this file
> @@ -1026,7 +1027,12 @@ struct file {
>  	const struct cred		*f_cred;
>  	/* --- cacheline 1 boundary (64 bytes) --- */
>  	struct path			f_path;
> -	struct mutex			f_pos_lock;
> +	union {
> +		/* regular files (with FMODE_ATOMIC_POS) and directories */
> +		struct mutex		f_pos_lock;
> +		/* pipes */
> +		u64			f_pipe;
> +	};
>  	loff_t				f_pos;
>  	u64				f_version;
>  	/* --- cacheline 2 boundary (128 bytes) --- */
> 
> -- 
> 2.45.2
>
Christian Brauner Sept. 3, 2024, 2:31 p.m. UTC | #2
On Tue, Sep 03, 2024 at 03:50:55PM GMT, Jan Kara wrote:
> On Fri 30-08-24 15:04:59, Christian Brauner wrote:
> > Only regular files with FMODE_ATOMIC_POS and directories need
> > f_pos_lock. Place a new f_pipe member in a union with f_pos_lock
> > that they can use and make them stop abusing f_version in follow-up
> > patches.
> > 
> > Signed-off-by: Christian Brauner <brauner@kernel.org>
> 
> What makes me a bit uneasy is that we do mutex_init() on the space in
> struct file and then pipe_open() will clobber it. And then we eventually
> call mutex_destroy() on the clobbered mutex. I think so far this does no

We don't call mutex_destroy() on it and don't need to. And calling
mutex_init() is fine precisely because pipes do use it. It would be
really ugly do ensure that mutex_init() isn't called for pipes. But I'll
add a comment.
Jan Kara Sept. 4, 2024, 2:08 p.m. UTC | #3
On Tue 03-09-24 16:31:28, Christian Brauner wrote:
> On Tue, Sep 03, 2024 at 03:50:55PM GMT, Jan Kara wrote:
> > On Fri 30-08-24 15:04:59, Christian Brauner wrote:
> > > Only regular files with FMODE_ATOMIC_POS and directories need
> > > f_pos_lock. Place a new f_pipe member in a union with f_pos_lock
> > > that they can use and make them stop abusing f_version in follow-up
> > > patches.
> > > 
> > > Signed-off-by: Christian Brauner <brauner@kernel.org>
> > 
> > What makes me a bit uneasy is that we do mutex_init() on the space in
> > struct file and then pipe_open() will clobber it. And then we eventually
> > call mutex_destroy() on the clobbered mutex. I think so far this does no
> 
> We don't call mutex_destroy() on it and don't need to.

Ah, right, we don't bother with that for f_pos_lock.

> And calling mutex_init() is fine precisely because pipes do use it. It
> would be really ugly do ensure that mutex_init() isn't called for pipes.
> But I'll add a comment.

I'm not sure I understand what do you mean by "calling mutex_init() is fine
precisely because pipes do use it." Perhaps you meant "don't use it"?
Otherwise after looking at it for a while I agree the cure would be likely
worse than the disease so a comment is as good as it gets I guess.

								Honza
Al Viro Sept. 4, 2024, 2:21 p.m. UTC | #4
On Fri, Aug 30, 2024 at 03:04:59PM +0200, Christian Brauner wrote:
> Only regular files with FMODE_ATOMIC_POS and directories need
> f_pos_lock. Place a new f_pipe member in a union with f_pos_lock
> that they can use and make them stop abusing f_version in follow-up
> patches.

Not sure I like that - having lseek(2) use a separate primitive
instead of fdget_pos(), grabbing ->f_pos_lock for _everything_ that
has FMODE_LSEEK, directory or no directory, would simplify quite
a few things.  OTOH, that will affect only the explanation of validity -
pipes do *not* have FMODE_LSEEK, so it becomes "fdget_pos() and
fdget_seek() are the only things that might want ->f_pos_lock, and
neither touch it for pipes - fdget_pos() because FMODE_ATOMIC_POS
is not there and fdget_seek() because FMODE_LSEEK isn't".

Oh, well...
diff mbox series

Patch

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 3e6b3c1afb31..ca4925008244 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1001,6 +1001,7 @@  static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
  * @f_cred: stashed credentials of creator/opener
  * @f_path: path of the file
  * @f_pos_lock: lock protecting file position
+ * @f_pipe: specific to pipes
  * @f_pos: file position
  * @f_version: file version
  * @f_security: LSM security context of this file
@@ -1026,7 +1027,12 @@  struct file {
 	const struct cred		*f_cred;
 	/* --- cacheline 1 boundary (64 bytes) --- */
 	struct path			f_path;
-	struct mutex			f_pos_lock;
+	union {
+		/* regular files (with FMODE_ATOMIC_POS) and directories */
+		struct mutex		f_pos_lock;
+		/* pipes */
+		u64			f_pipe;
+	};
 	loff_t				f_pos;
 	u64				f_version;
 	/* --- cacheline 2 boundary (128 bytes) --- */