sbin/hammer2/hammer2.8: Correct default vfs.hammer2.cluster_write value
[dragonfly.git] / doc / porting_drivers.txt
blobed23e5a3b945f0f965d65b1b293ba5514ceab0cb
1                     PORTING FREEBSD DRIVERS TO DRAGONFLY
3 * Copy the driver code to the appropriate DragonFly directory.  For example,
4   a disk driver /usr/src/sys/dev/blah in FreeBSD would likely be
5   /usr/src/sys/dev/disk/blah in DragonFly.
7 * Keep all the SVN IDs in the files as a future reference point. dports' SVN
8   will do that by default. When using the FreeBSD git repo, please note the
9   files' IDs manually, either in the files themselves or in the commit message.
10   The general idea is that it must not get lost.
12 * Driver local #include's probably use a <dev/blah/blah.h> path.  These
13   need to be changed to "blah.h".   '.' is not included in the #include
14   path in FreeBSD builds, but it is in DragonFly builds.
16 * Other #include's may reference things in <dev/...> which in DragonFly
17   reside in <bus/...>.  In particular, dev/pccard becomes bus/pccard.
18   Note that defines in FreeBSD's pccard_cis.h reside in DragonFly's
19   pccardreg.h .
21 * The following kernel functions have been renamed in DragonFly:
23   malloc(), free() etc. ->      kmalloc(), kfree() etc.
24   printf() etc.         ->      kprintf() etc.
25   psignal()             ->      ksignal()
26   random()              ->      krandom()
28 * MUTEX conversion - mutexes are generally replaced by spinlocks.  However,
29   DragonFly spinlocks are more restrictive than FreeBSD mutexes so a
30   direct replacement is not necessarily appropriate in all cases.  A lockmgr
31   lock should be used when a direct replacement is not appropriate.
32   In particular, DragonFly does not allow recursive exclusive spinlocks
33   and does not allow multiple exclusive spinlocks to be held by any given
34   thread.
36   Instances of <sys/mutex.h> should be replaced with <sys/spinlock.h>.
38   When replacing mutexes with spinlocks it is a good idea to rename
39   the structural field (typically 'mtx') to something else (typically 'spin').
41   The &Giant mutex is typically converted to get_mplock() and rel_mplock().
42   However, there are places where FreeBSD unlocks giant around some code and
43   then relocks giant... those should simply be removed.
45   FreeBSD has weird callout + mutex functions.  DragonFly does not integrate
46   the two.  Instead, the driver in DragonFly must obtain the spinlocks
47   in question in the callback routine.
49   As a rule of thumb, MTX_DEF mutexes should be replaced with exclusive,
50   recursive lockmgr locks.
52   So, suppose the original code is using
53         struct mtx my_mtx;
54   you'd normally rename it to
55         struct lock my_lock;
57   and change the initialization from something like
58         mtx_init(&my_mtx, "mymtx", "whatever", MTX_DEF);
59   to
60         lockinit(&my_lock, "mylock", 0, LK_CANRECURSE);
62   Destroying it is trivial,
63         mtx_destroy(&my_mtx);
64   becomes
65         lockuninit(&my_lock);
67   You use the same function for locking and unlocking a lockmgr lock,
68   so exchange
69         mtx_lock(&my_mtx);
70   with
71         lockmgr(&my_lock, LK_EXCLUSIVE);
72   and
73         mtx_unlock(&my_mtx);
74   with
75         lockmgr(&my_lock, LK_RELEASE);
77   For testing the lock status, one would use
78         lockstatus(&my_lock, curthread);
79   in place of
80         mtx_owned(&my_mtx);
82   An
83         mtx_trylock(&my_mtx);
84   call is replaced with
85         lockmgr_try(&my_lock, LK_EXCLUSIVE);
87   As for mtx_assert() calls, translate them like this:
89         mtx_assert(&my_mtx, MA_OWNED) -> KKASSERT(lockstatus(&my_lock, curthread) != 0)
90         mtx_assert(&my_mtx, MA_NOTOWNED) -> KKASSERT(lockstatus(&my_lock, curthread) == 0)
92   In DragonFly, lockstatus() does not return information about whether there have been
93   recursive lock acquisitions, so there is no generic way to emulate the
95         mtx_assert(&my_mtx, MA_OWNED|MA_RECURSED);
96         mtx_assert(&my_mtx, MA_OWNED|MA_NOTRECURSED);
98   calls.
100 * rwlock conversion: Use lockmgr locks
102 * UMA conversion - generally speaking UMA should be converted to a standard
103   kmalloc.
105   Note however that in FreeBSD M_NOWAIT is often used in cases where, in fact,
106   the kmalloc cannot fail without blowing something up or causing a fatal
107   (and very unexpected) I/O error.  M_INTWAIT should be used for these cases.
109 * CDEVSW conversion - see other devices.  Generally speaking a major number
110   is needed and a function map needs to be specified more explicitly.
112   Most calls passing struct cdev pointers are dev_t's in DragonFly.
114   All device vectors in DragonFly pass a dev_<name>_args structure pointer
115   instead of explicit arguments.
117   Strategy calls - we pass BIO's and a lot of BUF fields are in the BIO
118   in FreeBSD, but left in the BUF in DragonFly.  FreeBSD for some reason
119   names its struct bio pointers 'bp', its a good idea to rename them to 'bio'
120   to avoid confusion and have a struct buf *bp = bio->bio_buf; pointer to
121   access the buf.
123 * MSLEEP/TSLEEP conversion.  The DragonFly msleep/tsleep do not have 'PRI'
124   priorities.  0 should be used.
126 * BUS_* FUNCTIONS
128   bus_setup_intr() - replace INTR_TYPE_* flags with 0.  There is an extra
129   argument for an interrupt interlock using the sys/serializer.h interface.
130   This can either be left NULL or you can convert the spinlock(s) for
131   the driver into serializer locks and integrate the interrupt service
132   routine with a serializer.
134 * CAM CODE - cam_simq* code refcounts, so shared device queues (raid and
135   multi-channel devices) are not freed before all references have gone
136   away.
138 * UNRHDR functions - DragonFly uses a more generic idr(9) subsystem
139   compatible with the Linux API of the same name
141   This LWN article describes it in details: http://lwn.net/Articles/103209/
143   A typical conversion looks like this:
145   #include <sys/idr.h>
147   free_unr() has to be replaced by idr_remove()
149   alloc_unr() has to be replaced by a code sequence using idr_pre_get and
150   idr_get_new such as this one:
152   retry:
153         if (idr_pre_get(xxx) ==0) {
154         kprintf("Memory allocation error\n");
155             return error;
156         }
157         spin_lock(xxx);
158         ret = idr_get_new(xxx);
159         spin_unlock(xxx);
160         if (ret == EAGAIN)
161             goto retry;
163 * MPASS macro - Replace it with KKASSERT
166 * PROC_LOCK / PROC_UNLOCK: to be determined on a case-by-case basis
168   Some of the time these macros can be removed entirely
170   In some cases, some locking must be done; lwkt_gettoken(&proc_token)
171   and the corresponding lwkt_reltoken() call should be good replacements
173   It is not a good idea to blindly implement these macros globally, some
174   particular proc subsystem locking semantics differ enough between FreeBSD
175   and DragonFly that this would cause problems
177 * In DragonFly 5.1 format specifier %b was replaced by args safe "%pb%i" version
178   that only needs argument swapping. Replacement functions where not added.
180         kvcprintf("reg=%pb%i\n", "\10\2BITTWO\1BITONE\n", 3);
182 * In DragonFly 5.1 format specifier %r was removed from kprintf. As a
183   replacement function makedev_unit_b32() was added.
185   - Unit suffix encoded as base32 for make_dev() device creation:
187         char tbuf[MAKEDEV_MINNBUF];
189         kbd->kb_dev = make_dev(&kbd_ops, kbd->kb_index,
190                                 UID_ROOT, GID_WHEEL, 0600, "kbd%s",
191                                 makedev_unit_b32(tbuf, kbd->kb_index));
193   - For single character case the hex2ascii() can be used to avoid buffers:
195         kprintf("%c\n", hex2ascii(n % base));
197 * In DragonFly 3.3 format specifier %D was removed from kprintf. As a
198   replacement functions kether_ntoa() and hexncpy() were added.
200   - Ethernet address (MAC) to its hexadecimal form:
202         char ethstr[ETHER_ADDRSTRLEN + 1];
203         u_char hwaddr[6];
205         kprintf("MAC address %s\n", kether_ntoa(hwaddr, ethstr)
207   - Generic conversion (block of bytes to hexadecimal form):
209         char hexstr[18];
210         u_char mydata[6] = {1, 2, 3, 4, 5 ,6};
212         /*
213          * Below statement would print:
214          *
215          * 01-02-03-04-05-06
216          */
217         kprintf("%s\n", hexncpy(mydata, 6, hexstr, HEX_NCPYLEN(6), "-"));
219 * TAILQ_XXX_SAFE
221   Use TAILQ_XXX_MUTABLE; the macros have the same effect, only the name is
222   different
224 * kern_yield()
226   Replace by lwkt_yield()
228 * vm_page_lock() and vm_page_unlock()
230   Not needed on DragonFly, remove these calls
232 * vm_pager_get_pages()
234   Removed, use vm_pager_get_page() instead
236 * VPO_BUSY
238   Replace by PG_BUSY
240 * kern_psignal()
242   Replace by ksignal()