summaryrefslogtreecommitdiffstats
path: root/sys/geom/sched/gs_scheduler.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/geom/sched/gs_scheduler.h')
-rw-r--r--sys/geom/sched/gs_scheduler.h236
1 files changed, 236 insertions, 0 deletions
diff --git a/sys/geom/sched/gs_scheduler.h b/sys/geom/sched/gs_scheduler.h
new file mode 100644
index 0000000..fa9cb14
--- /dev/null
+++ b/sys/geom/sched/gs_scheduler.h
@@ -0,0 +1,236 @@
+/*-
+ * Copyright (c) 2009-2010 Fabio Checconi, Luigi Rizzo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ * $FreeBSD$
+ *
+ * Prototypes for GEOM-based disk scheduling algorithms.
+ * See g_sched.c for generic documentation.
+ *
+ * This file is used by the kernel modules implementing the various
+ * scheduling algorithms. They should provide all the methods
+ * defined in struct g_gsched, and also invoke the macro
+ * DECLARE_GSCHED_MODULE
+ * which registers the scheduling algorithm with the geom_sched module.
+ *
+ * The various scheduling algorithms do not need to know anything
+ * about geom, they only need to handle the 'bio' requests they
+ * receive, pass them down when needed, and use the locking interface
+ * defined below.
+ */
+
+#ifndef _G_GSCHED_H_
+#define _G_GSCHED_H_
+
+#ifdef _KERNEL
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/queue.h>
+#include <geom/geom.h>
+#include "g_sched.h"
+
+/*
+ * This is the interface exported to scheduling modules.
+ *
+ * gs_init() is called when our scheduling algorithm
+ * starts being used by a geom 'sched'
+ *
+ * gs_fini() is called when the algorithm is released.
+ *
+ * gs_start() is called when a new request comes in. It should
+ * enqueue the request and return 0 if success, or return non-zero
+ * in case of failure (meaning the request is passed down).
+ * The scheduler can use bio->bio_caller1 to store a non-null
+ * pointer meaning the request is under its control.
+ *
+ * gs_next() is called in a loop by g_sched_dispatch(), right after
+ * gs_start(), or on timeouts or 'done' events. It should return
+ * immediately, either a pointer to the bio to be served or NULL
+ * if no bio should be served now. If force is specified, a
+ * work-conserving behavior is expected.
+ *
+ * gs_done() is called when a request under service completes.
+ * In turn the scheduler may decide to call the dispatch loop
+ * to serve other pending requests (or make sure there is a pending
+ * timeout to avoid stalls).
+ *
+ * gs_init_class() is called when a new client (as determined by
+ * the classifier) starts being used.
+ *
+ * gs_hash_unref() is called right before the class hashtable is
+ * destroyed; after this call, the scheduler is supposed to hold no
+ * more references to the elements in the table.
+ */
+
+/* Forward declarations for prototypes. */
+struct g_geom;
+struct g_sched_class;
+
+typedef void *gs_init_t (struct g_geom *geom);
+typedef void gs_fini_t (void *data);
+typedef int gs_start_t (void *data, struct bio *bio);
+typedef void gs_done_t (void *data, struct bio *bio);
+typedef struct bio *gs_next_t (void *data, int force);
+typedef int gs_init_class_t (void *data, void *priv);
+typedef void gs_fini_class_t (void *data, void *priv);
+typedef void gs_hash_unref_t (void *data);
+
+struct g_gsched {
+ const char *gs_name;
+ int gs_refs;
+ int gs_priv_size;
+
+ gs_init_t *gs_init;
+ gs_fini_t *gs_fini;
+ gs_start_t *gs_start;
+ gs_done_t *gs_done;
+ gs_next_t *gs_next;
+ g_dumpconf_t *gs_dumpconf;
+
+ gs_init_class_t *gs_init_class;
+ gs_fini_class_t *gs_fini_class;
+ gs_hash_unref_t *gs_hash_unref;
+
+ LIST_ENTRY(g_gsched) glist;
+};
+
+#define KTR_GSCHED KTR_SPARE4
+
+MALLOC_DECLARE(M_GEOM_SCHED);
+
+/*
+ * Basic classification mechanism. Each request is associated to
+ * a g_sched_class, and each scheduler has the opportunity to set
+ * its own private data for the given (class, geom) pair. The
+ * private data have a base type of g_sched_private, and are
+ * extended at the end with the actual private fields of each
+ * scheduler.
+ */
+struct g_sched_class {
+ int gsc_refs;
+ int gsc_expire;
+ u_long gsc_key;
+ LIST_ENTRY(g_sched_class) gsc_clist;
+
+ void *gsc_priv[0];
+};
+
+/*
+ * Manipulate the classifier's data. g_sched_get_class() gets a reference
+ * to the the class corresponding to bp in gp, allocating and initializing
+ * it if necessary. g_sched_put_class() releases the reference.
+ * The returned value points to the private data for the class.
+ */
+void *g_sched_get_class(struct g_geom *gp, struct bio *bp);
+void g_sched_put_class(struct g_geom *gp, void *priv);
+
+static inline struct g_sched_class *
+g_sched_priv2class(void *priv)
+{
+
+ return ((struct g_sched_class *)((u_long)priv -
+ offsetof(struct g_sched_class, gsc_priv)));
+}
+
+static inline void
+g_sched_priv_ref(void *priv)
+{
+ struct g_sched_class *gsc;
+
+ gsc = g_sched_priv2class(priv);
+ gsc->gsc_refs++;
+}
+
+/*
+ * Locking interface. When each operation registered with the
+ * scheduler is invoked, a per-instance lock is taken to protect
+ * the data associated with it. If the scheduler needs something
+ * else to access the same data (e.g., a callout) it must use
+ * these functions.
+ */
+void g_sched_lock(struct g_geom *gp);
+void g_sched_unlock(struct g_geom *gp);
+
+/*
+ * Restart request dispatching. Must be called with the per-instance
+ * mutex held.
+ */
+void g_sched_dispatch(struct g_geom *geom);
+
+/*
+ * Simple gathering of statistical data, used by schedulers to collect
+ * info on process history. Just keep an exponential average of the
+ * samples, with some extra bits of precision.
+ */
+struct g_savg {
+ uint64_t gs_avg;
+ unsigned int gs_smpl;
+};
+
+static inline void
+g_savg_add_sample(struct g_savg *ss, uint64_t sample)
+{
+
+ /* EMA with alpha = 0.125, fixed point, 3 bits of precision. */
+ ss->gs_avg = sample + ss->gs_avg - (ss->gs_avg >> 3);
+ ss->gs_smpl = 1 + ss->gs_smpl - (ss->gs_smpl >> 3);
+}
+
+static inline int
+g_savg_valid(struct g_savg *ss)
+{
+
+ /* We want at least 8 samples to deem an average as valid. */
+ return (ss->gs_smpl > 7);
+}
+
+static inline uint64_t
+g_savg_read(struct g_savg *ss)
+{
+
+ return (ss->gs_avg / ss->gs_smpl);
+}
+
+/*
+ * Declaration of a scheduler module.
+ */
+int g_gsched_modevent(module_t mod, int cmd, void *arg);
+
+#define DECLARE_GSCHED_MODULE(name, gsched) \
+ static moduledata_t name##_mod = { \
+ #name, \
+ g_gsched_modevent, \
+ gsched, \
+ }; \
+ DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); \
+ MODULE_DEPEND(name, geom_sched, 0, 0, 0);
+
+#endif /* _KERNEL */
+
+#endif /* _G_GSCHED_H_ */
OpenPOWER on IntegriCloud