7f3e1d61b02dca1418fd78dfe53a2d9079a31d6a
[dragonfly.git] / sys / netgraph7 / dragonfly.c
1 #include <netgraph/ng_message.h>
2
3 #include <sys/malloc.h>
4 #include <sys/linker.h>
5 #include <sys/thread2.h>
6 #include <sys/vnode.h>
7
8 #include "dragonfly.h"
9
10 /* Temporary lock stuff. */
11 #include <sys/lock.h>
12 /* End Temporary lock stuff. */
13
14 int
15 linker_api_available(void)
16 {
17         /* linker_* API won't work without a process context */
18         if (curproc == NULL)
19                 return 0;
20         /*
21          * nlookup_init() relies on namei_oc to be initialized,
22          * but it's not when the netgraph module is loaded during boot.
23          */
24         if (namei_oc == NULL)
25                 return 0;
26         return 1;
27 }
28
29 int
30 ng_load_module(const char *name)
31 {
32         char *path, filename[NG_TYPESIZ + 3];
33         linker_file_t lf;
34         int error;
35
36         if (!linker_api_available())
37                 return (ENXIO);
38
39         /* Not found, try to load it as a loadable module */
40         ksnprintf(filename, sizeof(filename), "ng_%s.ko", name);
41         if ((path = linker_search_path(filename)) == NULL)
42                 return (ENXIO);
43         error = linker_load_file(path, &lf);
44         FREE(path, M_LINKER);
45         if (error == 0)
46                 lf->userrefs++;         /* pretend kldload'ed */
47         return (error);
48 }
49
50 int
51 ng_unload_module(const char *name)
52 {
53         char filename[NG_TYPESIZ + 3];
54         linker_file_t lf;
55         int error;
56
57         if (!linker_api_available())
58                 return (ENXIO);
59
60         /* Not found, try to load it as a loadable module */
61         ksnprintf(filename, sizeof(filename), "ng_%s.ko", name);
62         if ((lf = linker_find_file_by_name(filename)) == NULL)
63                 return (ENXIO);
64         error = linker_file_unload(lf);
65
66         if (error == 0)
67                 lf->userrefs--;         /* pretend kldunload'ed */
68         return (error);
69 }
70
71
72
73 /* Locking stuff. */
74
75
76 int
77 lockstatus_owned(struct lock *lkp, struct thread *td)
78 {
79         int lock_type = 0;
80
81         if (lkp->lk_exclusivecount != 0) {
82                 if (td == NULL || lkp->lk_lockholder == td)
83                         lock_type = LK_EXCLUSIVE;
84                 else
85                         lock_type = LK_EXCLOTHER;
86         } else if (lkp->lk_sharecount != 0) {
87                 lock_type = LK_SHARED;
88         }
89         return (lock_type);
90 }
91
92 /*
93  * Atomically drop a lockmgr lock and go to sleep. The lock is reacquired
94  * before returning from this function. Passes on the value returned by
95  * tsleep().
96  */
97 int
98 lock_sleep(void *ident, int flags, const char *wmesg, int timo,
99                 struct lock *lk)
100 {
101         int err, mode;
102
103         mode = lockstatus_owned(lk, curthread);
104         KKASSERT((mode == LK_EXCLUSIVE) || (mode == LK_SHARED));
105
106         crit_enter();
107         tsleep_interlock(ident);
108         lockmgr(lk, LK_RELEASE);
109         err = tsleep(ident, flags, wmesg, timo);
110         crit_exit();
111         lockmgr(lk, mode);
112         return err;
113 }