* Brian Behlendorf <behlendorf1@llnl.gov>
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
+ * Copyright (c) 2018 George Melikov. All Rights Reserved.
*/
/*
* corresponding inode.
*
* All mounts are handled automatically by an user mode helper which invokes
- * the mount mount procedure. Unmounts are handled by allowing the mount
+ * the mount procedure. Unmounts are handled by allowing the mount
* point to expire so the kernel may automatically unmount it.
*
* The '.zfs', '.zfs/snapshot', and all directories created under
* '.zfs/snapshot' (ie: '.zfs/snapshot/<snapname>') all share the same
- * share the same zfsvfs_t as the head filesystem (what '.zfs' lives under).
+ * zfsvfs_t as the head filesystem (what '.zfs' lives under).
*
* File systems mounted on top of the '.zfs/snapshot/<snapname>' paths
* (ie: snapshots) are complete ZFS filesystems and have their own unique
* Control Directory Tunables (.zfs)
*/
int zfs_expire_snapshot = ZFSCTL_EXPIRE_SNAPSHOT;
-int zfs_admin_snapshot = 1;
+int zfs_admin_snapshot = 0;
typedef struct {
char *se_name; /* full snapshot name */
taskqid_t se_taskqid; /* scheduled unmount taskqid */
avl_node_t se_node_name; /* zfs_snapshots_by_name link */
avl_node_t se_node_objsetid; /* zfs_snapshots_by_objsetid link */
- refcount_t se_refcount; /* reference count */
+ zfs_refcount_t se_refcount; /* reference count */
} zfs_snapentry_t;
static void zfsctl_snapshot_unmount_delay_impl(zfs_snapentry_t *se, int delay);
se->se_root_dentry = root_dentry;
se->se_taskqid = TASKQID_INVALID;
- refcount_create(&se->se_refcount);
+ zfs_refcount_create(&se->se_refcount);
return (se);
}
/*
- * Free a zfs_snapentry_t the called must ensure there are no active
+ * Free a zfs_snapentry_t the caller must ensure there are no active
* references.
*/
static void
zfsctl_snapshot_free(zfs_snapentry_t *se)
{
- refcount_destroy(&se->se_refcount);
+ zfs_refcount_destroy(&se->se_refcount);
strfree(se->se_name);
strfree(se->se_path);
static void
zfsctl_snapshot_hold(zfs_snapentry_t *se)
{
- refcount_add(&se->se_refcount, NULL);
+ zfs_refcount_add(&se->se_refcount, NULL);
}
/*
static void
zfsctl_snapshot_rele(zfs_snapentry_t *se)
{
- if (refcount_remove(&se->se_refcount, NULL) == 0)
+ if (zfs_refcount_remove(&se->se_refcount, NULL) == 0)
zfsctl_snapshot_free(se);
}
zfsctl_snapshot_add(zfs_snapentry_t *se)
{
ASSERT(RW_WRITE_HELD(&zfs_snapshot_lock));
- refcount_add(&se->se_refcount, NULL);
+ zfs_refcount_add(&se->se_refcount, NULL);
avl_add(&zfs_snapshots_by_name, se);
avl_add(&zfs_snapshots_by_objsetid, se);
}
search.se_name = snapname;
se = avl_find(&zfs_snapshots_by_name, &search, NULL);
if (se)
- refcount_add(&se->se_refcount, NULL);
+ zfs_refcount_add(&se->se_refcount, NULL);
return (se);
}
search.se_objsetid = objsetid;
se = avl_find(&zfs_snapshots_by_objsetid, &search, NULL);
if (se)
- refcount_add(&se->se_refcount, NULL);
+ zfs_refcount_add(&se->se_refcount, NULL);
return (se);
}
static void
zfsctl_snapshot_unmount_cancel(zfs_snapentry_t *se)
{
- ASSERT(RW_LOCK_HELD(&zfs_snapshot_lock));
-
if (taskq_cancel_id(system_delay_taskq, se->se_taskqid) == 0) {
se->se_taskqid = TASKQID_INVALID;
zfsctl_snapshot_rele(se);
zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
const struct file_operations *fops, const struct inode_operations *ops)
{
- struct timespec now;
+ inode_timespec_t now;
struct inode *ip;
znode_t *zp;
uint64_t objsetid = dmu_objset_id(zfsvfs->z_os);
rw_enter(&zfs_snapshot_lock, RW_WRITER);
- if ((se = zfsctl_snapshot_find_by_objsetid(spa, objsetid))
- != NULL) {
- zfsctl_snapshot_unmount_cancel(se);
+ se = zfsctl_snapshot_find_by_objsetid(spa, objsetid);
+ if (se != NULL)
zfsctl_snapshot_remove(se);
+ rw_exit(&zfs_snapshot_lock);
+ if (se != NULL) {
+ zfsctl_snapshot_unmount_cancel(se);
zfsctl_snapshot_rele(se);
}
- rw_exit(&zfs_snapshot_lock);
} else if (zfsvfs->z_ctldir) {
iput(zfsvfs->z_ctldir);
zfsvfs->z_ctldir = NULL;
break;
}
- memset(full_path, 0, path_len);
- snprintf(full_path, path_len - 1, "%s/.zfs/snapshot/%s",
+ snprintf(full_path, path_len, "%s/.zfs/snapshot/%s",
zfsvfs->z_vfs->vfs_mntpoint, snapname);
out:
kmem_free(snapname, ZFS_MAX_DATASET_NAME_LEN);
/*
* Lookup entry point for the 'snapshot' directory. Try to open the
* snapshot if it exist, creating the pseudo filesystem inode as necessary.
- * Perform a mount of the associated dataset on top of the inode.
*/
int
zfsctl_snapdir_lookup(struct inode *dip, char *name, struct inode **ipp,
goto out;
/* Trigger automount */
- error = kern_path(mnt, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &path);
+ error = -kern_path(mnt, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &path);
if (error)
goto out;