]> granicus.if.org Git - zfs/commitdiff
Linux 3.7 compat, schedule_delayed_work()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 10 Dec 2012 18:15:12 +0000 (10:15 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 12 Dec 2012 18:47:05 +0000 (10:47 -0800)
Linux kernel commit d8e794d accidentally broke the delayed work
APIs for non-GPL callers.   While the APIs to schedule a delayed
work item are still available to all callers, it is no longer
possible to initialize the delayed work item.

I'm cautiously optimistic we could get the delayed_work_timer_fn
exported for all callers in the upstream kernel.  But frankly
the compatibility code to use this kernel interface has always
been problematic.

Therefore, this patch abandons direct use the of the Linux
kernel interface in favor of the new delayed taskq interface.
It provides roughly the same functionality as delayed work queues
but it's a stable interface under our control.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #1053

include/sys/zfs_ctldir.h
module/zfs/zfs_ctldir.c

index 0a3c142eb76a86f9a67bd6dd715ca6b23dffdb9a..1ff23a298856dbae7afbd7dd44fb07ead86399f4 100644 (file)
@@ -50,7 +50,7 @@ typedef struct {
        char                    *se_name;
        char                    *se_path;
        struct inode            *se_inode;
-       struct delayed_work     se_work;
+       taskqid_t               se_taskqid;
        avl_node_t              se_node;
 } zfs_snapentry_t;
 
index d139b86136b2da54d2655f33e9a9cf0e1517d1b6..a667340c8d9b50ad0d005130a7b90b022aa79156 100644 (file)
  */
 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);