From 03583703045baa71f92be2bdf72a9d95ef0b5645 Mon Sep 17 00:00:00 2001 From: Cheyenne Wills Date: Wed, 29 Mar 2023 12:11:38 -0600 Subject: [PATCH 4/4] Linux 6.3: Use mnt_idmap for inode op functions Through a series of Linux 6.3 commits starting with: 'f2fs: project ids aren't idmapped' (64b4cdf22f) and ending with 'fs: move mnt_idmap' (3707d84c13) the inode operations functions were changed to take a mnt_idmap structure instead of a user_namespace structure. These were pulled in via the the merge commit: 'Pull vfs idmapping updates from Christian Brauner' (05e6295f7b) The commit message for the merge contains background and overall information for this conversion. The above change simply changes the functions to use a different structure (mnt_idmap instead of user_namespace). For afs, it is a simple change to swap the structures. But for some of the Linux calls (generic_fillattr(), setattr_prepare(), and inode_op->setattr()) we would like to use the Linux symbol nop_mnt_idmap, but that symbol is exported as GPL only. Instead, we will obtain its address from the current task structure at libafs initialization (much the same way as obtaining current user namespace for afs_ns). Add autoconf tests to determine if inode_operations.create() uses the mnt_idmap structure. If so set a generic configure define for "IOP_TAKES_MNT_IDMAP". Update afs's inode operations functions to take and use a mnt_idmap instead of a user_namespace. At libafs initialization, obtain the mnt_idmap from the current task and save it as an afs global variable, afs_mnt_idmap, to be used where needed. Reviewed-on: https://gerrit.openafs.org/15347 Reviewed-by: Mark Vitale Tested-by: BuildBot Reviewed-by: Cheyenne Wills Reviewed-by: Benjamin Kaduk (cherry picked from commit 858ee34545e57acab1e4e5813cd1b9a011538b9e) Change-Id: If89c6f401db04826ef45de83b91240f106cca616 Reviewed-on: https://gerrit.openafs.org/15389 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Mark Vitale Reviewed-by: Michael Meffie Reviewed-by: Kailas Zadbuke Reviewed-by: Stephan Wiesand (cherry picked from commit f6fbb85c00411bf97e9855be73baf49bd6b061d7) --- src/afs/LINUX/osi_compat.h | 8 ++++-- src/afs/LINUX/osi_machdep.h | 4 +++ src/afs/LINUX/osi_module.c | 22 ++++++++++++++++ src/afs/LINUX/osi_vnodeops.c | 51 ++++++++++++++++++++++++++++++------ src/cf/linux-kernel-sig.m4 | 13 +++++++++ 5 files changed, 88 insertions(+), 10 deletions(-) diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h index 808c608ad..bb4969ce8 100644 --- a/src/afs/LINUX/osi_compat.h +++ b/src/afs/LINUX/osi_compat.h @@ -534,7 +534,9 @@ afs_inode_setattr(struct osi_file *afile, struct iattr *newattrs) { int code = 0; struct inode *inode = OSIFILE_INODE(afile); -#if defined(IOP_TAKES_USER_NAMESPACE) +#if defined(IOP_TAKES_MNT_IDMAP) + code = inode->i_op->setattr(afs_mnt_idmap, afile->filp->f_dentry, newattrs); +#elif defined(IOP_TAKES_USER_NAMESPACE) code = inode->i_op->setattr(afs_ns, afile->filp->f_dentry, newattrs); #elif !defined(HAVE_LINUX_INODE_SETATTR) code = inode->i_op->setattr(afile->filp->f_dentry, newattrs); @@ -763,7 +765,9 @@ afs_d_path(struct dentry *dp, struct vfsmount *mnt, char *buf, int buflen) static inline int afs_setattr_prepare(struct dentry *dp, struct iattr *newattrs) { -#if defined(IOP_TAKES_USER_NAMESPACE) +#if defined(IOP_TAKES_MNT_IDMAP) + return setattr_prepare(afs_mnt_idmap, dp, newattrs); +#elif defined(IOP_TAKES_USER_NAMESPACE) return setattr_prepare(afs_ns, dp, newattrs); #elif defined(HAVE_LINUX_SETATTR_PREPARE) return setattr_prepare(dp, newattrs); diff --git a/src/afs/LINUX/osi_machdep.h b/src/afs/LINUX/osi_machdep.h index 34940c60d..2220e0530 100644 --- a/src/afs/LINUX/osi_machdep.h +++ b/src/afs/LINUX/osi_machdep.h @@ -217,6 +217,10 @@ extern struct user_namespace *afs_ns; # define afs_current_user_ns() ((struct user_namespace *)NULL) # endif +#if defined(IOP_TAKES_MNT_IDMAP) +extern struct mnt_idmap *afs_mnt_idmap; +#endif + static inline kuid_t afs_make_kuid(uid_t uid) { return make_kuid(afs_ns, uid); } diff --git a/src/afs/LINUX/osi_module.c b/src/afs/LINUX/osi_module.c index 79ba57c4d..fdc347d2c 100644 --- a/src/afs/LINUX/osi_module.c +++ b/src/afs/LINUX/osi_module.c @@ -31,6 +31,10 @@ #include #include +#if defined(IOP_TAKES_MNT_IDMAP) +# include +#endif + #include "osi_pagecopy.h" extern struct file_system_type afs_fs_type; @@ -46,6 +50,20 @@ int afs_global_owner = 0; struct user_namespace *afs_ns; #endif +#if defined(IOP_TAKES_MNT_IDMAP) +struct mnt_idmap *afs_mnt_idmap; + +static void +afs_init_idmap(void) +{ + struct path fs_root; + + get_fs_root(current->fs, &fs_root); + afs_mnt_idmap = mnt_idmap(fs_root.mnt); + path_put(&fs_root); +} +#endif + int __init afs_init(void) { @@ -55,6 +73,10 @@ afs_init(void) afs_ns = afs_current_user_ns(); #endif +#if defined(IOP_TAKES_MNT_IDMAP) + afs_init_idmap(); +#endif + osi_Init(); /* Initialize CellLRU since it is used while traversing CellServDB proc diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 06c00ac5b..fd54821bd 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1146,7 +1146,10 @@ vattr2inode(struct inode *ip, struct vattr *vp) * Linux version of setattr call. What to change is in the iattr struct. * We need to set bits in both the Linux inode as well as the vcache. */ -#if defined(IOP_TAKES_USER_NAMESPACE) +#if defined(IOP_TAKES_MNT_IDMAP) +static int +afs_notify_change(struct mnt_idmap *idmap, struct dentry *dp, struct iattr *iattrp) +#elif defined(IOP_TAKES_USER_NAMESPACE) static int afs_notify_change(struct user_namespace *mnt_userns, struct dentry *dp, struct iattr *iattrp) #else @@ -1180,7 +1183,18 @@ out: return afs_convert_code(code); } -#if defined(IOP_TAKES_USER_NAMESPACE) +#if defined(IOP_TAKES_MNT_IDMAP) +static int +afs_linux_getattr(struct mnt_idmap *idmap, const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int sync_mode) +{ + int err = afs_linux_revalidate(path->dentry); + if (!err) { + generic_fillattr(afs_mnt_idmap, path->dentry->d_inode, stat); + } + return err; +} +#elif defined(IOP_TAKES_USER_NAMESPACE) static int afs_linux_getattr(struct user_namespace *mnt_userns, const struct path *path, struct kstat *stat, u32 request_mask, unsigned int sync_mode) @@ -1661,7 +1675,11 @@ struct dentry_operations afs_dentry_operations = { * name is in kernel space at this point. */ -#if defined(IOP_TAKES_USER_NAMESPACE) +#if defined(IOP_TAKES_MNT_IDMAP) +static int +afs_linux_create(struct mnt_idmap *idmap, struct inode *dip, + struct dentry *dp, umode_t mode, bool excl) +#elif defined(IOP_TAKES_USER_NAMESPACE) static int afs_linux_create(struct user_namespace *mnt_userns, struct inode *dip, struct dentry *dp, umode_t mode, bool excl) @@ -1953,7 +1971,11 @@ afs_linux_unlink(struct inode *dip, struct dentry *dp) } -#if defined(IOP_TAKES_USER_NAMESPACE) +#if defined(IOP_TAKES_MNT_IDMAP) +static int +afs_linux_symlink(struct mnt_idmap *idmap, struct inode *dip, + struct dentry *dp, const char *target) +#elif defined(IOP_TAKES_USER_NAMESPACE) static int afs_linux_symlink(struct user_namespace *mnt_userns, struct inode *dip, struct dentry *dp, const char *target) @@ -1988,7 +2010,11 @@ out: return afs_convert_code(code); } -#if defined(IOP_TAKES_USER_NAMESPACE) +#if defined(IOP_TAKES_MNT_IDMAP) +static int +afs_linux_mkdir(struct mnt_idmap *idmap, struct inode *dip, + struct dentry *dp, umode_t mode) +#elif defined(IOP_TAKES_USER_NAMESPACE) static int afs_linux_mkdir(struct user_namespace *mnt_userns, struct inode *dip, struct dentry *dp, umode_t mode) @@ -2068,7 +2094,13 @@ afs_linux_rmdir(struct inode *dip, struct dentry *dp) } -#if defined(IOP_TAKES_USER_NAMESPACE) +#if defined(IOP_TAKES_MNT_IDMAP) +static int +afs_linux_rename(struct mnt_idmap *idmap, + struct inode *oldip, struct dentry *olddp, + struct inode *newip, struct dentry *newdp, + unsigned int flags) +#elif defined(IOP_TAKES_USER_NAMESPACE) static int afs_linux_rename(struct user_namespace *mnt_userns, struct inode *oldip, struct dentry *olddp, @@ -2092,7 +2124,7 @@ afs_linux_rename(struct inode *oldip, struct dentry *olddp, struct dentry *rehash = NULL; #if defined(HAVE_LINUX_INODE_OPERATIONS_RENAME_TAKES_FLAGS) || \ - defined(IOP_TAKES_USER_NAMESPACE) + defined(IOP_TAKES_MNT_IDMAP) || defined(IOP_TAKES_USER_NAMESPACE) if (flags) return -EINVAL; /* no support for new flags yet */ #endif @@ -3388,7 +3420,10 @@ done: * Check access rights - returns error if can't check or permission denied. */ -#if defined(IOP_TAKES_USER_NAMESPACE) +#if defined(IOP_TAKES_MNT_IDMAP) +static int +afs_linux_permission(struct mnt_idmap *idmap, struct inode *ip, int mode) +#elif defined(IOP_TAKES_USER_NAMESPACE) static int afs_linux_permission(struct user_namespace *mnt_userns, struct inode *ip, int mode) #elif defined(IOP_PERMISSION_TAKES_FLAGS) diff --git a/src/cf/linux-kernel-sig.m4 b/src/cf/linux-kernel-sig.m4 index e0cc9a2f3..5301f3503 100644 --- a/src/cf/linux-kernel-sig.m4 +++ b/src/cf/linux-kernel-sig.m4 @@ -28,4 +28,17 @@ dnl define. AS_IF([test AS_VAR_GET([ac_cv_linux_operation_inode_operations_create_user_namespace]) = yes], [AC_DEFINE([IOP_TAKES_USER_NAMESPACE], 1, [define if inodeops require struct user_namespace])]) +dnl Linux 6.3 replaced the user_namespace parameter with mnt_idmap for +dnl the inode operations functions. +AC_CHECK_LINUX_OPERATION([inode_operations], [create], [mnt_idmap], + [#include ], + [int], + [struct mnt_idmap *idmap, + struct inode *inode, struct dentry *dentry, + umode_t umode, bool flag]) +dnl if HAVE_LINUX_INODE_OPERATIONS_CREATE_MNT_IDMAP, create a more generic +dnl define. +AS_IF([test AS_VAR_GET([ac_cv_linux_operation_inode_operations_create_mnt_idmap]) = yes], + [AC_DEFINE([IOP_TAKES_MNT_IDMAP], 1, + [define if inodeops require struct mnt_idmap])]) ]) \ No newline at end of file -- 2.40.1