Skip to content

Commit

Permalink
Remove zpl_revalidate: fix snapshot rollback
Browse files Browse the repository at this point in the history
Open files, which aren't present in the snapshot, which is being
roll-backed to, need to disappear from the visible VFS image of
the dataset.

Kernel provides __d_drop function to locklessly drop invalid entry
from the dcache, but inode can be referenced by multiple dentries.

The introduced spl_d_drop_aliases function walks and invalidates
all aliases of an inode.

Signed-off-by: Pavel Snajdr <[email protected]>
  • Loading branch information
snajpa committed Nov 22, 2019
1 parent 0c46813 commit 77da49e
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 0 deletions.
30 changes: 30 additions & 0 deletions config/kernel-dentry-alias.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
dnl #
dnl # 3.18 API change
dnl # Dentry aliases are in d_u struct dentry member
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY_ALIAS_D_U], [
ZFS_LINUX_TEST_SRC([dentry_alias_d_u], [
#include <linux/fs.h>
#include <linux/dcache.h>
#include <linux/list.h>
], [
struct inode *inode __attribute__ ((unused)) = NULL;
struct dentry *dentry __attribute__ ((unused)) = NULL;
hlist_for_each_entry(dentry, &inode->i_dentry,
d_u.d_alias) {
__d_drop(dentry);
}
])
])

AC_DEFUN([ZFS_AC_KERNEL_DENTRY_ALIAS_D_U], [
AC_MSG_CHECKING([whether dentry aliases are in d_u member])
ZFS_LINUX_TEST_RESULT([dentry_alias_d_u], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_DENTRY_D_U_ALIASES, 1,
[dentry aliases are in d_u member])
],[
AC_MSG_RESULT(no)
])
])

2 changes: 2 additions & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_SETATTR_PREPARE
ZFS_AC_KERNEL_SRC_INSERT_INODE_LOCKED
ZFS_AC_KERNEL_SRC_DENTRY
ZFS_AC_KERNEL_SRC_DENTRY_ALIAS_D_U
ZFS_AC_KERNEL_SRC_TRUNCATE_SETSIZE
ZFS_AC_KERNEL_SRC_SECURITY_INODE
ZFS_AC_KERNEL_SRC_FST_MOUNT
Expand Down Expand Up @@ -181,6 +182,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_SETATTR_PREPARE
ZFS_AC_KERNEL_INSERT_INODE_LOCKED
ZFS_AC_KERNEL_DENTRY
ZFS_AC_KERNEL_DENTRY_ALIAS_D_U
ZFS_AC_KERNEL_TRUNCATE_SETSIZE
ZFS_AC_KERNEL_SECURITY_INODE
ZFS_AC_KERNEL_FST_MOUNT
Expand Down
21 changes: 21 additions & 0 deletions include/os/linux/kernel/linux/dcache_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,25 @@ d_clear_d_op(struct dentry *dentry)
DCACHE_OP_REVALIDATE | DCACHE_OP_DELETE);
}

/*
* Walk and invalidate all dentry aliases of an inode
* unless it's a mountpoint
*/
static inline void
spl_d_drop_aliases(struct inode *inode)
{
struct dentry *dentry;
spin_lock(&inode->i_lock);
#ifdef HAVE_DENTRY_D_U_ALIASES
hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
#else
hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
#endif
if (!IS_ROOT(dentry) && !d_mountpoint(dentry) &&
(dentry->d_inode == inode)) {
d_drop(dentry);
}
}
spin_unlock(&inode->i_lock);
}
#endif /* _ZFS_DCACHE_H */
2 changes: 2 additions & 0 deletions include/os/linux/zfs/sys/zpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ extern const struct inode_operations zpl_inode_operations;
extern const struct inode_operations zpl_dir_inode_operations;
extern const struct inode_operations zpl_symlink_inode_operations;
extern const struct inode_operations zpl_special_inode_operations;
#if 0
extern dentry_operations_t zpl_dentry_operations;
#endif

/* zpl_file.c */
extern ssize_t zpl_read_common(struct inode *ip, const char *buf,
Expand Down
3 changes: 3 additions & 0 deletions module/os/linux/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,9 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
sb->s_op = &zpl_super_operations;
sb->s_xattr = zpl_xattr_handlers;
sb->s_export_op = &zpl_export_operations;
#if 0
sb->s_d_op = &zpl_dentry_operations;
#endif

/* Set features for file system. */
zfs_set_fuid_feature(zfsvfs);
Expand Down Expand Up @@ -2275,6 +2277,7 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
zp = list_next(&zfsvfs->z_all_znodes, zp)) {
err2 = zfs_rezget(zp);
if (err2) {
spl_d_drop_aliases(ZTOI(zp));
remove_inode_hash(ZTOI(zp));
zp->z_is_stale = B_TRUE;
}
Expand Down
4 changes: 4 additions & 0 deletions module/os/linux/zfs/zpl_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,7 @@ zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
return (error);
}

#if 0
static int
#ifdef HAVE_D_REVALIDATE_NAMEIDATA
zpl_revalidate(struct dentry *dentry, struct nameidata *nd)
Expand Down Expand Up @@ -641,6 +642,7 @@ zpl_revalidate(struct dentry *dentry, unsigned int flags)

return (1);
}
#endif

const struct inode_operations zpl_inode_operations = {
.setattr = zpl_setattr,
Expand Down Expand Up @@ -731,6 +733,8 @@ const struct inode_operations zpl_special_inode_operations = {
#endif /* CONFIG_FS_POSIX_ACL */
};

#if 0
dentry_operations_t zpl_dentry_operations = {
.d_revalidate = zpl_revalidate,
};
#endif

0 comments on commit 77da49e

Please sign in to comment.