diff options
author | Pavel Snajdr <[email protected]> | 2019-11-11 18:34:21 +0100 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-11-11 09:34:21 -0800 |
commit | 5a6ac4cffcd0255ca6f730bcf356e12891fd18af (patch) | |
tree | 7498ba3b34fdca3c211b4b8bb79557eaaf413a40 /module/os/linux | |
parent | f15d6a54575567c6d69b6f1ffc000d2df5a8f206 (diff) |
Remove zpl_revalidate
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 <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Pavel Snajdr <[email protected]>
Closes #8774
Closes #9549
Diffstat (limited to 'module/os/linux')
-rw-r--r-- | module/os/linux/zfs/zfs_vfsops.c | 33 | ||||
-rw-r--r-- | module/os/linux/zfs/zpl_inode.c | 60 |
2 files changed, 30 insertions, 63 deletions
diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index d0771fa6f..75840dfe7 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -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) { diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c index 3f3b2e2dc..4c628f608 100644 --- a/module/os/linux/zfs/zpl_inode.c +++ b/module/os/linux/zfs/zpl_inode.c @@ -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, -}; |