dsched - Support policy switching via sysctl
authorAlex Hornung <ahornung@gmail.com>
Sun, 25 Apr 2010 21:21:24 +0000 (21:21 +0000)
committerAlex Hornung <ahornung@gmail.com>
Sun, 25 Apr 2010 21:21:24 +0000 (21:21 +0000)
* Add the sysctl dsched.policy tree to show the current policy of disks
  / serial numbers of disks and allow for switching to another available
  policy.

Requested-by: Sascha Wildner
sys/kern/kern_dsched.c
sys/sys/dsched.h

index 44b97d0..8c8efe3 100644 (file)
@@ -68,6 +68,8 @@ static int dsched_dev_list_disk(struct dsched_ioctl *data);
 static int dsched_dev_list_policies(struct dsched_ioctl *data);
 static int dsched_dev_handle_switch(char *disk, char *policy);
 
+static void dsched_sysctl_add_disk(struct dsched_disk_ctx *diskctx, char *name);
+
 static int     dsched_inited = 0;
 
 struct lock    dsched_lock;
@@ -172,6 +174,11 @@ dsched_disk_create_callback(struct disk *dp, const char *head_name, int unit)
                dsched_set_policy(dp, policy);
        }
 
+       ksnprintf(tunable_key, sizeof(tunable_key), "%s%d", head_name, unit);
+       dsched_sysctl_add_disk(
+           (struct dsched_disk_ctx *)dsched_get_disk_priv(dp),
+           tunable_key);
+
        lockmgr(&dsched_lock, LK_RELEASE);
 }
 
@@ -203,6 +210,10 @@ dsched_disk_update_callback(struct disk *dp, struct disk_info *info)
                dsched_switch(dp, policy);      
        }
 
+       dsched_sysctl_add_disk(
+           (struct dsched_disk_ctx *)dsched_get_disk_priv(dp),
+           info->d_serialno);
+
        lockmgr(&dsched_lock, LK_RELEASE);
 }
 
@@ -214,13 +225,20 @@ void
 dsched_disk_destroy_callback(struct disk *dp)
 {
        struct dsched_policy *old_policy;
+       struct dsched_disk_ctx *diskctx;
 
        lockmgr(&dsched_lock, LK_EXCLUSIVE);
 
+       diskctx = dsched_get_disk_priv(dp);
+
        old_policy = dp->d_sched_policy;
        dp->d_sched_policy = &dsched_default_policy;
        old_policy->cancel_all(dsched_get_disk_priv(dp));
        old_policy->teardown(dsched_get_disk_priv(dp));
+
+       if (diskctx->flags & DSCHED_SYSCTL_CTX_INITED)
+               sysctl_ctx_free(&diskctx->sysctl_ctx);
+
        policy_destroy(dp);
        atomic_subtract_int(&old_policy->ref_count, 1);
        KKASSERT(old_policy->ref_count >= 0);
@@ -1204,8 +1222,46 @@ sysctl_dsched_list_policies(SYSCTL_HANDLER_ARGS)
        return error;
 }
 
+static int
+sysctl_dsched_policy(SYSCTL_HANDLER_ARGS)
+{
+       char buf[DSCHED_POLICY_NAME_LENGTH];
+       struct dsched_disk_ctx *diskctx = arg1;
+       struct dsched_policy *pol = NULL;
+       int error;
+
+       if (diskctx == NULL) {
+               return 0;
+       }
+
+       lockmgr(&dsched_lock, LK_EXCLUSIVE);
+
+       pol = diskctx->dp->d_sched_policy;
+       memcpy(buf, pol->name, DSCHED_POLICY_NAME_LENGTH);
+
+       error = sysctl_handle_string(oidp, buf, DSCHED_POLICY_NAME_LENGTH, req);
+       if (error || req->newptr == NULL) {
+               lockmgr(&dsched_lock, LK_RELEASE);
+               return (error);
+       }
+
+       pol = dsched_find_policy(buf);
+       if (pol == NULL) {
+               lockmgr(&dsched_lock, LK_RELEASE);
+               return 0;
+       }
+
+       dsched_switch(diskctx->dp, pol);
+
+       lockmgr(&dsched_lock, LK_RELEASE);
+
+       return error;
+}
+
 SYSCTL_NODE(, OID_AUTO, dsched, CTLFLAG_RD, NULL,
     "Disk Scheduler Framework (dsched) magic");
+SYSCTL_NODE(_dsched, OID_AUTO, policy, CTLFLAG_RW, NULL,
+    "List of disks and their policies");
 SYSCTL_INT(_dsched, OID_AUTO, debug, CTLFLAG_RW, &dsched_debug_enable,
     0, "Enable dsched debugging");
 SYSCTL_PROC(_dsched, OID_AUTO, stats, CTLTYPE_OPAQUE|CTLFLAG_RD,
@@ -1214,3 +1270,15 @@ SYSCTL_PROC(_dsched, OID_AUTO, stats, CTLTYPE_OPAQUE|CTLFLAG_RD,
 SYSCTL_PROC(_dsched, OID_AUTO, policies, CTLTYPE_STRING|CTLFLAG_RD,
     NULL, 0, sysctl_dsched_list_policies, "A", "names of available policies");
 
+static void
+dsched_sysctl_add_disk(struct dsched_disk_ctx *diskctx, char *name)
+{
+       if (!(diskctx->flags & DSCHED_SYSCTL_CTX_INITED)) {
+               diskctx->flags |= DSCHED_SYSCTL_CTX_INITED;
+               sysctl_ctx_init(&diskctx->sysctl_ctx);
+       }
+
+       SYSCTL_ADD_PROC(&diskctx->sysctl_ctx, SYSCTL_STATIC_CHILDREN(_dsched_policy),
+           OID_AUTO, name, CTLTYPE_STRING|CTLFLAG_RW,
+           diskctx, 0, sysctl_dsched_policy, "A", "policy");
+}
index 7beffda..ca79b74 100644 (file)
@@ -105,8 +105,11 @@ struct dsched_disk_ctx {
        struct lock     lock;
 
        int32_t         refcount;
+       int32_t         flags;
 
        struct disk     *dp;            /* back pointer to disk struct */
+
+       struct sysctl_ctx_list sysctl_ctx;
 };
 
 struct dsched_thread_io {
@@ -183,8 +186,11 @@ TAILQ_HEAD(dsched_policy_head, dsched_policy);
 #define DSCHED_THREAD_CTX_UNLOCK(x)    lockmgr(&(x)->lock, LK_RELEASE);\
                                        dsched_thread_ctx_unref((x))
 
+/* flags for thread_io */
 #define        DSCHED_LINKED_DISK_CTX          0x01
 #define        DSCHED_LINKED_THREAD_CTX        0x02
+/* flags for disk_ctx */
+#define        DSCHED_SYSCTL_CTX_INITED        0x01
 
 #define DSCHED_THREAD_CTX_MAX_SZ       sizeof(struct dsched_thread_ctx)
 #define DSCHED_THREAD_IO_MAX_SZ                256