linux-unionfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: introduce struct fderr, convert overlayfs uses to that
       [not found] ` <20241003234732.GB147780@ZenIV>
@ 2024-10-04 10:47   ` Amir Goldstein
  2024-10-17 19:47     ` Al Viro
  0 siblings, 1 reply; 2+ messages in thread
From: Amir Goldstein @ 2024-10-04 10:47 UTC (permalink / raw)
  To: Al Viro
  Cc: linux-fsdevel, Christian Brauner, Jan Kara, Miklos Szeredi,
	overlayfs

On Fri, Oct 4, 2024 at 1:47 AM Al Viro <viro@zeniv.linux.org.uk> wrote:
>
> Similar to struct fd; unlike struct fd, it can represent
> error values.
>
> Accessors:
>
> * fd_empty(f):  true if f represents an error
> * fd_file(f):   just as for struct fd it yields a pointer to
>                 struct file if fd_empty(f) is false.  If
>                 fd_empty(f) is true, fd_file(f) is guaranteed
>                 _not_ to be an address of any object (IS_ERR()
>                 will be true in that case)
> * fd_err(f):    if f represents an error, returns that error,
>                 otherwise the return value is junk.
>
> Constructors:
>
> * ERR_FDERR(-E...):     an instance encoding given error [ERR_FDERR, perhaps?]
> * BORROWED_FDERR(file): if file points to a struct file instance,
>                         return a struct fderr representing that file
>                         reference with no flags set.
>                         if file is an ERR_PTR(-E...), return a struct
>                         fderr representing that error.
>                         file MUST NOT be NULL.
> * CLONED_FDERR(file):   similar, but in case when file points to
>                         a struct file instance, set FDPUT_FPUT in flags.
>
> Same destructor as for struct fd; I'm not entirely convinced that
> playing with _Generic is a good idea here, but for now let's go
> that way...
>
> See fs/overlayfs/file.c for example of use.

I had already posted an alternative code for overlayfs, but in case this
is going to be used anyway in overlayfs or in another code, see some
comments below...

>
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
>  fs/overlayfs/file.c  | 128 +++++++++++++++++++++----------------------
>  include/linux/file.h |  37 +++++++++++--
>  2 files changed, 95 insertions(+), 70 deletions(-)
>

[...]

> diff --git a/include/linux/file.h b/include/linux/file.h
> index f98de143245a..d85352523368 100644
> --- a/include/linux/file.h
> +++ b/include/linux/file.h
> @@ -44,13 +44,26 @@ static inline void fput_light(struct file *file, int fput_needed)
>  struct fd {
>         unsigned long word;
>  };
> +
> +/* either a reference to struct file + flags
> + * (cloned vs. borrowed, pos locked), with
> + * flags stored in lower bits of value,
> + * or an error (represented by small negative value).
> + */
> +struct fderr {
> +       unsigned long word;
> +};
> +
>  #define FDPUT_FPUT       1
>  #define FDPUT_POS_UNLOCK 2
>
> +#define fd_empty(f)    _Generic((f), \
> +                               struct fd: unlikely(!(f).word), \
> +                               struct fderr: IS_ERR_VALUE((f).word))


I suggest adding a fd_is_err(f) helper to rhyme with IS_ERR().

>  #define fd_file(f) ((struct file *)((f).word & ~(FDPUT_FPUT|FDPUT_POS_UNLOCK)))
> -static inline bool fd_empty(struct fd f)
> +static inline long fd_err(struct fderr f)
>  {
> -       return unlikely(!f.word);
> +       return (long)f.word;
>  }
>
>  #define EMPTY_FD (struct fd){0}
> @@ -63,11 +76,25 @@ static inline struct fd CLONED_FD(struct file *f)
>         return (struct fd){(unsigned long)f | FDPUT_FPUT};
>  }
>
> -static inline void fdput(struct fd fd)
> +static inline struct fderr ERR_FDERR(long n)
> +{
> +       return (struct fderr){(unsigned long)n};
> +}
> +static inline struct fderr BORROWED_FDERR(struct file *f)
>  {
> -       if (fd.word & FDPUT_FPUT)
> -               fput(fd_file(fd));
> +       return (struct fderr){(unsigned long)f};
>  }
> +static inline struct fderr CLONED_FDERR(struct file *f)
> +{
> +       if (IS_ERR(f))
> +               return BORROWED_FDERR(f);
> +       return (struct fderr){(unsigned long)f | FDPUT_FPUT};
> +}
> +
> +#define fdput(f)       (void) (_Generic((f), \
> +                               struct fderr: IS_ERR_VALUE((f).word),   \

Should that be !IS_ERR_VALUE((f).word)?

> +                               struct fd: true) && \
> +                           ((f).word & FDPUT_FPUT) && (fput(fd_file(f)),0))
>

or better yet

#define fd_is_err(f) _Generic((f), \
                                struct fd: false, \
                                struct fderr: IS_ERR_VALUE((f).word))
#define fdput(f) (!fd_is_err(f) && ((f).word & FDPUT_FPUT) &&
(fput(fd_file(f)),0))

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: introduce struct fderr, convert overlayfs uses to that
  2024-10-04 10:47   ` introduce struct fderr, convert overlayfs uses to that Amir Goldstein
@ 2024-10-17 19:47     ` Al Viro
  0 siblings, 0 replies; 2+ messages in thread
From: Al Viro @ 2024-10-17 19:47 UTC (permalink / raw)
  To: Amir Goldstein
  Cc: linux-fsdevel, Christian Brauner, Jan Kara, Miklos Szeredi,
	overlayfs

On Fri, Oct 04, 2024 at 12:47:09PM +0200, Amir Goldstein wrote:

> I had already posted an alternative code for overlayfs, but in case this
> is going to be used anyway in overlayfs or in another code, see some
> comments below...

As far as I can see, the current #overlayfs-next kills the case for
struct fderr; we might eventually get a valid use for it, but for the
time being I'm going to strip the overlayfs-related parts of that branch
(obviously), fix the braino you've spotted in fdput() and archive the
branch in case it's ever needed.

> > +#define fd_empty(f)    _Generic((f), \
> > +                               struct fd: unlikely(!(f).word), \
> > +                               struct fderr: IS_ERR_VALUE((f).word))
> 
> 
> I suggest adding a fd_is_err(f) helper to rhyme with IS_ERR().

Umm...  Dropping fd_empty() for that one, you mean?

> > +#define fdput(f)       (void) (_Generic((f), \
> > +                               struct fderr: IS_ERR_VALUE((f).word),   \
> 
> Should that be !IS_ERR_VALUE((f).word)?

It should, thanks for spotting that braino.
 
> or better yet
> 
> #define fd_is_err(f) _Generic((f), \
>                                 struct fd: false, \
>                                 struct fderr: IS_ERR_VALUE((f).word))

I think that's a bad idea; too likely to spill into struct fd users,
with "it's never false here" being a nasty surprise.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-10-17 19:47 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20241003234534.GM4017910@ZenIV>
     [not found] ` <20241003234732.GB147780@ZenIV>
2024-10-04 10:47   ` introduce struct fderr, convert overlayfs uses to that Amir Goldstein
2024-10-17 19:47     ` Al Viro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).