From 82a1b2d6289f9ceae0bee6f1e71d3bc29a8c5d16 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Mon, 30 May 2016 20:37:36 +0300 Subject: [PATCH] Check whether the kernel supports i_uid/gid_read/write helpers Since the concept of a kuid and the need to translate from it to ordinary integer type was added in kernel version 3.5 implement necessary plumbing to be able to detect this condition during compile time. If the kernel doesn't support the kuid then just fall back to directly accessing the respective struct inode's members Signed-off-by: Nikolay Borisov Signed-off-by: Brian Behlendorf Issue #4685 Issue #227 --- config/kernel-kuid-helpers.m4 | 22 +++++++++++++++ config/kernel.m4 | 1 + include/linux/vfs_compat.h | 53 +++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 config/kernel-kuid-helpers.m4 diff --git a/config/kernel-kuid-helpers.m4 b/config/kernel-kuid-helpers.m4 new file mode 100644 index 000000000000..60713b9d3132 --- /dev/null +++ b/config/kernel-kuid-helpers.m4 @@ -0,0 +1,22 @@ +dnl # +dnl # 3.5 API change, +dnl # Since usernamespaces were introduced in kernel version 3.5, it +dnl # became necessary to go through one more level of indirection +dnl # when dealing with uid/gid - namely the kuid type. +dnl # +dnl # +AC_DEFUN([ZFS_AC_KERNEL_KUID_HELPERS], [ + AC_MSG_CHECKING([whether i_(uid|gid)_(read|write) exist]) + ZFS_LINUX_TRY_COMPILE([ + #include + ],[ + struct inode *ip = NULL; + (void) i_uid_read(ip); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_KUID_HELPERS, 1, + [i_(uid|gid)_(read|write) exist]) + ],[ + AC_MSG_RESULT(no) + ]) +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index 086cd0b05b37..c9b24cbe8b64 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -92,6 +92,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ ZFS_AC_KERNEL_MAKE_REQUEST_FN ZFS_AC_KERNEL_GENERIC_IO_ACCT ZFS_AC_KERNEL_FPU + ZFS_AC_KERNEL_KUID_HELPERS AS_IF([test "$LINUX_OBJ" != "$LINUX"], [ KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ" diff --git a/include/linux/vfs_compat.h b/include/linux/vfs_compat.h index bcec1146a0c4..97220c2fe6b7 100644 --- a/include/linux/vfs_compat.h +++ b/include/linux/vfs_compat.h @@ -28,6 +28,7 @@ #define _ZFS_VFS_H #include +#include #include /* @@ -352,6 +353,58 @@ static inline struct inode *file_inode(const struct file *f) } #endif /* HAVE_FILE_INODE */ +#ifdef HAVE_KUID_HELPERS +static inline uid_t zfs_uid_read_impl(struct inode *ip) +{ + return (from_kuid(kcred->user_ns, ip->i_uid)); +} + +static inline uid_t zfs_uid_read(struct inode *ip) +{ + return (zfs_uid_read_impl(ip)); +} + +static inline gid_t zfs_gid_read_impl(struct inode *ip) +{ + return (from_kgid(kcred->user_ns, ip->i_gid)); +} + +static inline gid_t zfs_gid_read(struct inode *ip) +{ + return (zfs_gid_read_impl(ip)); +} + +static inline void zfs_uid_write(struct inode *ip, uid_t uid) +{ + ip->i_uid = make_kuid(kcred->user_ns, uid); +} + +static inline void zfs_gid_write(struct inode *ip, gid_t gid) +{ + ip->i_gid = make_kgid(kcred->user_ns, gid); +} +#else +static inline uid_t zfs_uid_read(struct inode *ip) +{ + return (ip->i_uid); +} + +static inline gid_t zfs_gid_read(struct inode *ip) +{ + return (ip->i_gid); +} + +static inline void zfs_uid_write(struct inode *ip, uid_t uid) +{ + ip->i_uid = uid; +} + +static inline void zfs_gid_write(struct inode *ip, gid_t gid) +{ + ip->i_gid = gid; +} +#endif + /* * 2.6.38 API change */