]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Remove zpl_revalidate
authorPavel Snajdr <snajpa@snajpa.net>
Mon, 11 Nov 2019 17:34:21 +0000 (18:34 +0100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 11 Nov 2019 17:34:21 +0000 (09:34 -0800)
This patch removes the need for zpl_revalidate altogether.

There were 3 main reasons why we used d_revalidate:

1. periodic automounted snapshots umount deferral
2. negative dentries created before snapshot rollback
3. stale inodes referenced by dentry cache after snapshot rollback

Periodic snapshots deferral solution introduces zfs_exit_fs function,
which is called as a part of ZFS_EXIT(zfsvfs_t) macro.

Negative dentries and stale inodes are solved by flushing the dcache
for the particular dataset on zfs_resume_fs call.

This patch also removes now unused HAVE_S_D_OP configure test.

Reviewed-by: Aleksa Sarai <cyphar@cyphar.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Pavel Snajdr <snajpa@snajpa.net>
Closes #8774
Closes #9549

config/kernel-dentry-operations.m4
include/os/linux/zfs/sys/zfs_vfsops.h
include/os/linux/zfs/sys/zfs_znode_impl.h
include/os/linux/zfs/sys/zpl.h
module/os/linux/zfs/zfs_vfsops.c
module/os/linux/zfs/zpl_inode.c

index 2dfd2ac554cff668bae92b4098ec48d9846e59ca..de7482801b7bb38a8a5a6c1f28ef2ce46c2e4b8f 100644 (file)
@@ -150,29 +150,6 @@ AC_DEFUN([ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS], [
        ])
 ])
 
