Re: [PATCH v2 17/21] backing-inode: add backing_inode_copyattr()

Amir Goldstein <[email protected]> Sat, 16 May 2026 23:32:50 +0200
Newsgroups org.kernel.vger.linux-unionfs,dev.linux.lists.fuse-devel
Message-ID <CAOQ4uxg9WT7WmJqQezgiCB1jOX_heW+=UJbbFntbfDUdm0H=tQ@mail.gmail.com>
On Sat, May 16, 2026 at 2:53 AM Joanne Koong <[email protected]> wrote:
>
> Move logic in ovl_copyattr() to a generic backing_inode_copyattr()
> function in a new fs/backing-inode.c, which other filesystems that use
> backing inodes (eg fuse passthrough) will use.
>
> Signed-off-by: Joanne Koong <[email protected]>
> ---
>  fs/Makefile                   |  2 +-
>  fs/backing-inode.c            | 43 +++++++++++++++++++++++++++++++++++
>  fs/overlayfs/util.c           | 33 +++------------------------
>  include/linux/backing-inode.h | 14 ++++++++++++


Nice!

Please add these files to
FILESYSTEMS [STACKABLE]
section in MAINTAINERS.

Otherwise, feel free to add:
Reviewed-by: Amir Goldstein <[email protected]>

There is one more cleanup patch required, now or later, to get rid of
some awkwardness in kernel fs code.
If you don't want to deal with it, I can take this cleanup later.

d_backing_inode() is a noop from the day it was added and has 177
call sites. Those call sites should be converted to d_inode() and
d_backing_inode() should go away.

backing_inode_security{,_novalidate}() are likewise unneeded
dups of inode_security{,_novalidate}() and should be removed.

Thanks,
Amir.

