Skip to content

Commit

Permalink
Remove zpl_revalidate
Browse files Browse the repository at this point in the history
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

The way I dealt with this is simply to defer the umount on each ZFS_EXIT on
the mount's zfsvfs.

2. negative dentries created before snapshot rollback
3. stale inodes referenced by dentry cache after snapshot rollback

was solved by flushing dcache for the given mount.

Fixes openzfs#8774

Signed-off-by: Pavel Snajdr <snajpa@snajpa.net>
  • Loading branch information
snajpa committed Oct 4, 2019
1 parent 2cc479d commit b322f0a
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 65 deletions.
1 change: 1 addition & 0 deletions include/os/linux/zfs/sys/zfs_vfsops.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ extern int zfsvfs_create(const char *name, boolean_t readony, zfsvfs_t **zfvp);
extern int zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os);
extern void zfsvfs_free(zfsvfs_t *zfsvfs);
extern int zfs_check_global_label(const char *dsname, const char *hexsl);
extern void zfs_defer_snap_umount(zfsvfs_t *zfsvfs);

extern boolean_t zfs_is_readonly(zfsvfs_t *zfsvfs);
extern int zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent);
Expand Down
1 change: 0 additions & 1 deletion include/os/linux/zfs/sys/zpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 17 additions & 1 deletion include/sys/zfs_znode.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,11 +280,27 @@ do { \
#define ZFS_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, EIO)
#define ZPL_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, -EIO)

/* Must be called before exiting the operation. */
/*
* Must be called before exiting the vop
*
*/
#ifdef __linux_
/*
* Automounted snapshots rely on periodic revalidation
* to defer snapshots from being automatically unmounted.
*/
#define ZFS_EXIT(zfsvfs) \
do { \
if (unlikely(zfsvfs->z_issnap)) \
zfs_defer_snap_umount(zfsvfs); \
rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG); \
} while (0)
#else
#define ZFS_EXIT(zfsvfs) \
do { \
rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG); \
} while (0)
#endif
#define ZPL_EXIT(zfsvfs) ZFS_EXIT(zfsvfs)

/* Verifies the znode is valid. */
Expand Down
16 changes: 13 additions & 3 deletions module/os/linux/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1807,6 +1807,18 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
atomic_long_t zfs_bdi_seq = ATOMIC_LONG_INIT(0);
#endif

void
zfs_defer_snap_umount(zfsvfs_t *zfsvfs)
{
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_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
{
Expand Down Expand Up @@ -1856,9 +1868,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);
Expand Down Expand Up @@ -2228,6 +2237,7 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
zfs_unlinked_drain(zfsvfs);
}

shrink_dcache_sb(zfsvfs->z_parent->z_sb);
bail:
if (err != 0)
zfsvfs->z_unmounted = B_TRUE;
Expand Down
60 changes: 0 additions & 60 deletions module/os/linux/zfs/zpl_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};

0 comments on commit b322f0a

Please sign in to comment.