11ba4a712SPawel Jakub Dawidek /*- 21ba4a712SPawel Jakub Dawidek * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> 31ba4a712SPawel Jakub Dawidek * All rights reserved. 41ba4a712SPawel Jakub Dawidek * 51ba4a712SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 61ba4a712SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 71ba4a712SPawel Jakub Dawidek * are met: 81ba4a712SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 91ba4a712SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 101ba4a712SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 111ba4a712SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 121ba4a712SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 131ba4a712SPawel Jakub Dawidek * 141ba4a712SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 151ba4a712SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161ba4a712SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171ba4a712SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 181ba4a712SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191ba4a712SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201ba4a712SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211ba4a712SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221ba4a712SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231ba4a712SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241ba4a712SPawel Jakub Dawidek * SUCH DAMAGE. 251ba4a712SPawel Jakub Dawidek */ 261ba4a712SPawel Jakub Dawidek 271ba4a712SPawel Jakub Dawidek #include <sys/cdefs.h> 281ba4a712SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 291ba4a712SPawel Jakub Dawidek 301ba4a712SPawel Jakub Dawidek #include <sys/param.h> 311ba4a712SPawel Jakub Dawidek #include <sys/kernel.h> 321ba4a712SPawel Jakub Dawidek #include <sys/systm.h> 331ba4a712SPawel Jakub Dawidek #include <sys/sysctl.h> 341ba4a712SPawel Jakub Dawidek #include <sys/errno.h> 3549939083SJamie Gritton #include <sys/jail.h> 361ba4a712SPawel Jakub Dawidek #include <sys/malloc.h> 371ba4a712SPawel Jakub Dawidek #include <sys/lock.h> 381ba4a712SPawel Jakub Dawidek #include <sys/mutex.h> 3961304249SJamie Gritton #include <sys/rmlock.h> 4061304249SJamie Gritton #include <sys/sx.h> 411ba4a712SPawel Jakub Dawidek #include <sys/queue.h> 421ba4a712SPawel Jakub Dawidek #include <sys/proc.h> 431ba4a712SPawel Jakub Dawidek #include <sys/osd.h> 441ba4a712SPawel Jakub Dawidek 451ba4a712SPawel Jakub Dawidek /* OSD (Object Specific Data) */ 461ba4a712SPawel Jakub Dawidek 471ba4a712SPawel Jakub Dawidek static MALLOC_DEFINE(M_OSD, "osd", "Object Specific Data"); 481ba4a712SPawel Jakub Dawidek 491ba4a712SPawel Jakub Dawidek static int osd_debug = 0; 501ba4a712SPawel Jakub Dawidek TUNABLE_INT("debug.osd", &osd_debug); 511ba4a712SPawel Jakub Dawidek SYSCTL_INT(_debug, OID_AUTO, osd, CTLFLAG_RW, &osd_debug, 0, "OSD debug level"); 521ba4a712SPawel Jakub Dawidek 531ba4a712SPawel Jakub Dawidek #define OSD_DEBUG(...) do { \ 541ba4a712SPawel Jakub Dawidek if (osd_debug) { \ 551ba4a712SPawel Jakub Dawidek printf("OSD (%s:%u): ", __func__, __LINE__); \ 561ba4a712SPawel Jakub Dawidek printf(__VA_ARGS__); \ 571ba4a712SPawel Jakub Dawidek printf("\n"); \ 581ba4a712SPawel Jakub Dawidek } \ 591ba4a712SPawel Jakub Dawidek } while (0) 601ba4a712SPawel Jakub Dawidek 6161304249SJamie Gritton static void do_osd_del(u_int type, struct osd *osd, u_int slot, 6261304249SJamie Gritton int list_locked); 6361304249SJamie Gritton 641ba4a712SPawel Jakub Dawidek /* 651ba4a712SPawel Jakub Dawidek * Lists of objects with OSD. 6661304249SJamie Gritton * 6761304249SJamie Gritton * Lock key: 6861304249SJamie Gritton * (m) osd_module_lock 6961304249SJamie Gritton * (o) osd_object_lock 7061304249SJamie Gritton * (l) osd_list_lock 711ba4a712SPawel Jakub Dawidek */ 7261304249SJamie Gritton static LIST_HEAD(, osd) osd_list[OSD_LAST + 1]; /* (m) */ 7361304249SJamie Gritton static osd_method_t *osd_methods[OSD_LAST + 1]; /* (m) */ 7461304249SJamie Gritton static u_int osd_nslots[OSD_LAST + 1]; /* (m) */ 7561304249SJamie Gritton static osd_destructor_t *osd_destructors[OSD_LAST + 1]; /* (o) */ 76b38ff370SJamie Gritton static const u_int osd_nmethods[OSD_LAST + 1] = { 7749939083SJamie Gritton [OSD_JAIL] = PR_MAXMETHOD, 78b38ff370SJamie Gritton }; 7961304249SJamie Gritton 8061304249SJamie Gritton static struct sx osd_module_lock[OSD_LAST + 1]; 8161304249SJamie Gritton static struct rmlock osd_object_lock[OSD_LAST + 1]; 8261304249SJamie Gritton static struct mtx osd_list_lock[OSD_LAST + 1]; 831ba4a712SPawel Jakub Dawidek 841ba4a712SPawel Jakub Dawidek static void 851ba4a712SPawel Jakub Dawidek osd_default_destructor(void *value __unused) 861ba4a712SPawel Jakub Dawidek { 871ba4a712SPawel Jakub Dawidek /* Do nothing. */ 881ba4a712SPawel Jakub Dawidek } 891ba4a712SPawel Jakub Dawidek 901ba4a712SPawel Jakub Dawidek int 9161304249SJamie Gritton osd_register(u_int type, osd_destructor_t destructor, osd_method_t *methods) 921ba4a712SPawel Jakub Dawidek { 931ba4a712SPawel Jakub Dawidek void *newptr; 9461304249SJamie Gritton u_int i, m; 951ba4a712SPawel Jakub Dawidek 961ba4a712SPawel Jakub Dawidek KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type.")); 971ba4a712SPawel Jakub Dawidek 981ba4a712SPawel Jakub Dawidek /* 991ba4a712SPawel Jakub Dawidek * If no destructor is given, use default one. We need to use some 1001ba4a712SPawel Jakub Dawidek * destructor, because NULL destructor means unused slot. 1011ba4a712SPawel Jakub Dawidek */ 1021ba4a712SPawel Jakub Dawidek if (destructor == NULL) 1031ba4a712SPawel Jakub Dawidek destructor = osd_default_destructor; 1041ba4a712SPawel Jakub Dawidek 10561304249SJamie Gritton sx_xlock(&osd_module_lock[type]); 1061ba4a712SPawel Jakub Dawidek /* 1071ba4a712SPawel Jakub Dawidek * First, we try to find unused slot. 1081ba4a712SPawel Jakub Dawidek */ 1091ba4a712SPawel Jakub Dawidek for (i = 0; i < osd_nslots[type]; i++) { 1101ba4a712SPawel Jakub Dawidek if (osd_destructors[type][i] == NULL) { 1111ba4a712SPawel Jakub Dawidek OSD_DEBUG("Unused slot found (type=%u, slot=%u).", 1121ba4a712SPawel Jakub Dawidek type, i); 1131ba4a712SPawel Jakub Dawidek break; 1141ba4a712SPawel Jakub Dawidek } 1151ba4a712SPawel Jakub Dawidek } 1161ba4a712SPawel Jakub Dawidek /* 1171ba4a712SPawel Jakub Dawidek * If no unused slot was found, allocate one. 1181ba4a712SPawel Jakub Dawidek */ 1191ba4a712SPawel Jakub Dawidek if (i == osd_nslots[type]) { 1201ba4a712SPawel Jakub Dawidek osd_nslots[type]++; 12161304249SJamie Gritton if (osd_nmethods[type] != 0) 12261304249SJamie Gritton osd_methods[type] = realloc(osd_methods[type], 12361304249SJamie Gritton sizeof(osd_method_t) * osd_nslots[type] * 12461304249SJamie Gritton osd_nmethods[type], M_OSD, M_WAITOK); 12561304249SJamie Gritton newptr = malloc(sizeof(osd_destructor_t) * osd_nslots[type], 12661304249SJamie Gritton M_OSD, M_WAITOK); 12761304249SJamie Gritton rm_wlock(&osd_object_lock[type]); 12861304249SJamie Gritton bcopy(osd_destructors[type], newptr, 12961304249SJamie Gritton sizeof(osd_destructor_t) * i); 13061304249SJamie Gritton free(osd_destructors[type], M_OSD); 1311ba4a712SPawel Jakub Dawidek osd_destructors[type] = newptr; 13261304249SJamie Gritton rm_wunlock(&osd_object_lock[type]); 1331ba4a712SPawel Jakub Dawidek OSD_DEBUG("New slot allocated (type=%u, slot=%u).", 1341ba4a712SPawel Jakub Dawidek type, i + 1); 1351ba4a712SPawel Jakub Dawidek } 13661304249SJamie Gritton 1371ba4a712SPawel Jakub Dawidek osd_destructors[type][i] = destructor; 13861304249SJamie Gritton if (osd_nmethods[type] != 0) { 13961304249SJamie Gritton for (m = 0; m < osd_nmethods[type]; m++) 14061304249SJamie Gritton osd_methods[type][i * osd_nmethods[type] + m] = 14161304249SJamie Gritton methods != NULL ? methods[m] : NULL; 14261304249SJamie Gritton } 14361304249SJamie Gritton sx_xunlock(&osd_module_lock[type]); 1441ba4a712SPawel Jakub Dawidek return (i + 1); 1451ba4a712SPawel Jakub Dawidek } 1461ba4a712SPawel Jakub Dawidek 1471ba4a712SPawel Jakub Dawidek void 1481ba4a712SPawel Jakub Dawidek osd_deregister(u_int type, u_int slot) 1491ba4a712SPawel Jakub Dawidek { 1501ba4a712SPawel Jakub Dawidek struct osd *osd, *tosd; 1511ba4a712SPawel Jakub Dawidek 1521ba4a712SPawel Jakub Dawidek KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type.")); 1531ba4a712SPawel Jakub Dawidek KASSERT(slot > 0, ("Invalid slot.")); 1541ba4a712SPawel Jakub Dawidek KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot.")); 1551ba4a712SPawel Jakub Dawidek 15661304249SJamie Gritton sx_xlock(&osd_module_lock[type]); 15761304249SJamie Gritton rm_wlock(&osd_object_lock[type]); 1581ba4a712SPawel Jakub Dawidek /* 1591ba4a712SPawel Jakub Dawidek * Free all OSD for the given slot. 1601ba4a712SPawel Jakub Dawidek */ 16161304249SJamie Gritton mtx_lock(&osd_list_lock[type]); 16261304249SJamie Gritton LIST_FOREACH_SAFE(osd, &osd_list[type], osd_next, tosd) 16361304249SJamie Gritton do_osd_del(type, osd, slot, 1); 16461304249SJamie Gritton mtx_unlock(&osd_list_lock[type]); 1651ba4a712SPawel Jakub Dawidek /* 1661ba4a712SPawel Jakub Dawidek * Set destructor to NULL to free the slot. 1671ba4a712SPawel Jakub Dawidek */ 1681ba4a712SPawel Jakub Dawidek osd_destructors[type][slot - 1] = NULL; 1691ba4a712SPawel Jakub Dawidek if (slot == osd_nslots[type]) { 1701ba4a712SPawel Jakub Dawidek osd_nslots[type]--; 1711ba4a712SPawel Jakub Dawidek osd_destructors[type] = realloc(osd_destructors[type], 1721ba4a712SPawel Jakub Dawidek sizeof(osd_destructor_t) * osd_nslots[type], M_OSD, 1731ba4a712SPawel Jakub Dawidek M_NOWAIT | M_ZERO); 17461304249SJamie Gritton if (osd_nmethods[type] != 0) 17561304249SJamie Gritton osd_methods[type] = realloc(osd_methods[type], 17661304249SJamie Gritton sizeof(osd_method_t) * osd_nslots[type] * 17761304249SJamie Gritton osd_nmethods[type], M_OSD, M_NOWAIT | M_ZERO); 1781ba4a712SPawel Jakub Dawidek /* 1791ba4a712SPawel Jakub Dawidek * We always reallocate to smaller size, so we assume it will 1801ba4a712SPawel Jakub Dawidek * always succeed. 1811ba4a712SPawel Jakub Dawidek */ 18261304249SJamie Gritton KASSERT(osd_destructors[type] != NULL && 18361304249SJamie Gritton (osd_nmethods[type] == 0 || osd_methods[type] != NULL), 18461304249SJamie Gritton ("realloc() failed")); 1851ba4a712SPawel Jakub Dawidek OSD_DEBUG("Deregistration of the last slot (type=%u, slot=%u).", 1861ba4a712SPawel Jakub Dawidek type, slot); 1871ba4a712SPawel Jakub Dawidek } else { 1881ba4a712SPawel Jakub Dawidek OSD_DEBUG("Slot deregistration (type=%u, slot=%u).", 1891ba4a712SPawel Jakub Dawidek type, slot); 1901ba4a712SPawel Jakub Dawidek } 19161304249SJamie Gritton rm_wunlock(&osd_object_lock[type]); 19261304249SJamie Gritton sx_xunlock(&osd_module_lock[type]); 1931ba4a712SPawel Jakub Dawidek } 1941ba4a712SPawel Jakub Dawidek 1951ba4a712SPawel Jakub Dawidek int 1961ba4a712SPawel Jakub Dawidek osd_set(u_int type, struct osd *osd, u_int slot, void *value) 1971ba4a712SPawel Jakub Dawidek { 19861304249SJamie Gritton struct rm_priotracker tracker; 1991ba4a712SPawel Jakub Dawidek 2001ba4a712SPawel Jakub Dawidek KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type.")); 2011ba4a712SPawel Jakub Dawidek KASSERT(slot > 0, ("Invalid slot.")); 2021ba4a712SPawel Jakub Dawidek KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot.")); 2031ba4a712SPawel Jakub Dawidek 20461304249SJamie Gritton rm_rlock(&osd_object_lock[type], &tracker); 20561304249SJamie Gritton if (slot > osd->osd_nslots) { 20661304249SJamie Gritton if (value == NULL) { 20761304249SJamie Gritton OSD_DEBUG( 20861304249SJamie Gritton "Not allocating null slot (type=%u, slot=%u).", 20961304249SJamie Gritton type, slot); 21061304249SJamie Gritton rm_runlock(&osd_object_lock[type], &tracker); 21161304249SJamie Gritton return (0); 21261304249SJamie Gritton } else if (osd->osd_nslots == 0) { 2131ba4a712SPawel Jakub Dawidek /* 21461304249SJamie Gritton * First OSD for this object, so we need to allocate 21561304249SJamie Gritton * space and put it onto the list. 2161ba4a712SPawel Jakub Dawidek */ 2171ba4a712SPawel Jakub Dawidek osd->osd_slots = malloc(sizeof(void *) * slot, M_OSD, 2181ba4a712SPawel Jakub Dawidek M_NOWAIT | M_ZERO); 21961304249SJamie Gritton if (osd->osd_slots == NULL) { 22061304249SJamie Gritton rm_runlock(&osd_object_lock[type], &tracker); 2211ba4a712SPawel Jakub Dawidek return (ENOMEM); 22261304249SJamie Gritton } 2231ba4a712SPawel Jakub Dawidek osd->osd_nslots = slot; 22461304249SJamie Gritton mtx_lock(&osd_list_lock[type]); 2251ba4a712SPawel Jakub Dawidek LIST_INSERT_HEAD(&osd_list[type], osd, osd_next); 22661304249SJamie Gritton mtx_unlock(&osd_list_lock[type]); 2271ba4a712SPawel Jakub Dawidek OSD_DEBUG("Setting first slot (type=%u).", type); 22861304249SJamie Gritton } else { 2291ba4a712SPawel Jakub Dawidek void *newptr; 2301ba4a712SPawel Jakub Dawidek 2311ba4a712SPawel Jakub Dawidek /* 23261304249SJamie Gritton * Too few slots allocated here, needs to extend 23361304249SJamie Gritton * the array. 2341ba4a712SPawel Jakub Dawidek */ 23561304249SJamie Gritton newptr = realloc(osd->osd_slots, sizeof(void *) * slot, 23661304249SJamie Gritton M_OSD, M_NOWAIT | M_ZERO); 23761304249SJamie Gritton if (newptr == NULL) { 23861304249SJamie Gritton rm_runlock(&osd_object_lock[type], &tracker); 2391ba4a712SPawel Jakub Dawidek return (ENOMEM); 24061304249SJamie Gritton } 2411ba4a712SPawel Jakub Dawidek osd->osd_slots = newptr; 2421ba4a712SPawel Jakub Dawidek osd->osd_nslots = slot; 2431ba4a712SPawel Jakub Dawidek OSD_DEBUG("Growing slots array (type=%u).", type); 2441ba4a712SPawel Jakub Dawidek } 24561304249SJamie Gritton } 2461ba4a712SPawel Jakub Dawidek OSD_DEBUG("Setting slot value (type=%u, slot=%u, value=%p).", type, 2471ba4a712SPawel Jakub Dawidek slot, value); 2481ba4a712SPawel Jakub Dawidek osd->osd_slots[slot - 1] = value; 24961304249SJamie Gritton rm_runlock(&osd_object_lock[type], &tracker); 2501ba4a712SPawel Jakub Dawidek return (0); 2511ba4a712SPawel Jakub Dawidek } 2521ba4a712SPawel Jakub Dawidek 2531ba4a712SPawel Jakub Dawidek void * 2541ba4a712SPawel Jakub Dawidek osd_get(u_int type, struct osd *osd, u_int slot) 2551ba4a712SPawel Jakub Dawidek { 25661304249SJamie Gritton struct rm_priotracker tracker; 25761304249SJamie Gritton void *value; 2581ba4a712SPawel Jakub Dawidek 2591ba4a712SPawel Jakub Dawidek KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type.")); 2601ba4a712SPawel Jakub Dawidek KASSERT(slot > 0, ("Invalid slot.")); 2611ba4a712SPawel Jakub Dawidek KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot.")); 2621ba4a712SPawel Jakub Dawidek 26361304249SJamie Gritton rm_rlock(&osd_object_lock[type], &tracker); 2641ba4a712SPawel Jakub Dawidek if (slot > osd->osd_nslots) { 26561304249SJamie Gritton value = NULL; 2661ba4a712SPawel Jakub Dawidek OSD_DEBUG("Slot doesn't exist (type=%u, slot=%u).", type, slot); 26761304249SJamie Gritton } else { 26861304249SJamie Gritton value = osd->osd_slots[slot - 1]; 26961304249SJamie Gritton OSD_DEBUG("Returning slot value (type=%u, slot=%u, value=%p).", 27061304249SJamie Gritton type, slot, value); 2711ba4a712SPawel Jakub Dawidek } 27261304249SJamie Gritton rm_runlock(&osd_object_lock[type], &tracker); 27361304249SJamie Gritton return (value); 2741ba4a712SPawel Jakub Dawidek } 2751ba4a712SPawel Jakub Dawidek 2761ba4a712SPawel Jakub Dawidek void 2771ba4a712SPawel Jakub Dawidek osd_del(u_int type, struct osd *osd, u_int slot) 2781ba4a712SPawel Jakub Dawidek { 27961304249SJamie Gritton struct rm_priotracker tracker; 28061304249SJamie Gritton 28161304249SJamie Gritton rm_rlock(&osd_object_lock[type], &tracker); 28261304249SJamie Gritton do_osd_del(type, osd, slot, 0); 28361304249SJamie Gritton rm_runlock(&osd_object_lock[type], &tracker); 28461304249SJamie Gritton } 28561304249SJamie Gritton 28661304249SJamie Gritton static void 28761304249SJamie Gritton do_osd_del(u_int type, struct osd *osd, u_int slot, int list_locked) 28861304249SJamie Gritton { 2891ba4a712SPawel Jakub Dawidek int i; 2901ba4a712SPawel Jakub Dawidek 2911ba4a712SPawel Jakub Dawidek KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type.")); 2921ba4a712SPawel Jakub Dawidek KASSERT(slot > 0, ("Invalid slot.")); 2931ba4a712SPawel Jakub Dawidek KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot.")); 2941ba4a712SPawel Jakub Dawidek 2951ba4a712SPawel Jakub Dawidek OSD_DEBUG("Deleting slot (type=%u, slot=%u).", type, slot); 2961ba4a712SPawel Jakub Dawidek 2971ba4a712SPawel Jakub Dawidek if (slot > osd->osd_nslots) { 2981ba4a712SPawel Jakub Dawidek OSD_DEBUG("Slot doesn't exist (type=%u, slot=%u).", type, slot); 2991ba4a712SPawel Jakub Dawidek return; 3001ba4a712SPawel Jakub Dawidek } 3013dd4fac9SJamie Gritton if (osd->osd_slots[slot - 1] != NULL) { 3021ba4a712SPawel Jakub Dawidek osd_destructors[type][slot - 1](osd->osd_slots[slot - 1]); 3031ba4a712SPawel Jakub Dawidek osd->osd_slots[slot - 1] = NULL; 3043dd4fac9SJamie Gritton } 3051ba4a712SPawel Jakub Dawidek for (i = osd->osd_nslots - 1; i >= 0; i--) { 3061ba4a712SPawel Jakub Dawidek if (osd->osd_slots[i] != NULL) { 30761304249SJamie Gritton OSD_DEBUG("Slot still has a value (type=%u, slot=%u).", 30861304249SJamie Gritton type, i + 1); 3091ba4a712SPawel Jakub Dawidek break; 3101ba4a712SPawel Jakub Dawidek } 3111ba4a712SPawel Jakub Dawidek } 3121ba4a712SPawel Jakub Dawidek if (i == -1) { 3131ba4a712SPawel Jakub Dawidek /* No values left for this object. */ 3141ba4a712SPawel Jakub Dawidek OSD_DEBUG("No more slots left (type=%u).", type); 31561304249SJamie Gritton if (!list_locked) 31661304249SJamie Gritton mtx_lock(&osd_list_lock[type]); 3171ba4a712SPawel Jakub Dawidek LIST_REMOVE(osd, osd_next); 31861304249SJamie Gritton if (!list_locked) 31961304249SJamie Gritton mtx_unlock(&osd_list_lock[type]); 3201ba4a712SPawel Jakub Dawidek free(osd->osd_slots, M_OSD); 3211ba4a712SPawel Jakub Dawidek osd->osd_slots = NULL; 3221ba4a712SPawel Jakub Dawidek osd->osd_nslots = 0; 3231ba4a712SPawel Jakub Dawidek } else if (slot == osd->osd_nslots) { 3241ba4a712SPawel Jakub Dawidek /* This was the last slot. */ 3251ba4a712SPawel Jakub Dawidek osd->osd_slots = realloc(osd->osd_slots, 3261ba4a712SPawel Jakub Dawidek sizeof(void *) * (i + 1), M_OSD, M_NOWAIT | M_ZERO); 3271ba4a712SPawel Jakub Dawidek /* 3281ba4a712SPawel Jakub Dawidek * We always reallocate to smaller size, so we assume it will 3291ba4a712SPawel Jakub Dawidek * always succeed. 3301ba4a712SPawel Jakub Dawidek */ 3311ba4a712SPawel Jakub Dawidek KASSERT(osd->osd_slots != NULL, ("realloc() failed")); 3321ba4a712SPawel Jakub Dawidek osd->osd_nslots = i + 1; 3331ba4a712SPawel Jakub Dawidek OSD_DEBUG("Reducing slots array to %u (type=%u).", 3341ba4a712SPawel Jakub Dawidek osd->osd_nslots, type); 3351ba4a712SPawel Jakub Dawidek } 3361ba4a712SPawel Jakub Dawidek } 3371ba4a712SPawel Jakub Dawidek 33861304249SJamie Gritton int 33961304249SJamie Gritton osd_call(u_int type, u_int method, void *obj, void *data) 34061304249SJamie Gritton { 34161304249SJamie Gritton osd_method_t methodfun; 34261304249SJamie Gritton int error, i; 34361304249SJamie Gritton 34461304249SJamie Gritton KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type.")); 34561304249SJamie Gritton KASSERT(method < osd_nmethods[type], ("Invalid method.")); 34661304249SJamie Gritton 34761304249SJamie Gritton /* 34861304249SJamie Gritton * Call this method for every slot that defines it, stopping if an 34961304249SJamie Gritton * error is encountered. 35061304249SJamie Gritton */ 35161304249SJamie Gritton error = 0; 35261304249SJamie Gritton sx_slock(&osd_module_lock[type]); 353b38ff370SJamie Gritton for (i = 0; i < osd_nslots[type]; i++) { 35461304249SJamie Gritton methodfun = 355b38ff370SJamie Gritton osd_methods[type][i * osd_nmethods[type] + method]; 35661304249SJamie Gritton if (methodfun != NULL && (error = methodfun(obj, data)) != 0) 35761304249SJamie Gritton break; 35861304249SJamie Gritton } 35961304249SJamie Gritton sx_sunlock(&osd_module_lock[type]); 36061304249SJamie Gritton return (error); 36161304249SJamie Gritton } 36261304249SJamie Gritton 3631ba4a712SPawel Jakub Dawidek void 3641ba4a712SPawel Jakub Dawidek osd_exit(u_int type, struct osd *osd) 3651ba4a712SPawel Jakub Dawidek { 36661304249SJamie Gritton struct rm_priotracker tracker; 3671ba4a712SPawel Jakub Dawidek u_int i; 3681ba4a712SPawel Jakub Dawidek 3691ba4a712SPawel Jakub Dawidek KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type.")); 3701ba4a712SPawel Jakub Dawidek 3711ba4a712SPawel Jakub Dawidek if (osd->osd_nslots == 0) { 3721ba4a712SPawel Jakub Dawidek KASSERT(osd->osd_slots == NULL, ("Non-null osd_slots.")); 3731ba4a712SPawel Jakub Dawidek /* No OSD attached, just leave. */ 3741ba4a712SPawel Jakub Dawidek return; 3751ba4a712SPawel Jakub Dawidek } 3761ba4a712SPawel Jakub Dawidek 37761304249SJamie Gritton rm_rlock(&osd_object_lock[type], &tracker); 37861304249SJamie Gritton for (i = 1; i <= osd->osd_nslots; i++) { 37961304249SJamie Gritton if (osd_destructors[type][i - 1] != NULL) 38061304249SJamie Gritton do_osd_del(type, osd, i, 0); 38161304249SJamie Gritton else 38261304249SJamie Gritton OSD_DEBUG("Unused slot (type=%u, slot=%u).", type, i); 38361304249SJamie Gritton } 38461304249SJamie Gritton rm_runlock(&osd_object_lock[type], &tracker); 3851ba4a712SPawel Jakub Dawidek OSD_DEBUG("Object exit (type=%u).", type); 3861ba4a712SPawel Jakub Dawidek } 3871ba4a712SPawel Jakub Dawidek 3881ba4a712SPawel Jakub Dawidek static void 3891ba4a712SPawel Jakub Dawidek osd_init(void *arg __unused) 3901ba4a712SPawel Jakub Dawidek { 3911ba4a712SPawel Jakub Dawidek u_int i; 3921ba4a712SPawel Jakub Dawidek 3931ba4a712SPawel Jakub Dawidek for (i = OSD_FIRST; i <= OSD_LAST; i++) { 3941ba4a712SPawel Jakub Dawidek osd_nslots[i] = 0; 3951ba4a712SPawel Jakub Dawidek LIST_INIT(&osd_list[i]); 39661304249SJamie Gritton sx_init(&osd_module_lock[i], "osd_module"); 39761304249SJamie Gritton rm_init(&osd_object_lock[i], "osd_object", 0); 39861304249SJamie Gritton mtx_init(&osd_list_lock[i], "osd_list", NULL, MTX_DEF); 3991ba4a712SPawel Jakub Dawidek osd_destructors[i] = NULL; 40061304249SJamie Gritton osd_methods[i] = NULL; 4011ba4a712SPawel Jakub Dawidek } 4021ba4a712SPawel Jakub Dawidek } 4031ba4a712SPawel Jakub Dawidek SYSINIT(osd, SI_SUB_LOCK, SI_ORDER_ANY, osd_init, NULL); 404