#include <sys/fcntl.h>
#include <machine/varargs.h>
+TAILQ_HEAD(tdio_list_head, dsched_thread_io);
+
MALLOC_DEFINE(M_DSCHED, "dsched", "dsched allocs");
static dsched_prepare_t noop_prepare;
DSCHED_THREAD_CTX_LOCK(tdctx);
KKASSERT(!TAILQ_EMPTY(&tdctx->tdio_list));
- TAILQ_FOREACH(tdio, &tdctx->tdio_list, link) {
+ /*
+ * XXX:
+ * iterate in reverse to make sure we find the most up-to-date
+ * tdio for a given disk. After a switch it may take some time
+ * for everything to clean up.
+ */
+ TAILQ_FOREACH_REVERSE(tdio, &tdctx->tdio_list, tdio_list_head, link) {
if (tdio->dp == dp) {
dsched_thread_io_ref(tdio);
found = 1;
KKASSERT(found == 1);
diskctx = dsched_get_disk_priv(dp);
dsched_disk_ctx_ref(diskctx);
+
+ if (dp->d_sched_policy != &dsched_noop_policy)
+ KKASSERT(tdio->debug_policy == dp->d_sched_policy);
+
+ KKASSERT(tdio->debug_inited == 0xF00F1234);
+
error = dp->d_sched_policy->bio_queue(diskctx, tdio, bio);
if (error) {
KKASSERT(policy->ref_count == 0);
}
lockmgr(&dsched_lock, LK_RELEASE);
+
return 0;
}
/* Bring everything back to life */
dsched_set_policy(dp, new_policy);
lockmgr(&dsched_lock, LK_RELEASE);
+
return 0;
}
locked = 1;
}
+ DSCHED_GLOBAL_THREAD_CTX_LOCK();
+
policy_new(dp, new_policy);
new_policy->prepare(dsched_get_disk_priv(dp));
dp->d_sched_policy = new_policy;
+
+ DSCHED_GLOBAL_THREAD_CTX_UNLOCK();
+
atomic_add_int(&new_policy->ref_count, 1);
kprintf("disk scheduler: set policy of %s to %s\n", dp->d_cdev->si_name,
new_policy->name);
#endif
DSCHED_GLOBAL_THREAD_CTX_LOCK();
+ lockmgr(&tdctx->lock, LK_EXCLUSIVE);
+
while ((tdio = TAILQ_FIRST(&tdctx->tdio_list)) != NULL) {
KKASSERT(tdio->flags & DSCHED_LINKED_THREAD_CTX);
TAILQ_REMOVE(&tdctx->tdio_list, tdio, link);
KKASSERT(tdctx->refcount == 0x80000000);
TAILQ_REMOVE(&dsched_tdctx_list, tdctx, link);
+ lockmgr(&tdctx->lock, LK_RELEASE);
+
DSCHED_GLOBAL_THREAD_CTX_UNLOCK();
objcache_put(dsched_tdctx_cache, tdctx);
atomic_set_int(&tdio->flags, DSCHED_LINKED_THREAD_CTX);
}
+ tdio->debug_policy = pol;
+ tdio->debug_inited = 0xF00F1234;
+
atomic_add_int(&dsched_stats.tdio_allocations, 1);
return tdio;
}
dsched_disk_ctx_ref(diskctx);
dsched_set_disk_priv(dp, diskctx);
- DSCHED_GLOBAL_THREAD_CTX_LOCK();
TAILQ_FOREACH(tdctx, &dsched_tdctx_list, link) {
tdio = dsched_thread_io_alloc(dp, tdctx, pol);
}
- DSCHED_GLOBAL_THREAD_CTX_UNLOCK();
-
}
void
#define dsched_get_bio_priv(bio) ((bio)?((bio)->bio_caller_info2.ptr):NULL)
#define dsched_set_bio_stime(bio, x) ((bio)->bio_caller_info3.lvalue = (x))
#define dsched_get_bio_stime(bio) ((bio)?((bio)->bio_caller_info3.lvalue):0)
+#define dsched_set_bio_tdio(bio, x) ((bio)->bio_caller_info3.ptr = (x))
+#define dsched_get_bio_tdio(bio) ((bio)?((bio)->bio_caller_info3.ptr):0)
struct dsched_thread_ctx {
struct sysctl_ctx_list sysctl_ctx;
};
+struct dsched_policy;
+
struct dsched_thread_io {
TAILQ_ENTRY(dsched_thread_io) link;
TAILQ_ENTRY(dsched_thread_io) dlink;
struct dsched_disk_ctx *diskctx;
struct dsched_thread_ctx *tdctx;
struct proc *p;
+ struct dsched_policy *debug_policy;
+ int debug_inited;
+ int debug_priv;
};
typedef int dsched_prepare_t(struct dsched_disk_ctx *diskctx);