Skip to content

Commit

Permalink
renameat2: add EL7 compatibility handling
Browse files Browse the repository at this point in the history
EL7 has backported renameat2(2) support, but this was done by creating a
wrapper struct around the inode_operations struct and adding the rename2
callback to the wrapping struct. The semantics are the same as the
upstream callback, so just detect and use the wrapper.

Since we only need this wrapper for rename2 (and renaming is a directory
operation) we only use the wrapper for the directory iops struct.

Signed-off-by: Pavel Snajdr <snajpa@snajpa.net>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
  • Loading branch information
snajpa authored and cyphar committed Jun 17, 2021
1 parent 1d07c28 commit 841cee9
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 0 deletions.
27 changes: 27 additions & 0 deletions config/kernel-rename.m4
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,24 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [
};
],[])
dnl #
dnl # EL7 compatibility
dnl #
dnl # EL7 has backported renameat2 support, but it's done by defining a
dnl # separate iops wrapper structure that takes the .renameat2 function.
dnl #
ZFS_LINUX_TEST_SRC([dir_inode_operations_wrapper_rename2], [
#include <linux/fs.h>
int rename2_fn(struct inode *sip, struct dentry *sdp,
struct inode *tip, struct dentry *tdp,
unsigned int flags) { return 0; }
static const struct inode_operations_wrapper
iops __attribute__ ((unused)) = {
.rename2 = rename2_fn,
};
],[])
dnl #
dnl # 5.12 API change,
dnl #
Expand Down Expand Up @@ -78,6 +96,15 @@ AC_DEFUN([ZFS_AC_KERNEL_RENAME], [
[iops->rename() wants flags])
],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING([whether struct inode_operations_wrapper takes .rename2()])
ZFS_LINUX_TEST_RESULT([dir_inode_operations_wrapper_rename2], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_RENAME2_OPERATIONS_WRAPPER, 1,
[struct inode_operations_wrapper takes .rename2()])
],[
AC_MSG_RESULT(no)
])
])
])
])
Expand Down
4 changes: 4 additions & 0 deletions include/os/linux/zfs/sys/zpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ extern void zpl_vap_init(vattr_t *vap, struct inode *dir,
umode_t mode, cred_t *cr);

extern const struct inode_operations zpl_inode_operations;
#ifdef HAVE_RENAME2_OPERATIONS_WRAPPER
extern const struct inode_operations_wrapper zpl_dir_inode_operations;
#else
extern const struct inode_operations zpl_dir_inode_operations;
#endif
extern const struct inode_operations zpl_symlink_inode_operations;
extern const struct inode_operations zpl_special_inode_operations;
extern dentry_operations_t zpl_dentry_operations;
Expand Down
5 changes: 5 additions & 0 deletions module/os/linux/zfs/zfs_znode.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,12 @@ zfs_inode_set_ops(zfsvfs_t *zfsvfs, struct inode *ip)
break;

case S_IFDIR:
#ifdef HAVE_RENAME2_OPERATIONS_WRAPPER
ip->i_flags |= S_IOPS_WRAPPER;
ip->i_op = &zpl_dir_inode_operations.ops;
#else
ip->i_op = &zpl_dir_inode_operations;
#endif
ip->i_fop = &zpl_dir_file_operations;
ITOZ(ip)->z_zn_prefetch = B_TRUE;
break;
Expand Down
9 changes: 9 additions & 0 deletions module/os/linux/zfs/zpl_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,12 @@ const struct inode_operations zpl_inode_operations = {
#endif /* CONFIG_FS_POSIX_ACL */
};

#ifdef HAVE_RENAME2_OPERATIONS_WRAPPER
const struct inode_operations_wrapper zpl_dir_inode_operations = {
.ops = {
#else
const struct inode_operations zpl_dir_inode_operations = {
#endif
.create = zpl_create,
.lookup = zpl_lookup,
.link = zpl_link,
Expand Down Expand Up @@ -761,6 +766,10 @@ const struct inode_operations zpl_dir_inode_operations = {
#endif /* HAVE_SET_ACL */
.get_acl = zpl_get_acl,
#endif /* CONFIG_FS_POSIX_ACL */
#ifdef HAVE_RENAME2_OPERATIONS_WRAPPER
},
.rename2 = zpl_rename2,
#endif
};

const struct inode_operations zpl_symlink_inode_operations = {
Expand Down

0 comments on commit 841cee9

Please sign in to comment.