aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_ctldir.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zfs_ctldir.c')
-rw-r--r--module/zfs/zfs_ctldir.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/module/zfs/zfs_ctldir.c b/module/zfs/zfs_ctldir.c
index d139b8613..a667340c8 100644
--- a/module/zfs/zfs_ctldir.c
+++ b/module/zfs/zfs_ctldir.c
@@ -90,6 +90,11 @@
*/
int zfs_expire_snapshot = ZFSCTL_EXPIRE_SNAPSHOT;
+/*
+ * Dedicated task queue for unmounting snapshots.
+ */
+static taskq_t *zfs_expire_taskq;
+
static zfs_snapentry_t *
zfsctl_sep_alloc(void)
{
@@ -112,16 +117,15 @@ zfsctl_sep_free(zfs_snapentry_t *sep)
static void
zfsctl_expire_snapshot(void *data)
{
- zfs_snapentry_t *sep;
- zfs_sb_t *zsb;
+ zfs_snapentry_t *sep = (zfs_snapentry_t *)data;
+ zfs_sb_t *zsb = ITOZSB(sep->se_inode);
int error;
- sep = spl_get_work_data(data, zfs_snapentry_t, se_work.work);
- zsb = ITOZSB(sep->se_inode);
-
error = zfsctl_unmount_snapshot(zsb, sep->se_name, MNT_EXPIRE);
if (error == EBUSY)
- schedule_delayed_work(&sep->se_work, zfs_expire_snapshot * HZ);
+ sep->se_taskqid = taskq_dispatch_delay(zfs_expire_taskq,
+ zfsctl_expire_snapshot, sep, TQ_SLEEP,
+ ddi_get_lbolt() + zfs_expire_snapshot * HZ);
}
int
@@ -661,7 +665,7 @@ zfsctl_snapdir_inactive(struct inode *ip)
if (sep->se_inode == ip) {
avl_remove(&zsb->z_ctldir_snaps, sep);
- cancel_delayed_work_sync(&sep->se_work);
+ taskq_cancel_id(zfs_expire_taskq, sep->se_taskqid);
zfsctl_sep_free(sep);
break;
}
@@ -708,7 +712,8 @@ __zfsctl_unmount_snapshot(zfs_snapentry_t *sep, int flags)
* to prevent zfsctl_expire_snapshot() from attempting a unmount.
*/
if ((error == 0) && !(flags & MNT_EXPIRE))
- cancel_delayed_work(&sep->se_work);
+ taskq_cancel_id(zfs_expire_taskq, sep->se_taskqid);
+
return (error);
}
@@ -837,7 +842,7 @@ zfsctl_mount_snapshot(struct path *path, int flags)
sep = avl_find(&zsb->z_ctldir_snaps, &search, NULL);
if (sep) {
avl_remove(&zsb->z_ctldir_snaps, sep);
- cancel_delayed_work_sync(&sep->se_work);
+ taskq_cancel_id(zfs_expire_taskq, sep->se_taskqid);
zfsctl_sep_free(sep);
}
@@ -847,8 +852,9 @@ zfsctl_mount_snapshot(struct path *path, int flags)
sep->se_inode = ip;
avl_add(&zsb->z_ctldir_snaps, sep);
- spl_init_delayed_work(&sep->se_work, zfsctl_expire_snapshot, sep);
- schedule_delayed_work(&sep->se_work, zfs_expire_snapshot * HZ);
+ sep->se_taskqid = taskq_dispatch_delay(zfs_expire_taskq,
+ zfsctl_expire_snapshot, sep, TQ_SLEEP,
+ ddi_get_lbolt() + zfs_expire_snapshot * HZ);
mutex_exit(&zsb->z_ctldir_lock);
error:
@@ -977,6 +983,8 @@ zfsctl_shares_lookup(struct inode *dip, char *name, struct inode **ipp,
void
zfsctl_init(void)
{
+ zfs_expire_taskq = taskq_create("z_unmount", 1, maxclsyspri,
+ 1, 8, TASKQ_PREPOPULATE);
}
/*
@@ -986,6 +994,7 @@ zfsctl_init(void)
void
zfsctl_fini(void)
{
+ taskq_destroy(zfs_expire_taskq);
}
module_param(zfs_expire_snapshot, int, 0644);