27 #include <sys/cdefs.h>
30 #include <sys/param.h>
31 #include <sys/kernel.h>
32 #include <sys/systm.h>
33 #include <sys/sysctl.h>
34 #include <sys/errno.h>
36 #include <sys/malloc.h>
38 #include <sys/mutex.h>
39 #include <sys/rmlock.h>
41 #include <sys/queue.h>
53 #define OSD_DEBUG(...) do { \
55 printf("OSD (%s:%u): ", __func__, __LINE__); \
56 printf(__VA_ARGS__); \
73 static osd_method_t *osd_methods[OSD_LAST + 1];
74 static u_int osd_nslots[OSD_LAST + 1];
75 static osd_destructor_t *osd_destructors[OSD_LAST + 1];
76 static const u_int osd_nmethods[OSD_LAST + 1] = {
77 [OSD_JAIL] = PR_MAXMETHOD,
96 KASSERT(type >= OSD_FIRST && type <= OSD_LAST, (
"Invalid type."));
102 if (destructor == NULL)
109 for (i = 0; i < osd_nslots[
type]; i++) {
110 if (osd_destructors[type][i] == NULL) {
111 OSD_DEBUG(
"Unused slot found (type=%u, slot=%u).",
119 if (i == osd_nslots[type]) {
121 if (osd_nmethods[type] != 0)
123 sizeof(osd_method_t) * osd_nslots[type] *
124 osd_nmethods[type], M_OSD, M_WAITOK);
125 newptr =
malloc(
sizeof(osd_destructor_t) * osd_nslots[type],
128 bcopy(osd_destructors[type], newptr,
129 sizeof(osd_destructor_t) * i);
130 free(osd_destructors[type], M_OSD);
131 osd_destructors[
type] = newptr;
133 OSD_DEBUG(
"New slot allocated (type=%u, slot=%u).",
137 osd_destructors[
type][i] = destructor;
138 if (osd_nmethods[type] != 0) {
139 for (m = 0; m < osd_nmethods[
type]; m++)
140 osd_methods[type][i * osd_nmethods[type] + m] =
141 methods != NULL ? methods[m] : NULL;
150 struct osd *osd, *tosd;
152 KASSERT(type >= OSD_FIRST && type <= OSD_LAST, (
"Invalid type."));
153 KASSERT(slot > 0, (
"Invalid slot."));
154 KASSERT(osd_destructors[type][slot - 1] != NULL, (
"Unused slot."));
162 LIST_FOREACH_SAFE(osd, &osd_list[type], osd_next, tosd)
168 osd_destructors[
type][slot - 1] = NULL;
169 if (slot == osd_nslots[type]) {
171 osd_destructors[
type] =
realloc(osd_destructors[type],
172 sizeof(osd_destructor_t) * osd_nslots[type], M_OSD,
174 if (osd_nmethods[type] != 0)
176 sizeof(osd_method_t) * osd_nslots[type] *
177 osd_nmethods[type], M_OSD, M_NOWAIT | M_ZERO);
182 KASSERT(osd_destructors[type] != NULL &&
183 (osd_nmethods[type] == 0 || osd_methods[type] != NULL),
184 (
"realloc() failed"));
185 OSD_DEBUG(
"Deregistration of the last slot (type=%u, slot=%u).",
188 OSD_DEBUG(
"Slot deregistration (type=%u, slot=%u).",
198 struct rm_priotracker tracker;
200 KASSERT(type >= OSD_FIRST && type <= OSD_LAST, (
"Invalid type."));
201 KASSERT(slot > 0, (
"Invalid slot."));
202 KASSERT(osd_destructors[type][slot - 1] != NULL, (
"Unused slot."));
205 if (slot > osd->osd_nslots) {
208 "Not allocating null slot (type=%u, slot=%u).",
212 }
else if (osd->osd_nslots == 0) {
217 osd->osd_slots =
malloc(
sizeof(
void *) * slot, M_OSD,
219 if (osd->osd_slots == NULL) {
223 osd->osd_nslots = slot;
225 LIST_INSERT_HEAD(&osd_list[type], osd, osd_next);
227 OSD_DEBUG(
"Setting first slot (type=%u).", type);
235 newptr =
realloc(osd->osd_slots,
sizeof(
void *) * slot,
236 M_OSD, M_NOWAIT | M_ZERO);
237 if (newptr == NULL) {
241 osd->osd_slots = newptr;
242 osd->osd_nslots = slot;
243 OSD_DEBUG(
"Growing slots array (type=%u).", type);
246 OSD_DEBUG(
"Setting slot value (type=%u, slot=%u, value=%p).", type,
248 osd->osd_slots[slot - 1] =
value;
256 struct rm_priotracker tracker;
259 KASSERT(type >= OSD_FIRST && type <= OSD_LAST, (
"Invalid type."));
260 KASSERT(slot > 0, (
"Invalid slot."));
261 KASSERT(osd_destructors[type][slot - 1] != NULL, (
"Unused slot."));
264 if (slot > osd->osd_nslots) {
266 OSD_DEBUG(
"Slot doesn't exist (type=%u, slot=%u).", type, slot);
268 value = osd->osd_slots[slot - 1];
269 OSD_DEBUG(
"Returning slot value (type=%u, slot=%u, value=%p).",
279 struct rm_priotracker tracker;
291 KASSERT(type >= OSD_FIRST && type <= OSD_LAST, (
"Invalid type."));
292 KASSERT(slot > 0, (
"Invalid slot."));
293 KASSERT(osd_destructors[type][slot - 1] != NULL, (
"Unused slot."));
295 OSD_DEBUG(
"Deleting slot (type=%u, slot=%u).", type, slot);
297 if (slot > osd->osd_nslots) {
298 OSD_DEBUG(
"Slot doesn't exist (type=%u, slot=%u).", type, slot);
301 if (osd->osd_slots[slot - 1] != NULL) {
302 osd_destructors[
type][slot - 1](osd->osd_slots[slot - 1]);
303 osd->osd_slots[slot - 1] = NULL;
305 for (i = osd->osd_nslots - 1; i >= 0; i--) {
306 if (osd->osd_slots[i] != NULL) {
307 OSD_DEBUG(
"Slot still has a value (type=%u, slot=%u).",
314 OSD_DEBUG(
"No more slots left (type=%u).", type);
317 LIST_REMOVE(osd, osd_next);
320 free(osd->osd_slots, M_OSD);
321 osd->osd_slots = NULL;
323 }
else if (slot == osd->osd_nslots) {
325 osd->osd_slots =
realloc(osd->osd_slots,
326 sizeof(
void *) * (i + 1), M_OSD, M_NOWAIT | M_ZERO);
331 KASSERT(osd->osd_slots != NULL, (
"realloc() failed"));
332 osd->osd_nslots = i + 1;
333 OSD_DEBUG(
"Reducing slots array to %u (type=%u).",
334 osd->osd_nslots, type);
341 osd_method_t methodfun;
344 KASSERT(type >= OSD_FIRST && type <= OSD_LAST, (
"Invalid type."));
345 KASSERT(method < osd_nmethods[type], (
"Invalid method."));
353 for (i = 0; i < osd_nslots[
type]; i++) {
355 osd_methods[
type][i * osd_nmethods[
type] + method];
356 if (methodfun != NULL && (error = methodfun(obj, data)) != 0)
366 struct rm_priotracker tracker;
369 KASSERT(type >= OSD_FIRST && type <= OSD_LAST, (
"Invalid type."));
371 if (osd->osd_nslots == 0) {
372 KASSERT(osd->osd_slots == NULL, (
"Non-null osd_slots."));
378 for (i = 1; i <= osd->osd_nslots; i++) {
379 if (osd_destructors[type][i - 1] != NULL)
382 OSD_DEBUG(
"Unused slot (type=%u, slot=%u).", type, i);
385 OSD_DEBUG(
"Object exit (type=%u).", type);
393 for (i = OSD_FIRST; i <= OSD_LAST; i++) {
395 LIST_INIT(&osd_list[i]);
399 osd_destructors[i] = NULL;
400 osd_methods[i] = NULL;
static struct mtx osd_list_lock[OSD_LAST+1]
static void osd_default_destructor(void *value __unused)
void * realloc(void *addr, unsigned long size, struct malloc_type *mtp, int flags)
static MALLOC_DEFINE(M_OSD,"osd","Object Specific Data")
static void osd_init(void *arg __unused)
int osd_call(u_int type, u_int method, void *obj, void *data)
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
SYSINIT(osd, SI_SUB_LOCK, SI_ORDER_ANY, osd_init, NULL)
void osd_deregister(u_int type, u_int slot)
SYSCTL_INT(_debug, OID_AUTO, osd, CTLFLAG_RW,&osd_debug, 0,"OSD debug level")
static struct sx osd_module_lock[OSD_LAST+1]
static void do_osd_del(u_int type, struct osd *osd, u_int slot, int list_locked)
void * osd_get(u_int type, struct osd *osd, u_int slot)
void rm_init(struct rmlock *rm, const char *name)
int osd_set(u_int type, struct osd *osd, u_int slot, void *value)
void free(void *addr, struct malloc_type *mtp)
int osd_register(u_int type, osd_destructor_t destructor, osd_method_t *methods)
void mtx_init(struct mtx *m, const char *name, const char *type, int opts)
TUNABLE_INT("debug.osd",&osd_debug)
static struct rmlock osd_object_lock[OSD_LAST+1]
void osd_del(u_int type, struct osd *osd, u_int slot)
void osd_exit(u_int type, struct osd *osd)