-dnl #
-dnl # 2.6.38 API change
-dnl # Added sb->s_d_op default dentry_operations member
-dnl #
-AC_DEFUN([ZFS_AC_KERNEL_SRC_S_D_OP], [
-       ZFS_LINUX_TEST_SRC([super_block_s_d_op], [
-               #include <linux/fs.h>
-       ],[
-               struct super_block sb __attribute__ ((unused));
-               sb.s_d_op = NULL;
-       ])
-])
-
-AC_DEFUN([ZFS_AC_KERNEL_S_D_OP], [
-       AC_MSG_CHECKING([whether super_block has s_d_op])
-       ZFS_LINUX_TEST_RESULT([super_block_s_d_op], [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_S_D_OP, 1, [struct super_block has s_d_op])
-       ], [
-               AC_MSG_RESULT(no)
-       ])
-])
-
 AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY], [
         ZFS_AC_KERNEL_SRC_D_MAKE_ROOT
         ZFS_AC_KERNEL_SRC_D_OBTAIN_ALIAS
@@ -180,7 +157,6 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY], [
         ZFS_AC_KERNEL_SRC_D_SET_D_OP
         ZFS_AC_KERNEL_SRC_D_REVALIDATE_NAMEIDATA
         ZFS_AC_KERNEL_SRC_CONST_DENTRY_OPERATIONS
-        ZFS_AC_KERNEL_SRC_S_D_OP
 ])
 
 AC_DEFUN([ZFS_AC_KERNEL_DENTRY], [
@@ -190,5 +166,4 @@ AC_DEFUN([ZFS_AC_KERNEL_DENTRY], [
         ZFS_AC_KERNEL_D_SET_D_OP
         ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA
         ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS
-        ZFS_AC_KERNEL_S_D_OP
 ])
index 3a959996f3cdc36e61c351c0f081a993af1d3993..26e49d7b497ca4e32b18a0736c4dbae58450fa7b 100644 (file)
@@ -197,6 +197,7 @@ typedef struct zfid_long {
 extern int zfs_suspend_fs(zfsvfs_t *zfsvfs);
 extern int zfs_resume_fs(zfsvfs_t *zfsvfs, struct dsl_dataset *ds);
 extern int zfs_end_fs(zfsvfs_t *zfsvfs, struct dsl_dataset *ds);
+extern void zfs_exit_fs(zfsvfs_t *zfsvfs);
 extern int zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
     const char *domain, uint64_t rid, uint64_t *valuep);
 extern int zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
index 0ecfb0a90a4f8a6e29407451f6f7fc568b4590e5..65abf4ca9d7937b58dfdba03f08b97c919775215 100644 (file)
@@ -84,6 +84,7 @@ do {                                                          \
 /* Must be called before exiting the operation. */
 #define        ZFS_EXIT(zfsvfs)                                        \
 do {                                                           \
+       zfs_exit_fs(zfsvfs);                                    \
        rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG);             \
 } while (0)
 #define        ZPL_EXIT(zfsvfs)        ZFS_EXIT(zfsvfs)
index 2766269f31c8650e20bb0a7032a98e3696b1346a..01f0f6f38c6eb2419dd6270343f1e6f0aebb17b0 100644 (file)
@@ -45,7 +45,6 @@ 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;
-extern dentry_operations_t zpl_dentry_operations;
 
 /* zpl_file.c */
 extern ssize_t zpl_read_common(struct inode *ip, const char *buf,
index d0771fa6fedb45534647f40b12f684fbc950617f..75840dfe71fbc4e5c2e5e4bdaf2a09fe5c1ab6ff 100644 (file)
@@ -1931,9 +1931,6 @@ 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;
-#ifdef HAVE_S_D_OP
-       sb->s_d_op = &zpl_dentry_operations;
-#endif /* HAVE_S_D_OP */
 
        /* Set features for file system. */
        zfs_set_fuid_feature(zfsvfs);
@@ -2303,6 +2300,16 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
                zfs_unlinked_drain(zfsvfs);
        }
 
+       /*
+        * Most of the time zfs_suspend_fs is used for changing the contents
+        * of the underlying dataset. ZFS rollback and receive operations
+        * might create files for which negative dentries are present in
+        * the cache. Since walking the dcache would require a lot of GPL-only
+        * code duplication, it's much easier on these rather rare occasions
+        * just to flush the whole dcache for the given dataset/filesystem.
+        */
+       shrink_dcache_sb(zfsvfs->z_sb);
+
 bail:
        if (err != 0)
                zfsvfs->z_unmounted = B_TRUE;
@@ -2353,6 +2360,26 @@ zfs_end_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
        return (0);
 }
 
+/*
+ * Automounted snapshots rely on periodic revalidation
+ * to defer snapshots from being automatically unmounted.
+ */
+
+inline void
+zfs_exit_fs(zfsvfs_t *zfsvfs)
+{
+       if (!zfsvfs->z_issnap)
+               return;
+
+       if (time_after(jiffies, zfsvfs->z_snap_defer_time +
+           MAX(zfs_expire_snapshot * HZ / 2, HZ))) {
+               zfsvfs->z_snap_defer_time = jiffies;
+               zfsctl_snapshot_unmount_delay(zfsvfs->z_os->os_spa,
+                   dmu_objset_id(zfsvfs->z_os),
+                   zfs_expire_snapshot);
+       }
+}
+
 int
 zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers)
 {
index 3f3b2e2dc53cb2b99072a7ed4848ef8c10fd0a6b..4c628f60898c8e7f130cbf61565e8e27a794a99e 100644 (file)
@@ -70,9 +70,6 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 
        spin_lock(&dentry->d_lock);
        dentry->d_time = jiffies;
-#ifndef HAVE_S_D_OP
-       d_set_d_op(dentry, &zpl_dentry_operations);
-#endif /* HAVE_S_D_OP */
        spin_unlock(&dentry->d_lock);
 
        if (error) {
@@ -655,59 +652,6 @@ zpl_fallocate(struct inode *ip, int mode, loff_t offset, loff_t len)
 }
 #endif /* HAVE_INODE_FALLOCATE */
 
-static int
-#ifdef HAVE_D_REVALIDATE_NAMEIDATA
-zpl_revalidate(struct dentry *dentry, struct nameidata *nd)
-{
-       unsigned int flags = (nd ? nd->flags : 0);
-#else
-zpl_revalidate(struct dentry *dentry, unsigned int flags)
-{
-#endif /* HAVE_D_REVALIDATE_NAMEIDATA */
-       /* CSTYLED */
-       zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info;
-       int error;
-
-       if (flags & LOOKUP_RCU)
-               return (-ECHILD);
-
-       /*
-        * Automounted snapshots rely on periodic dentry revalidation
-        * to defer snapshots from being automatically unmounted.
-        */
-       if (zfsvfs->z_issnap) {
-               if (time_after(jiffies, zfsvfs->z_snap_defer_time +
-                   MAX(zfs_expire_snapshot * HZ / 2, HZ))) {
-                       zfsvfs->z_snap_defer_time = jiffies;
-                       zfsctl_snapshot_unmount_delay(zfsvfs->z_os->os_spa,
-                           dmu_objset_id(zfsvfs->z_os), zfs_expire_snapshot);
-               }
-       }
-
-       /*
-        * After a rollback negative dentries created before the rollback
-        * time must be invalidated.  Otherwise they can obscure files which
-        * are only present in the rolled back dataset.
-        */
-       if (dentry->d_inode == NULL) {
-               spin_lock(&dentry->d_lock);
-               error = time_before(dentry->d_time, zfsvfs->z_rollback_time);
-               spin_unlock(&dentry->d_lock);
-
-               if (error)
-                       return (0);
-       }
-
-       /*
-        * The dentry may reference a stale inode if a mounted file system
-        * was rolled back to a point in time where the object didn't exist.
-        */
-       if (dentry->d_inode && ITOZ(dentry->d_inode)->z_is_stale)
-               return (0);
-
-       return (1);
-}
-
 const struct inode_operations zpl_inode_operations = {
        .setattr        = zpl_setattr,
        .getattr        = zpl_getattr,
@@ -820,7 +764,3 @@ const struct inode_operations zpl_special_inode_operations = {
 #endif /* HAVE_GET_ACL | HAVE_CHECK_ACL | HAVE_PERMISSION */
 #endif /* CONFIG_FS_POSIX_ACL */
 };
-
-dentry_operations_t zpl_dentry_operations = {
-       .d_revalidate   = zpl_revalidate,
-};