From d1e3c2235141e704cf62d8059c50ef5510e2eaea Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Wed, 19 Oct 2016 11:12:20 -0700 Subject: [PATCH 1/4] Remove dir inode operations from zpl_inode_operations These operations are dir specific, there's no point putting them in zpl_inode_operations which is for regular files. Signed-off-by: Chunwei Chen --- module/zfs/zpl_inode.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c index b7ac4649c1a1..d26193ffa5b3 100644 --- a/module/zfs/zpl_inode.c +++ b/module/zfs/zpl_inode.c @@ -649,14 +649,6 @@ zpl_revalidate(struct dentry *dentry, unsigned int flags) } const struct inode_operations zpl_inode_operations = { - .create = zpl_create, - .link = zpl_link, - .unlink = zpl_unlink, - .symlink = zpl_symlink, - .mkdir = zpl_mkdir, - .rmdir = zpl_rmdir, - .mknod = zpl_mknod, - .rename = zpl_rename, .setattr = zpl_setattr, .getattr = zpl_getattr, .setxattr = generic_setxattr, From dff075c09f144e35d19594c53d732317fe94b4f6 Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Wed, 19 Oct 2016 11:19:01 -0700 Subject: [PATCH 2/4] Linux 4.9 compat: iops->rename() wants flags In Linux 4.9, torvalds/linux@2773bf0, iops->rename() and iops->rename2() are merged together into iops->rename(), it now wants flags. Signed-off-by: Chunwei Chen --- config/kernel-rename.m4 | 25 +++++++++++++++++++++++++ config/kernel.m4 | 1 + module/zfs/zpl_ctldir.c | 23 ++++++++++++++++++++--- module/zfs/zpl_inode.c | 21 +++++++++++++++++++-- 4 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 config/kernel-rename.m4 diff --git a/config/kernel-rename.m4 b/config/kernel-rename.m4 new file mode 100644 index 000000000000..9f894fb4db1a --- /dev/null +++ b/config/kernel-rename.m4 @@ -0,0 +1,25 @@ +dnl # +dnl # 4.9 API change, +dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants +dnl # flags. +dnl # +AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [ + AC_MSG_CHECKING([whether iops->rename() wants flags]) + ZFS_LINUX_TRY_COMPILE([ + #include + int rename_fn(struct inode *sip, struct dentry *sdp, + struct inode *tip, struct dentry *tdp, + unsigned int flags) { return 0; } + + static const struct inode_operations + iops __attribute__ ((unused)) = { + .rename = rename_fn, + }; + ],[ + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1, [iops->rename() wants flags]) + ],[ + AC_MSG_RESULT(no) + ]) +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index c53e61157841..37635256b322 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -103,6 +103,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ ZFS_AC_KERNEL_FPU ZFS_AC_KERNEL_KUID_HELPERS ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST + ZFS_AC_KERNEL_RENAME_WANTS_FLAGS AS_IF([test "$LINUX_OBJ" != "$LINUX"], [ KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ" diff --git a/module/zfs/zpl_ctldir.c b/module/zfs/zpl_ctldir.c index 7c4fcea3e43c..cdd6668b1dc0 100644 --- a/module/zfs/zpl_ctldir.c +++ b/module/zfs/zpl_ctldir.c @@ -301,13 +301,17 @@ zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir) } #endif /* HAVE_VFS_ITERATE */ -int -zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry, - struct inode *tdip, struct dentry *tdentry) +static int +zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry, + struct inode *tdip, struct dentry *tdentry, unsigned int flags) { cred_t *cr = CRED(); int error; + /* We probably don't want to support renameat2(2) in ctldir */ + if (flags) + return (-EINVAL); + crhold(cr); error = -zfsctl_snapdir_rename(sdip, dname(sdentry), tdip, dname(tdentry), cr, 0); @@ -317,6 +321,15 @@ zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry, return (error); } +#ifndef HAVE_RENAME_WANTS_FLAGS +static int +zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry, + struct inode *tdip, struct dentry *tdentry) +{ + return (zpl_snapdir_rename2(sdip, sdentry, tdip, tdentry, 0)); +} +#endif + static int zpl_snapdir_rmdir(struct inode *dip, struct dentry *dentry) { @@ -405,7 +418,11 @@ const struct file_operations zpl_fops_snapdir = { const struct inode_operations zpl_ops_snapdir = { .lookup = zpl_snapdir_lookup, .getattr = zpl_snapdir_getattr, +#ifdef HAVE_RENAME_WANTS_FLAGS + .rename = zpl_snapdir_rename2, +#else .rename = zpl_snapdir_rename, +#endif .rmdir = zpl_snapdir_rmdir, .mkdir = zpl_snapdir_mkdir, }; diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c index d26193ffa5b3..113885ead7eb 100644 --- a/module/zfs/zpl_inode.c +++ b/module/zfs/zpl_inode.c @@ -356,13 +356,17 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) } static int -zpl_rename(struct inode *sdip, struct dentry *sdentry, - struct inode *tdip, struct dentry *tdentry) +zpl_rename2(struct inode *sdip, struct dentry *sdentry, + struct inode *tdip, struct dentry *tdentry, unsigned int flags) { cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; + /* We don't have renameat2(2) support */ + if (flags) + return (-EINVAL); + crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_rename(sdip, dname(sdentry), tdip, dname(tdentry), cr, 0); @@ -373,6 +377,15 @@ zpl_rename(struct inode *sdip, struct dentry *sdentry, return (error); } +#ifndef HAVE_RENAME_WANTS_FLAGS +static int +zpl_rename(struct inode *sdip, struct dentry *sdentry, + struct inode *tdip, struct dentry *tdentry) +{ + return (zpl_rename2(sdip, sdentry, tdip, tdentry, 0)); +} +#endif + static int zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) { @@ -681,7 +694,11 @@ const struct inode_operations zpl_dir_inode_operations = { .mkdir = zpl_mkdir, .rmdir = zpl_rmdir, .mknod = zpl_mknod, +#ifdef HAVE_RENAME_WANTS_FLAGS + .rename = zpl_rename2, +#else .rename = zpl_rename, +#endif .setattr = zpl_setattr, .getattr = zpl_getattr, .setxattr = generic_setxattr, From dc1bb656ccc3a0de0f8cafecd10afcee715c7a84 Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Wed, 19 Oct 2016 11:19:17 -0700 Subject: [PATCH 3/4] Linux 4.9 compat: remove iops->{set,get,remove}xattr In Linux 4.9, torvalds/linux@fd50eca, iops->{set,get,remove}xattr and generic_{set,get,remove}xattr are removed. xattr operations will directly go through sb->s_xattr. Signed-off-by: Chunwei Chen --- config/kernel-xattr-handler.m4 | 25 +++++++++++++++++++++++++ config/kernel.m4 | 1 + module/zfs/zpl_inode.c | 8 ++++++++ 3 files changed, 34 insertions(+) diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4 index ce18eaf9caf6..300cb0ba8ea4 100644 --- a/config/kernel-xattr-handler.m4 +++ b/config/kernel-xattr-handler.m4 @@ -57,6 +57,31 @@ AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_NAME], [ ]) ]) +dnl # +dnl # 4.9 API change, +dnl # iops->{set,get,remove}xattr and generic_{set,get,remove}xattr are +dnl # removed. xattr operations will directly go through sb->s_xattr. +dnl # +AC_DEFUN([ZFS_AC_KERNEL_HAVE_GENERIC_SETXATTR], [ + AC_MSG_CHECKING([whether generic_setxattr() exists]) + ZFS_LINUX_TRY_COMPILE([ + #include + #include + + static const struct inode_operations + iops __attribute__ ((unused)) = { + .setxattr = generic_setxattr + }; + ],[ + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_GENERIC_SETXATTR, 1, + [generic_setxattr() exists]) + ],[ + AC_MSG_RESULT(no) + ]) +]) + dnl # dnl # Supported xattr handler get() interfaces checked newest to oldest. dnl # diff --git a/config/kernel.m4 b/config/kernel.m4 index 37635256b322..66e97c250bcc 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -104,6 +104,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ ZFS_AC_KERNEL_KUID_HELPERS ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST ZFS_AC_KERNEL_RENAME_WANTS_FLAGS + ZFS_AC_KERNEL_HAVE_GENERIC_SETXATTR AS_IF([test "$LINUX_OBJ" != "$LINUX"], [ KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ" diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c index 113885ead7eb..f59f2df97b42 100644 --- a/module/zfs/zpl_inode.c +++ b/module/zfs/zpl_inode.c @@ -664,9 +664,11 @@ zpl_revalidate(struct dentry *dentry, unsigned int flags) const struct inode_operations zpl_inode_operations = { .setattr = zpl_setattr, .getattr = zpl_getattr, +#ifdef HAVE_GENERIC_SETXATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .removexattr = generic_removexattr, +#endif .listxattr = zpl_xattr_list, #ifdef HAVE_INODE_TRUNCATE_RANGE .truncate_range = zpl_truncate_range, @@ -701,9 +703,11 @@ const struct inode_operations zpl_dir_inode_operations = { #endif .setattr = zpl_setattr, .getattr = zpl_getattr, +#ifdef HAVE_GENERIC_SETXATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .removexattr = generic_removexattr, +#endif .listxattr = zpl_xattr_list, #if defined(CONFIG_FS_POSIX_ACL) #if defined(HAVE_GET_ACL) @@ -728,18 +732,22 @@ const struct inode_operations zpl_symlink_inode_operations = { #endif .setattr = zpl_setattr, .getattr = zpl_getattr, +#ifdef HAVE_GENERIC_SETXATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .removexattr = generic_removexattr, +#endif .listxattr = zpl_xattr_list, }; const struct inode_operations zpl_special_inode_operations = { .setattr = zpl_setattr, .getattr = zpl_getattr, +#ifdef HAVE_GENERIC_SETXATTR .setxattr = generic_setxattr, .getxattr = generic_getxattr, .removexattr = generic_removexattr, +#endif .listxattr = zpl_xattr_list, #if defined(CONFIG_FS_POSIX_ACL) #if defined(HAVE_GET_ACL) From d2632d302507b069dfc202d9464eaa32df621b19 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Tue, 18 Oct 2016 23:49:23 +0000 Subject: [PATCH 4/4] Linux 4.9 compat: inode_change_ok() renamed setattr_prepare() In torvalds/linux@31051c8 the inode_change_ok() function was renamed setattr_prepare() and updated to take a dentry ratheri than an inode. Update the code to call the setattr_prepare() and add a wrapper function which call inode_change_ok() for older kernels. Signed-off-by: Brian Behlendorf Signed-off-by: Chunwei Chen Requires-spl: refs/pull/581/head --- config/kernel-setattr-prepare.m4 | 23 +++++++++++++++++++++++ config/kernel.m4 | 1 + include/linux/vfs_compat.h | 11 +++++++++++ module/zfs/zpl_inode.c | 2 +- 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 config/kernel-setattr-prepare.m4 diff --git a/config/kernel-setattr-prepare.m4 b/config/kernel-setattr-prepare.m4 new file mode 100644 index 000000000000..32f7deb77abe --- /dev/null +++ b/config/kernel-setattr-prepare.m4 @@ -0,0 +1,23 @@ +dnl # +dnl # 4.9 API change +dnl # The inode_change_ok() function has been renamed setattr_prepare() +dnl # and updated to take a dentry rather than an inode. +dnl # +AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE], + [AC_MSG_CHECKING([whether setattr_prepare() is available]) + ZFS_LINUX_TRY_COMPILE_SYMBOL([ + #include + ], [ + struct dentry *dentry = NULL; + struct iattr *attr = NULL; + int error; + + error = setattr_prepare(dentry, attr); + ], [setattr_prepare], [fs/attr.c], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SETATTR_PREPARE, 1, + [setattr_prepare() is available]) + ], [ + AC_MSG_RESULT(no) + ]) +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index 66e97c250bcc..44a20f2135c6 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -74,6 +74,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ ZFS_AC_KERNEL_ENCODE_FH_WITH_INODE ZFS_AC_KERNEL_COMMIT_METADATA ZFS_AC_KERNEL_CLEAR_INODE + ZFS_AC_KERNEL_SETATTR_PREPARE ZFS_AC_KERNEL_INSERT_INODE_LOCKED ZFS_AC_KERNEL_D_MAKE_ROOT ZFS_AC_KERNEL_D_OBTAIN_ALIAS diff --git a/include/linux/vfs_compat.h b/include/linux/vfs_compat.h index 8a64cabef1eb..989c237a34e5 100644 --- a/include/linux/vfs_compat.h +++ b/include/linux/vfs_compat.h @@ -444,4 +444,15 @@ static inline void zfs_gid_write(struct inode *ip, gid_t gid) #define zpl_follow_up(path) follow_up(path) #endif +/* + * 4.9 API change + */ +#ifndef HAVE_SETATTR_PREPARE +static inline int +setattr_prepare(struct dentry *dentry, struct iattr *ia) +{ + return (inode_change_ok(dentry->d_inode, ia)); +} +#endif + #endif /* _ZFS_VFS_H */ diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c index f59f2df97b42..b8adda7a1b1b 100644 --- a/module/zfs/zpl_inode.c +++ b/module/zfs/zpl_inode.c @@ -323,7 +323,7 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) int error; fstrans_cookie_t cookie; - error = inode_change_ok(ip, ia); + error = setattr_prepare(dentry, ia); if (error) return (error);