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 locklessly walks and
invalidates all aliases of an inode; the lockless approach assumes
the function is only called when z_teardown_lock is active or the
inode in question is locked.

Signed-off-by: Pavel Snajdr <[email protected]>
  • Loading branch information
snajpa committed Nov 20, 2019
1 parent 8221bcf commit 259d2a3
Show file tree
Hide file tree
Showing 9 changed files with 122 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
1 change: 1 addition & 0 deletions include/os/linux/spl/sys/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ KERNEL_H = \
$(top_srcdir)/include/os/linux/spl/sys/console.h \
$(top_srcdir)/include/os/linux/spl/sys/cred.h \
$(top_srcdir)/include/os/linux/spl/sys/ctype.h \
$(top_srcdir)/include/os/linux/spl/sys/dcache.h \
$(top_srcdir)/include/os/linux/spl/sys/debug.h \
$(top_srcdir)/include/os/linux/spl/sys/disp.h \
$(top_srcdir)/include/os/linux/spl/sys/dkio.h \
Expand Down
30 changes: 30 additions & 0 deletions include/os/linux/spl/sys/dcache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2019 OpenZFS Project
* Written by Pavel Snajdr <[email protected]>
*
* This file is part of the SPL, Solaris Porting Layer.
* For details, see <http://zfsonlinux.org/>.
*
* The SPL is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* The SPL is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with the SPL. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _SPL_DCACHE_H
#define _SPL_DCACHE_H

#include <linux/file.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>

extern void spl_d_drop_aliases(struct inode *inode);
#endif /* SPL_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
1 change: 1 addition & 0 deletions module/os/linux/spl/Makefile.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
$(MODULE)-objs += ../os/linux/spl/spl-atomic.o
$(MODULE)-objs += ../os/linux/spl/spl-condvar.o
$(MODULE)-objs += ../os/linux/spl/spl-cred.o
$(MODULE)-objs += ../os/linux/spl/spl-dcache.o
$(MODULE)-objs += ../os/linux/spl/spl-err.o
$(MODULE)-objs += ../os/linux/spl/spl-generic.o
$(MODULE)-objs += ../os/linux/spl/spl-kmem.o
Expand Down
48 changes: 48 additions & 0 deletions module/os/linux/spl/spl-dcache.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2019 OpenZFS Project
* Written by Pavel Snajdr <[email protected]>
*
* This file is part of the SPL, Solaris Porting Layer.
* For details, see <http://zfsonlinux.org/>.
*
* The SPL is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* The SPL is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with the SPL. If not, see <http://www.gnu.org/licenses/>.
*/

#include <sys/debug.h>
#include <sys/dcache.h>
#include <sys/sysmacros.h>
#include <sys/kmem.h>
#include <sys/vmem.h>
#include <linux/mm.h>
#include <linux/dcache.h>
#include <linux/list.h>

/*
* Locklessly walk and invalidate all aliases of an inode; the lockless
* approach assumes the function is only called when z_teardown_lock is
* active or the inode in question is locked.
*/
void
spl_d_drop_aliases(struct inode *inode)
{
struct dentry *dentry;
#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
__d_drop(dentry);
}
}
EXPORT_SYMBOL(spl_d_drop_aliases);
4 changes: 4 additions & 0 deletions module/os/linux/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include <sys/zfs_fuid.h>
#include <sys/sunddi.h>
#include <sys/dmu_objset.h>
#include <sys/dcache.h>
#include <sys/spa_boot.h>
#include <sys/objlist.h>
#include <sys/zpl.h>
Expand Down Expand Up @@ -1926,7 +1927,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 +2278,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 259d2a3

Please sign in to comment.