mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-01-13 00:32:47 +03:00
Linux 6.17: d_set_d_op() is no longer available
We only have extremely narrow uses, so move it all into a single function that does only what we need, with and without d_set_d_op(). Sponsored-by: https://despairlabs.com/sponsor/ Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Tony Hutter <hutter2@llnl.gov> Signed-off-by: Rob Norris <robn@despairlabs.com> Closes #17621
This commit is contained in:
parent
f3421697d0
commit
7d7ae8979a
@ -24,6 +24,9 @@ dnl #
|
||||
dnl # 2.6.38 API change
|
||||
dnl # Added d_set_d_op() helper function.
|
||||
dnl #
|
||||
dnl # 6.17 API change
|
||||
dnl # d_set_d_op() removed. No direct replacement.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_D_SET_D_OP], [
|
||||
ZFS_LINUX_TEST_SRC([d_set_d_op], [
|
||||
#include <linux/dcache.h>
|
||||
@ -34,11 +37,12 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_D_SET_D_OP], [
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_D_SET_D_OP], [
|
||||
AC_MSG_CHECKING([whether d_set_d_op() is available])
|
||||
ZFS_LINUX_TEST_RESULT_SYMBOL([d_set_d_op],
|
||||
[d_set_d_op], [fs/dcache.c], [
|
||||
ZFS_LINUX_TEST_RESULT([d_set_d_op], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_D_SET_D_OP, 1,
|
||||
[Define if d_set_d_op() is available])
|
||||
], [
|
||||
ZFS_LINUX_TEST_ERROR([d_set_d_op])
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
@ -59,32 +59,6 @@
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 2.6.30 API change,
|
||||
* The const keyword was added to the 'struct dentry_operations' in
|
||||
* the dentry structure. To handle this we define an appropriate
|
||||
* dentry_operations_t typedef which can be used.
|
||||
*/
|
||||
typedef const struct dentry_operations dentry_operations_t;
|
||||
|
||||
/*
|
||||
* 2.6.38 API addition,
|
||||
* Added d_clear_d_op() helper function which clears some flags and the
|
||||
* registered dentry->d_op table. This is required because d_set_d_op()
|
||||
* issues a warning when the dentry operations table is already set.
|
||||
* For the .zfs control directory to work properly we must be able to
|
||||
* override the default operations table and register custom .d_automount
|
||||
* and .d_revalidate callbacks.
|
||||
*/
|
||||
static inline void
|
||||
d_clear_d_op(struct dentry *dentry)
|
||||
{
|
||||
dentry->d_op = NULL;
|
||||
dentry->d_flags &= ~(
|
||||
DCACHE_OP_HASH | DCACHE_OP_COMPARE |
|
||||
DCACHE_OP_REVALIDATE | DCACHE_OP_DELETE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk and invalidate all dentry aliases of an inode
|
||||
* unless it's a mountpoint
|
||||
|
||||
@ -197,7 +197,7 @@ zpl_snapdir_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
return (!!dentry->d_inode);
|
||||
}
|
||||
|
||||
static dentry_operations_t zpl_dops_snapdirs = {
|
||||
static const struct dentry_operations zpl_dops_snapdirs = {
|
||||
/*
|
||||
* Auto mounting of snapshots is only supported for 2.6.37 and
|
||||
* newer kernels. Prior to this kernel the ops->follow_link()
|
||||
@ -210,6 +210,51 @@ static dentry_operations_t zpl_dops_snapdirs = {
|
||||
.d_revalidate = zpl_snapdir_revalidate,
|
||||
};
|
||||
|
||||
/*
|
||||
* For the .zfs control directory to work properly we must be able to override
|
||||
* the default operations table and register custom .d_automount and
|
||||
* .d_revalidate callbacks.
|
||||
*/
|
||||
static void
|
||||
set_snapdir_dentry_ops(struct dentry *dentry, unsigned int extraflags) {
|
||||
static const unsigned int op_flags =
|
||||
DCACHE_OP_HASH | DCACHE_OP_COMPARE |
|
||||
DCACHE_OP_REVALIDATE | DCACHE_OP_DELETE |
|
||||
DCACHE_OP_PRUNE | DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_REAL;
|
||||
|
||||
#ifdef HAVE_D_SET_D_OP
|
||||
/*
|
||||
* d_set_d_op() will set the DCACHE_OP_ flags according to what it
|
||||
* finds in the passed dentry_operations, so we don't have to.
|
||||
*
|
||||
* We clear the flags and the old op table before calling d_set_d_op()
|
||||
* because issues a warning when the dentry operations table is already
|
||||
* set.
|
||||
*/
|
||||
dentry->d_op = NULL;
|
||||
dentry->d_flags &= ~op_flags;
|
||||
d_set_d_op(dentry, &zpl_dops_snapdirs);
|
||||
dentry->d_flags |= extraflags;
|
||||
#else
|
||||
/*
|
||||
* Since 6.17 there's no exported way to modify dentry ops, so we have
|
||||
* to reach in and do it ourselves. This should be safe for our very
|
||||
* narrow use case, which is to create or splice in an entry to give
|
||||
* access to a snapshot.
|
||||
*
|
||||
* We need to set the op flags directly. We hardcode
|
||||
* DCACHE_OP_REVALIDATE because that's the only operation we have; if
|
||||
* we ever extend zpl_dops_snapdirs we will need to update the op flags
|
||||
* to match.
|
||||
*/
|
||||
spin_lock(&dentry->d_lock);
|
||||
dentry->d_op = &zpl_dops_snapdirs;
|
||||
dentry->d_flags &= ~op_flags;
|
||||
dentry->d_flags |= DCACHE_OP_REVALIDATE | extraflags;
|
||||
spin_unlock(&dentry->d_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct dentry *
|
||||
zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
|
||||
unsigned int flags)
|
||||
@ -231,10 +276,7 @@ zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
|
||||
return (ERR_PTR(error));
|
||||
|
||||
ASSERT(error == 0 || ip == NULL);
|
||||
d_clear_d_op(dentry);
|
||||
d_set_d_op(dentry, &zpl_dops_snapdirs);
|
||||
dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
|
||||
|
||||
set_snapdir_dentry_ops(dentry, DCACHE_NEED_AUTOMOUNT);
|
||||
return (d_splice_alias(ip, dentry));
|
||||
}
|
||||
|
||||
@ -368,8 +410,7 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
|
||||
|
||||
error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0);
|
||||
if (error == 0) {
|
||||
d_clear_d_op(dentry);
|
||||
d_set_d_op(dentry, &zpl_dops_snapdirs);
|
||||
set_snapdir_dentry_ops(dentry, 0);
|
||||
d_instantiate(dentry, ip);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user