mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Remove zpl_revalidate: fix snapshot rollback
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 drop invalid entry from the dcache, but inode can be referenced by dentry multiple dentries. The introduced zpl_d_drop_aliases function walks and invalidates all aliases of an inode. Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Pavel Snajdr <snajpa@snajpa.net> Closes #9600 Closes #14070
This commit is contained in:
committed by
Brian Behlendorf
parent
e09fdda977
commit
86db35c447
@@ -487,7 +487,6 @@ zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
|
||||
zp->z_is_sa = B_FALSE;
|
||||
zp->z_is_mapped = B_FALSE;
|
||||
zp->z_is_ctldir = B_TRUE;
|
||||
zp->z_is_stale = B_FALSE;
|
||||
zp->z_sa_hdl = NULL;
|
||||
zp->z_blksz = 0;
|
||||
zp->z_seq = 0;
|
||||
|
||||
@@ -1522,7 +1522,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;
|
||||
sb->s_d_op = &zpl_dentry_operations;
|
||||
|
||||
/* Set features for file system. */
|
||||
zfs_set_fuid_feature(zfsvfs);
|
||||
@@ -1881,8 +1880,8 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds)
|
||||
zp = list_next(&zfsvfs->z_all_znodes, zp)) {
|
||||
err2 = zfs_rezget(zp);
|
||||
if (err2) {
|
||||
zpl_d_drop_aliases(ZTOI(zp));
|
||||
remove_inode_hash(ZTOI(zp));
|
||||
zp->z_is_stale = B_TRUE;
|
||||
}
|
||||
|
||||
/* see comment in zfs_suspend_fs() */
|
||||
|
||||
@@ -552,7 +552,6 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
|
||||
zp->z_atime_dirty = B_FALSE;
|
||||
zp->z_is_mapped = B_FALSE;
|
||||
zp->z_is_ctldir = B_FALSE;
|
||||
zp->z_is_stale = B_FALSE;
|
||||
zp->z_suspended = B_FALSE;
|
||||
zp->z_sa_hdl = NULL;
|
||||
zp->z_mapcnt = 0;
|
||||
|
||||
@@ -728,46 +728,6 @@ out:
|
||||
return (error);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
@@ -856,7 +816,3 @@ const struct inode_operations zpl_special_inode_operations = {
|
||||
.get_acl = zpl_get_acl,
|
||||
#endif /* CONFIG_FS_POSIX_ACL */
|
||||
};
|
||||
|
||||
dentry_operations_t zpl_dentry_operations = {
|
||||
.d_revalidate = zpl_revalidate,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user