diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h index 808c608adf..bb4969ce87 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 34940c60df..2220e05307 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 79ba57c4da..fdc347d2c5 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 d875788b62..2c5439dfd0 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 e0cc9a2f38..5301f35036 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