>  4 files changed, 61 insertions(+), 31 deletions(-)
>  create mode 100644 fs/backing-inode.c
>  create mode 100644 include/linux/backing-inode.h
>
> diff --git a/fs/Makefile b/fs/Makefile
> index cf4a745e9679..3f8a227d4938 100644
> --- a/fs/Makefile
> +++ b/fs/Makefile
> @@ -40,7 +40,7 @@ obj-$(CONFIG_COMPAT_BINFMT_ELF)       += compat_binfmt_elf.o
>  obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o
>  obj-$(CONFIG_BINFMT_FLAT)      += binfmt_flat.o
>
> -obj-$(CONFIG_FS_STACK)         += backing-file.o
> +obj-$(CONFIG_FS_STACK)         += backing-file.o backing-inode.o
>  obj-$(CONFIG_FS_MBCACHE)       += mbcache.o
>  obj-$(CONFIG_FS_POSIX_ACL)     += posix_acl.o
>  obj-$(CONFIG_NFS_COMMON)       += nfs_common/
> diff --git a/fs/backing-inode.c b/fs/backing-inode.c
> new file mode 100644
> index 000000000000..474770a1fa9d
> --- /dev/null
> +++ b/fs/backing-inode.c
> @@ -0,0 +1,43 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Common helpers for stackable filesystems and backing inodes.
> + */
> +
> +#include <linux/backing-inode.h>
> +
> +/*
> + * backing_inode_copyattr - copy inode attributes from a backing inode
> + *
> + * When a filesystem copies inode information from a backing layer to its own
> + * inode, it applies the idmapping of the backing mount, ensuring that
> + * the inode ownership will correctly reflect the ownership of the idmapped
> + * backing mount. For example, an idmapped backing mount mapping id 1001 to id
> + * 1000 will take care to map any backing inode owned by id 1001 to id 1000.
> + * These mapping helpers are nops when the backing mount isn't idmapped.
> + */
> +void backing_inode_copyattr(struct inode *inode,
> +                           const struct path *backing_path)
> +{
> +       struct inode *realinode;
> +       struct mnt_idmap *real_idmap;
> +       vfsuid_t vfsuid;
> +       vfsgid_t vfsgid;
> +
> +       realinode = d_inode_rcu(backing_path->dentry);
> +       real_idmap = mnt_idmap(backing_path->mnt);
> +
> +       spin_lock(&inode->i_lock);
> +       vfsuid = i_uid_into_vfsuid(real_idmap, realinode);
> +       vfsgid = i_gid_into_vfsgid(real_idmap, realinode);
> +
> +       inode->i_uid = vfsuid_into_kuid(vfsuid);
> +       inode->i_gid = vfsgid_into_kgid(vfsgid);
> +       inode->i_mode = realinode->i_mode;
> +       inode_set_atime_to_ts(inode, inode_get_atime(realinode));
> +       inode_set_mtime_to_ts(inode, inode_get_mtime(realinode));
> +       inode_set_ctime_to_ts(inode, inode_get_ctime(realinode));
> +       i_size_write(inode, i_size_read(realinode));
> +       spin_unlock(&inode->i_lock);
> +}
> +EXPORT_SYMBOL_GPL(backing_inode_copyattr);
> +
> diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
> index 3f1b763a8bb4..3e7d66c26c10 100644
> --- a/fs/overlayfs/util.c
> +++ b/fs/overlayfs/util.c
> @@ -16,6 +16,7 @@
>  #include <linux/namei.h>
>  #include <linux/ratelimit.h>
>  #include <linux/overflow.h>
> +#include <linux/backing-inode.h>
>  #include "overlayfs.h"
>
>  /* Get write access to upper mnt - may fail if upper sb was remounted ro */
> @@ -1503,38 +1504,10 @@ int ovl_sync_status(struct ovl_fs *ofs)
>         return errseq_check(&mnt->mnt_sb->s_wb_err, ofs->errseq);
>  }
>
> -/*
> - * ovl_copyattr() - copy inode attributes from layer to ovl inode
> - *
> - * When overlay copies inode information from an upper or lower layer to the
> - * relevant overlay inode it will apply the idmapping of the upper or lower
> - * layer when doing so ensuring that the ovl inode ownership will correctly
> - * reflect the ownership of the idmapped upper or lower layer. For example, an
> - * idmapped upper or lower layer mapping id 1001 to id 1000 will take care to
> - * map any lower or upper inode owned by id 1001 to id 1000. These mapping
> - * helpers are nops when the relevant layer isn't idmapped.
> - */
>  void ovl_copyattr(struct inode *inode)
>  {
>         struct path realpath;
> -       struct inode *realinode;
> -       struct mnt_idmap *real_idmap;
> -       vfsuid_t vfsuid;
> -       vfsgid_t vfsgid;
>
> -       realinode = ovl_i_path_real(inode, &realpath);
> -       real_idmap = mnt_idmap(realpath.mnt);
> -
> -       spin_lock(&inode->i_lock);
> -       vfsuid = i_uid_into_vfsuid(real_idmap, realinode);
> -       vfsgid = i_gid_into_vfsgid(real_idmap, realinode);
> -
> -       inode->i_uid = vfsuid_into_kuid(vfsuid);
> -       inode->i_gid = vfsgid_into_kgid(vfsgid);
> -       inode->i_mode = realinode->i_mode;
> -       inode_set_atime_to_ts(inode, inode_get_atime(realinode));
> -       inode_set_mtime_to_ts(inode, inode_get_mtime(realinode));
> -       inode_set_ctime_to_ts(inode, inode_get_ctime(realinode));
> -       i_size_write(inode, i_size_read(realinode));
> -       spin_unlock(&inode->i_lock);
> +       ovl_i_path_real(inode, &realpath);
> +       backing_inode_copyattr(inode, &realpath);
>  }
> diff --git a/include/linux/backing-inode.h b/include/linux/backing-inode.h
> new file mode 100644
> index 000000000000..6b43cba9fabd
> --- /dev/null
> +++ b/include/linux/backing-inode.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Common helpers for stackable filesystems and backing inodes.
> + */
> +
> +#ifndef _LINUX_BACKING_INODE_H
> +#define _LINUX_BACKING_INODE_H
> +
> +#include <linux/fs.h>
> +
> +void backing_inode_copyattr(struct inode *inode,
> +                           const struct path *backing_path);
> +
> +#endif /* _LINUX_BACKING_INODE_H */
> --
> 2.52.0
>