DragonFly On-Line Manual Pages
DSCHED(9) DragonFly Kernel Developer's Manual DSCHED(9)
NAME
dsched, dsched_cancel_bio, dsched_debug, dsched_disk_ctx_ref,
dsched_disk_ctx_unref, dsched_new_policy_thread_tdio, dsched_register,
dsched_strategy_async, dsched_strategy_raw, dsched_thread_io_ref,
dsched_thread_io_unref, dsched_unregister, DSCHED_POLICY_MODULE,
DSCHED_DISK_CTX_LOCK, DSCHED_DISK_CTX_UNLOCK, DSCHED_THREAD_IO_LOCK,
DSCHED_THREAD_IO_UNLOCK, dsched_get_bio_dp, dsched_get_bio_priv,
dsched_get_disk_priv -- kernel disk scheduler framework
SYNOPSIS
#include <sys/dsched.h>
Functions:
void
dsched_cancel_bio(struct bio *bp);
int
dsched_debug(int level, char *fmt, ...);
void
dsched_disk_ctx_ref(struct dsched_disk_ctx *diskctx);
void
dsched_disk_ctx_unref(struct dsched_disk_ctx *diskctx);
void
dsched_new_policy_thread_tdio(struct dsched_disk_ctx *diskctx,
struct dsched_policy *pol);
int
dsched_register(struct dsched_policy *d_policy);
void
dsched_strategy_async(struct disk *dp, struct bio *bp, biodone_t *done,
void *priv);
void
dsched_strategy_raw(struct disk *dp, struct bio *bp);
void
dsched_thread_io_ref(struct dsched_thread_io *tdio);
void
dsched_thread_io_unref(struct dsched_thread_io *tdio);
int
dsched_unregister(struct dsched_policy *d_policy);
Macros:
DSCHED_POLICY_MODULE(name, modeventhand_t evh, version);
DSCHED_DISK_CTX_LOCK(struct dsched_disk_ctx *diskctx);
DSCHED_DISK_CTX_UNLOCK(struct dsched_disk_ctx *diskctx);
DSCHED_THREAD_IO_LOCK(struct dsched_thread_io *tdio);
DSCHED_THREAD_IO_UNLOCK(struct dsched_thread_io *tdio);
dsched_get_bio_dp(struct bio *bio);
dsched_get_bio_priv(struct bio *bio);
dsched_get_disk_priv(struct disk *dp, void *priv);
Callbacks:
typedef int
dsched_prepare_t(struct dsched_disk_ctx *diskctx);
typedef void
dsched_teardown_t(struct dsched_disk_ctx *diskctx);
typedef void
dsched_cancel_t(struct dsched_disk_ctx *diskctx);
typedef int
dsched_queue_t(struct dsched_disk_ctx *diskctx,
struct dsched_thread_io *tdio, struct bio *bio);
typedef void
dsched_new_tdio_t(struct dsched_thread_io *tdio);
typedef void
dsched_destroy_tdio_t(struct dsched_thread_io *tdio);
typedef void
dsched_new_diskctx_t(struct dsched_disk_ctx *diskctx);
typedef void
dsched_destroy_diskctx_t(struct dsched_disk_ctx *diskctx);
DESCRIPTION
To create a new dsched policy `foo' the following is required:
DSCHED_POLICY_MODULE(dsched_foo, foo_mod_handler, 1);
struct dsched_policy dsched_foo_policy = {
.name = "foo",
.prepare = foo_prepare,
.teardown = foo_teardown,
.cancel_all = foo_cancel,
.bio_queue = foo_queue,
/* The following are optional */
.new_tdio = foo_tdio_ctor,
.new_diskctx = foo_diskctx_ctor,
.destroy_tdio = foo_tdio_dtor,
.destroy_diskctx = foo_diskctx_dtor
};
The name is the unique identifier of the dsched policy and the name the
user specifies to set this dsched policy.
The prepare callback is called whenever the new dsched policy is set for
a new disk. This can be used to create per disk threads for the dsched
policy instance. Note that any thread created during prepare will not
have a dsched_thread_ctx or dsched_thread_io associated with it. If this
is required because the thread will do I/O, the thread itself needs to
call dsched_new_policy_thread_tdio().
The teardown callback is called whenever a dsched policy is
unset/detached from a disk or when a disk is disconnected. It should
clean up all per-disk resources such as any thread created in prepare.
The dsched framework guarantees that no more calls to any other method
such as bio_queue will occur once teardown has been called.
The cancel_all callback is called immediately before teardown. It is
required to cancel all bios currently queued or stalled in the dsched
policy instance for the given disk. The dsched framework guarantees that
no more calls to any other method such as bio_queue will occur once
cancel_all has been called.
The bio_queue callback is called for every bio intended for the disk(s)
with the given dsched policy. It needs to either dispatch it, queue it
in any other form for later dispatch, or return a non-zero return value,
in which case the dsched framework will dispatch that bio directly. If
the function took care of the bio and does not want dsched to dispatch
it, 0 must be returned.
The new_tdio callback is called for every dsched_thread_io created for a
disk with this dsched policy. Similarly, the destroy_tdio callback is
called on destruction (release of all references) of the
dsched_thread_io. These functions don't have to be specified; if they
are left out or set to NULL they simply won't be called.
The new_diskctx callback is called for every dsched_disk_ctx created for
a disk with this dsched policy. Similarly, the destroy_diskctx callback
is called on destruction (release of all references) of the
dsched_disk_ctx. These functions don't have to be specified; if they are
left out or set to NULL, they simply won't be called.
For convenience, the structs dsched_thread_io and dsched_disk_ctx are
allocated with plenty of spare space, so that each policy can extend
these, for example as follows:
struct foo_thread_io {
struct dsched_thread_io head;
int foo;
int bar;
};
struct foo_disk_ctx {
struct dsched_disk_ctx head;
int foo;
int bar;
};
CTASSERT(sizeof(struct foo_thread_io) <= DSCHED_THREAD_IO_MAX_SZ);
CTASSERT(sizeof(struct foo_disk_ctx) <= DSCHED_DISK_CTX_MAX_SZ);
It is important that the first member of the new struct is one of type
dsched_thread_io or dsched_disk_ctx, respectively. The CTASSERT() must
be used to ensure that the new structs fit into the space provided by
dsched. Not including these asserts can cause serious and difficult to
debug issues. For all the functions described in FUNCTIONS that require
a dsched_thread_io or dsched_disk_ctx, the address of the head element
should be passed, or alternatively the address of the new struct be cast
to the right type and that passed.
FUNCTIONS
The DSCHED_POLICY_MODULE() macro declares a dsched policy kernel module.
evh is the event handler for the module (see DECLARE_MODULE(9) for more
information). The event handler is supposed to register a dsched policy
with dsched_register() on load and to unregister it using
dsched_unregister() when it is unloaded. version is the version number
of the module (see MODULE_VERSION(9) for more information).
The dsched_strategy_async() function dispatches a bio bp in an asynchro-
nous manner to the disk specified by dp. The private data priv will be
attached to the bio and is later retrievable via dsched_get_bio_priv().
The biodone_t routine done will be called once the bio completes. The
done routine can use dsched_get_disk_priv(), dsched_get_bio_dp() and
dsched_get_bio_priv() to retrieve the context. Since
dsched_strategy_async() also saves the current time (via getmicrotime())
in bio->bio_caller_info3.tv, the done routine can also calculate the time
passed from dispatch to completion by getting the current time again (via
getmicrotime()) and calculating the timeval difference to the value
stored in bio->bio_caller_info3.tv. At the end of the done routine it
needs to call pop_bio() and biodone() as for any other biodone_t routine.
The dsched_cancel_bio() function cancels the bio and sets ENXIO as error
on the buf.
The dsched_strategy_raw() function simply dispatches the bio directly to
the disk specified by dp using dev_dstrategy().
The dsched_debug() function works as a conditional kprintf(). Depending
on the setting of the dsched.debug sysctl(8) variable, the debug info
will be shown or not.
The dsched_register() function registers the policy described by d_policy
as a valid dsched policy which can then be used as a scheduler policy for
the disks. If a policy with the given name already exists, EEXIST is
returned (otherwise 0).
The dsched_unregister() function unregisters the policy described by
d_policy. The given dsched policy will no longer be valid as a scheduler
policy. If the given policy is currently in use, EBUSY will be returned
and the policy won't be unregistered; otherwise 0 is returned.
The DSCHED_THREAD_IO_LOCK() and DSCHED_THREAD_IO_UNLOCK() functions lock
and unlock a dsched_thread_io tdio, respectively. The lock must be held
whenever the members queue and qlength are manipulated to avoid messing
up the TAILQ. It can also be used to serialize any other access to the
derived foo_thread_io members.
The DSCHED_DISK_CTX_LOCK() and DSCHED_DISK_CTX_UNLOCK() functions lock
and unlock a dsched_disk_ctx diskctx, respectively. The lock must be
held whenever the member queue is manipulated to avoid messing up the
TAILQ. It can also be used to serialize any other access to the derived
foo_disk_ctx members.
The dsched_thread_io_ref() and dsched_thread_io_unref() functions
increase and decrease the reference count on a dsched_thread_io tdio,
respectively. Whenever the reference count drops to 0, the tdio will be
released. Be aware that it is possible that the dsched framework holds
references on the tdio, too, so it can be that the object is not freed
when all references are dropped.
The dsched_disk_ctx_ref() and dsched_disk_ctx_unref() functions increase
and decrease the reference count on a dsched_disk_ctx diskctx, respec-
tively. Whenever the reference count drops to 0, the diskctx will be
released. Be aware that it is possible that the dsched framework holds
references on the diskctx, too, so it can be that the object is not freed
when all references are dropped.
The dsched_get_bio_dp(), dsched_get_disk_priv() and dsched_get_bio_priv()
are intended for use in the biodone_t routine specified in the call to
dsched_strategy_async(). dsched_get_bio_dp() retrieves the struct disk
associated with the bio. This can then be used to retrieve the struct
dsched_disk_ctx via dsched_get_disk_priv(). The dsched_get_bio_priv()
function returns the private data associated with the bio on the call to
dsched_strategy_async().
The dsched_new_policy_thread_tdio() function must be called from any
thread created within the prepare method that will perform I/O, since
these won't have a dsched_thread_io associated with them.
FILES
The uncontended path of the dsched implementation is in
/sys/kern/kern_dsched.c. The data structures are in /sys/sys/dsched.h.
SEE ALSO
dsched(4)
HISTORY
The dsched framework first appeared in DragonFly 2.5.
AUTHORS
The dsched framework was written by Alex Hornung.
DragonFly 4.3 September 18, 2013 DragonFly 4.3