17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5d3d50737SRafael Vanoni * Common Development and Distribution License (the "License"). 6d3d50737SRafael Vanoni * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*07d06da5SSurya Prakki 227c478bd9Sstevel@tonic-gate /* 23d3d50737SRafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * Inter-Domain Network 277c478bd9Sstevel@tonic-gate * 287c478bd9Sstevel@tonic-gate * Shared Memory Region (SMR) supporting code. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <sys/types.h> 327c478bd9Sstevel@tonic-gate #include <sys/param.h> 337c478bd9Sstevel@tonic-gate #include <sys/machparam.h> 347c478bd9Sstevel@tonic-gate #include <sys/debug.h> 357c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 367c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 377c478bd9Sstevel@tonic-gate #include <sys/mutex.h> 387c478bd9Sstevel@tonic-gate #include <sys/rwlock.h> 397c478bd9Sstevel@tonic-gate #include <sys/systm.h> 407c478bd9Sstevel@tonic-gate #include <sys/machlock.h> 417c478bd9Sstevel@tonic-gate #include <sys/membar.h> 427c478bd9Sstevel@tonic-gate #include <sys/mman.h> 437c478bd9Sstevel@tonic-gate #include <vm/hat.h> 447c478bd9Sstevel@tonic-gate #include <vm/as.h> 457c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 467c478bd9Sstevel@tonic-gate #include <sys/vm_machparam.h> 477c478bd9Sstevel@tonic-gate #include <sys/x_call.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #include <sys/idn.h> 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #ifdef DEBUG 527c478bd9Sstevel@tonic-gate #define DIOCHECK(domid) \ 537c478bd9Sstevel@tonic-gate { \ 547c478bd9Sstevel@tonic-gate int _dio; \ 557c478bd9Sstevel@tonic-gate if ((_dio = idn_domain[domid].dio) < 0) { \ 567c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, \ 577c478bd9Sstevel@tonic-gate ">>>>> file %s, line %d: domain %d, dio = %d", \ 587c478bd9Sstevel@tonic-gate __FILE__, __LINE__, (domid), _dio); \ 597c478bd9Sstevel@tonic-gate } \ 607c478bd9Sstevel@tonic-gate } 617c478bd9Sstevel@tonic-gate #else 627c478bd9Sstevel@tonic-gate #define DIOCHECK(domid) 637c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static int smr_slab_alloc_local(int domid, smr_slab_t **spp); 667c478bd9Sstevel@tonic-gate static int smr_slab_alloc_remote(int domid, smr_slab_t **spp); 677c478bd9Sstevel@tonic-gate static void smr_slab_free_local(int domid, smr_slab_t *sp); 687c478bd9Sstevel@tonic-gate static void smr_slab_free_remote(int domid, smr_slab_t *sp); 697c478bd9Sstevel@tonic-gate static int smr_slabwaiter_register(int domid); 707c478bd9Sstevel@tonic-gate static int smr_slabwaiter_unregister(int domid, smr_slab_t **spp); 717c478bd9Sstevel@tonic-gate static int smr_slaballoc_wait(int domid, smr_slab_t **spp); 727c478bd9Sstevel@tonic-gate static smr_slab_t *smr_slab_reserve(int domid); 737c478bd9Sstevel@tonic-gate static void smr_slab_unreserve(int domid, smr_slab_t *sp); 747c478bd9Sstevel@tonic-gate static void smr_slab_reap_global(); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* 777c478bd9Sstevel@tonic-gate * Can only be called by the master. Allocate a slab from the 787c478bd9Sstevel@tonic-gate * local pool representing the SMR, on behalf of the given 797c478bd9Sstevel@tonic-gate * domain. Slab is either being requested for use by the 807c478bd9Sstevel@tonic-gate * local domain (i.e. domid == idn.localid), or it's being 817c478bd9Sstevel@tonic-gate * allocated to give to a remote domain which requested one. 827c478bd9Sstevel@tonic-gate * In the base of allocating on behalf of a remote domain, 837c478bd9Sstevel@tonic-gate * smr_slab_t structure is used simply to manage ownership. 847c478bd9Sstevel@tonic-gate * 857c478bd9Sstevel@tonic-gate * Returns: smr_slaballoc_wait 867c478bd9Sstevel@tonic-gate * (EINVAL, ETIMEDOUT) 877c478bd9Sstevel@tonic-gate * smr_slabwatier_unregister 887c478bd9Sstevel@tonic-gate * (0, EINVAL, EBUSY, ENOMEM) 897c478bd9Sstevel@tonic-gate * ENOLCK 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate static int 927c478bd9Sstevel@tonic-gate smr_slab_alloc_local(int domid, smr_slab_t **spp) 937c478bd9Sstevel@tonic-gate { 947c478bd9Sstevel@tonic-gate int serrno = 0; 957c478bd9Sstevel@tonic-gate int nwait; 967c478bd9Sstevel@tonic-gate smr_slab_t *sp; 977c478bd9Sstevel@tonic-gate idn_domain_t *dp; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * Only the master can make local allocations. 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); 1047c478bd9Sstevel@tonic-gate ASSERT(idn.localid == IDN_GET_MASTERID()); 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate *spp = NULL; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate dp = &idn_domain[domid]; 1097c478bd9Sstevel@tonic-gate ASSERT(DSLAB_READ_HELD(domid)); 1107c478bd9Sstevel@tonic-gate ASSERT(dp->dslab_state == DSLAB_STATE_LOCAL); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* 1137c478bd9Sstevel@tonic-gate * Register myself with the waiting list. 1147c478bd9Sstevel@tonic-gate */ 1157c478bd9Sstevel@tonic-gate nwait = smr_slabwaiter_register(domid); 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate if (nwait > 1) { 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * XXX - old comment? 1207c478bd9Sstevel@tonic-gate * Need to drop the read lock _after_ registering 1217c478bd9Sstevel@tonic-gate * ourselves with the potential wait list for this allocation. 1227c478bd9Sstevel@tonic-gate * Although this allocation is not a remote one, we could 1237c478bd9Sstevel@tonic-gate * still have multiple threads on the master trying to 1247c478bd9Sstevel@tonic-gate * satisfy (allocate) request on behalf of a remote domain. 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * Somebody is already in the process of satisfying 1287c478bd9Sstevel@tonic-gate * the allocation request for this respective 1297c478bd9Sstevel@tonic-gate * domain. All we need to do is wait and let 1307c478bd9Sstevel@tonic-gate * it happen. 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate serrno = smr_slaballoc_wait(domid, spp); 1337c478bd9Sstevel@tonic-gate return (serrno); 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * I'm the original slab requester for this domain. It's local 1377c478bd9Sstevel@tonic-gate * so go ahead and do the job. 1387c478bd9Sstevel@tonic-gate */ 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate if ((sp = smr_slab_reserve(domid)) == NULL) 1417c478bd9Sstevel@tonic-gate serrno = ENOMEM; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * Allocation may have failed. In either case we've 1457c478bd9Sstevel@tonic-gate * got to do the put to at least wake potential waiters up. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate if (!serrno) { 1487c478bd9Sstevel@tonic-gate if (DSLAB_LOCK_TRYUPGRADE(domid) == 0) { 1497c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(domid); 1507c478bd9Sstevel@tonic-gate DSLAB_LOCK_EXCL(domid); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate (void) smr_slaballoc_put(domid, sp, 0, serrno); 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * If serrno is ENOLCK here, then we must have failed 1587c478bd9Sstevel@tonic-gate * on the upgrade above, so lock already dropped. 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate if (serrno != ENOLCK) { 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Need to drop since reaping may be recursive? 1637c478bd9Sstevel@tonic-gate */ 1647c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(domid); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * Since we were the original requester but never went 1697c478bd9Sstevel@tonic-gate * to sleep, we need to directly unregister ourselves 1707c478bd9Sstevel@tonic-gate * from the waiting list. 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate serrno = smr_slabwaiter_unregister(domid, spp); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* 1757c478bd9Sstevel@tonic-gate * Now that we've satisfied the request, let's check if any 1767c478bd9Sstevel@tonic-gate * reaping is necessary. Only the master does this and only 1777c478bd9Sstevel@tonic-gate * when allocating slabs, an infrequent event :-o 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate smr_slab_reap_global(); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate ASSERT((serrno == 0) ? (*spp != NULL) : (*spp == NULL)); 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate DSLAB_LOCK_SHARED(domid); 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate return (serrno); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * Can only be called by a slave on behalf of himself. Need to 1907c478bd9Sstevel@tonic-gate * make a request to the master to allocate a slab of SMR buffers 1917c478bd9Sstevel@tonic-gate * for the local domain. 1927c478bd9Sstevel@tonic-gate * 1937c478bd9Sstevel@tonic-gate * Returns: smr_slaballoc_wait 1947c478bd9Sstevel@tonic-gate * (0, EINVAL, EBUSY, ENOMEM) 1957c478bd9Sstevel@tonic-gate * ENOLCK 1967c478bd9Sstevel@tonic-gate * ECANCELED 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate static int 1997c478bd9Sstevel@tonic-gate smr_slab_alloc_remote(int domid, smr_slab_t **spp) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate int nwait; 2027c478bd9Sstevel@tonic-gate int serrno = 0; 2037c478bd9Sstevel@tonic-gate int bailout = 0; 2047c478bd9Sstevel@tonic-gate int masterid; 2057c478bd9Sstevel@tonic-gate idn_domain_t *dp, *mdp = NULL; 2067c478bd9Sstevel@tonic-gate procname_t proc = "smr_slab_alloc_remote"; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Only slaves make remote allocations. 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate ASSERT(idn.localid != IDN_GET_MASTERID()); 2127c478bd9Sstevel@tonic-gate ASSERT(domid == idn.localid); 2137c478bd9Sstevel@tonic-gate ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate *spp = NULL; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate dp = &idn_domain[domid]; 2187c478bd9Sstevel@tonic-gate ASSERT(DSLAB_READ_HELD(domid)); 2197c478bd9Sstevel@tonic-gate ASSERT(dp->dslab_state == DSLAB_STATE_REMOTE); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate /* 2227c478bd9Sstevel@tonic-gate * Register myself with the slaballoc waiting list. 2237c478bd9Sstevel@tonic-gate * Note that only allow one outstanding allocation 2247c478bd9Sstevel@tonic-gate * request for the given domain. Other callers which 2257c478bd9Sstevel@tonic-gate * detect a slab is needed simply get stuck on the 2267c478bd9Sstevel@tonic-gate * waiting list waiting for the original caller to 2277c478bd9Sstevel@tonic-gate * get the job done. 2287c478bd9Sstevel@tonic-gate * The waiter_register routine will allocate the necessary 2297c478bd9Sstevel@tonic-gate * slab structure which will ultimately be inserted in 2307c478bd9Sstevel@tonic-gate * the domain's slab list via smr_slaballoc_put(). 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate nwait = smr_slabwaiter_register(domid); 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * Make sure we have a connection with the master 2367c478bd9Sstevel@tonic-gate * before we wait around for nothing and send a 2377c478bd9Sstevel@tonic-gate * command off to nowhere. 2387c478bd9Sstevel@tonic-gate * First do a quick (no lock) check for global okayness. 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate if ((idn.state != IDNGS_ONLINE) || 2417c478bd9Sstevel@tonic-gate ((masterid = IDN_GET_MASTERID()) == IDN_NIL_DOMID)) { 2427c478bd9Sstevel@tonic-gate bailout = 1; 2437c478bd9Sstevel@tonic-gate serrno = ECANCELED; 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * We need to drop our read lock _before_ acquiring the 2477c478bd9Sstevel@tonic-gate * slaballoc waiter lock. This is necessary because the 2487c478bd9Sstevel@tonic-gate * thread that receives the slab alloc response and fills 2497c478bd9Sstevel@tonic-gate * in the slab structure will need to grab the domain write 2507c478bd9Sstevel@tonic-gate * lock while holding onto the slaballoc waiter lock. 2517c478bd9Sstevel@tonic-gate * Potentially could deadlock if we didn't drop our domain 2527c478bd9Sstevel@tonic-gate * lock before. Plus, we've registered. 2537c478bd9Sstevel@tonic-gate * 2547c478bd9Sstevel@tonic-gate * 4093209 - Note also that we do this _after_ the check for 2557c478bd9Sstevel@tonic-gate * idn.masterid where we grab the READER global 2567c478bd9Sstevel@tonic-gate * lock. This is to prevent somebody from 2577c478bd9Sstevel@tonic-gate * changing our state after we drop the drwlock. 2587c478bd9Sstevel@tonic-gate * A deadlock can occur when shutting down a 2597c478bd9Sstevel@tonic-gate * domain we're holding the 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate if (!bailout) { 2637c478bd9Sstevel@tonic-gate mdp = &idn_domain[masterid]; 2647c478bd9Sstevel@tonic-gate /* 2657c478bd9Sstevel@tonic-gate * Global state is okay. Let's double check the 2667c478bd9Sstevel@tonic-gate * state of our actual target domain. 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate if (mdp->dstate != IDNDS_CONNECTED) { 2697c478bd9Sstevel@tonic-gate bailout = 1; 2707c478bd9Sstevel@tonic-gate serrno = ECANCELED; 2717c478bd9Sstevel@tonic-gate } else if (IDN_DLOCK_TRY_SHARED(masterid)) { 2727c478bd9Sstevel@tonic-gate if (mdp->dstate != IDNDS_CONNECTED) { 2737c478bd9Sstevel@tonic-gate bailout = 1; 2747c478bd9Sstevel@tonic-gate serrno = ECANCELED; 2757c478bd9Sstevel@tonic-gate IDN_DUNLOCK(masterid); 2767c478bd9Sstevel@tonic-gate } else if (nwait != 1) { 2777c478bd9Sstevel@tonic-gate IDN_DUNLOCK(masterid); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * Note that keep the drwlock(read) for 2817c478bd9Sstevel@tonic-gate * the target (master) domain if it appears 2827c478bd9Sstevel@tonic-gate * we're the lucky one to send the command. 2837c478bd9Sstevel@tonic-gate * We hold onto the lock until we've actually 2847c478bd9Sstevel@tonic-gate * sent the command out. 2857c478bd9Sstevel@tonic-gate * We don't reach this place unless it 2867c478bd9Sstevel@tonic-gate * appears everything is kosher with 2877c478bd9Sstevel@tonic-gate * the target (master) domain. 2887c478bd9Sstevel@tonic-gate */ 2897c478bd9Sstevel@tonic-gate } else { 2907c478bd9Sstevel@tonic-gate bailout = 1; 2917c478bd9Sstevel@tonic-gate serrno = ENOLCK; 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate if (bailout) { 2967c478bd9Sstevel@tonic-gate ASSERT(serrno); 2977c478bd9Sstevel@tonic-gate /* 2987c478bd9Sstevel@tonic-gate * Gotta bail. Abort operation. Error result 2997c478bd9Sstevel@tonic-gate * will be picked up when we attempt to wait. 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate PR_SMR("%s: BAILING OUT on behalf domain %d " 3027c478bd9Sstevel@tonic-gate "(err=%d, gs=%s, ms=%s)\n", 3037c478bd9Sstevel@tonic-gate proc, domid, serrno, idngs_str[idn.state], 3047c478bd9Sstevel@tonic-gate (masterid == IDN_NIL_DOMID) 3057c478bd9Sstevel@tonic-gate ? "unknown" : idnds_str[idn_domain[masterid].dstate]); 3067c478bd9Sstevel@tonic-gate (void) smr_slabwaiter_abort(domid, serrno); 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate } else if (nwait == 1) { 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * We are the original requester. Initiate the 3117c478bd9Sstevel@tonic-gate * actual request to the master. 3127c478bd9Sstevel@tonic-gate */ 313d3d50737SRafael Vanoni idn_send_cmd(masterid, IDNCMD_SLABALLOC, IDN_SLAB_SIZE, 0, 0); 3147c478bd9Sstevel@tonic-gate ASSERT(mdp); 3157c478bd9Sstevel@tonic-gate IDN_DUNLOCK(masterid); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate /* 3197c478bd9Sstevel@tonic-gate * Wait here for response. Once awakened func returns 3207c478bd9Sstevel@tonic-gate * with slab structure possibly filled with gifts! 3217c478bd9Sstevel@tonic-gate */ 3227c478bd9Sstevel@tonic-gate serrno = smr_slaballoc_wait(domid, spp); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate return (serrno); 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate /* 3287c478bd9Sstevel@tonic-gate * Allocate a slab from the Master on behalf 3297c478bd9Sstevel@tonic-gate * of the given domain. Note that master uses 3307c478bd9Sstevel@tonic-gate * this function to allocate slabs on behalf of 3317c478bd9Sstevel@tonic-gate * remote domains also. 3327c478bd9Sstevel@tonic-gate * Entered with drwlock held. 3337c478bd9Sstevel@tonic-gate * Leaves with drwlock dropped. 3347c478bd9Sstevel@tonic-gate * Returns: EDQUOT 3357c478bd9Sstevel@tonic-gate * EINVAL 3367c478bd9Sstevel@tonic-gate * ENOLCK 3377c478bd9Sstevel@tonic-gate * smr_slab_alloc_local 3387c478bd9Sstevel@tonic-gate * smr_slab_alloc_remote 3397c478bd9Sstevel@tonic-gate * (0, EINVAL, EBUSY, ENOMEM) 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate int 3427c478bd9Sstevel@tonic-gate smr_slab_alloc(int domid, smr_slab_t **spp) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate int serrno = 0; 3457c478bd9Sstevel@tonic-gate idn_domain_t *dp; 3467c478bd9Sstevel@tonic-gate procname_t proc = "smr_slab_alloc"; 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate dp = &idn_domain[domid]; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate ASSERT(DSLAB_READ_HELD(domid)); 3527c478bd9Sstevel@tonic-gate ASSERT(dp->dslab_state != DSLAB_STATE_UNKNOWN); 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate *spp = NULL; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate switch (dp->dslab_state) { 3577c478bd9Sstevel@tonic-gate case DSLAB_STATE_UNKNOWN: 3587c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3597c478bd9Sstevel@tonic-gate "IDN: 300: no slab allocations without a master"); 3607c478bd9Sstevel@tonic-gate serrno = EINVAL; 3617c478bd9Sstevel@tonic-gate break; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate case DSLAB_STATE_LOCAL: 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * If I'm the master, then get a slab 3667c478bd9Sstevel@tonic-gate * from the local SMR pool, but only 3677c478bd9Sstevel@tonic-gate * if the number of allocated slabs has 3687c478bd9Sstevel@tonic-gate * not been exceeded. 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate if (((int)dp->dnslabs < IDN_SLAB_MAXPERDOMAIN) || 3717c478bd9Sstevel@tonic-gate !IDN_SLAB_MAXPERDOMAIN) 3727c478bd9Sstevel@tonic-gate serrno = smr_slab_alloc_local(domid, spp); 3737c478bd9Sstevel@tonic-gate else 3747c478bd9Sstevel@tonic-gate serrno = EDQUOT; 3757c478bd9Sstevel@tonic-gate break; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate case DSLAB_STATE_REMOTE: 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * Have to make a remote request. 3807c478bd9Sstevel@tonic-gate * In order to prevent overwhelming the master 3817c478bd9Sstevel@tonic-gate * with a bunch of requests that he won't be able 3827c478bd9Sstevel@tonic-gate * to handle we do a check to see if we're still 3837c478bd9Sstevel@tonic-gate * under quota. Note that the limit is known 3847c478bd9Sstevel@tonic-gate * apriori based on the SMR/NWR size and 3857c478bd9Sstevel@tonic-gate * IDN_SLAB_MINTOTAL. Domains must have the same 3867c478bd9Sstevel@tonic-gate * size SMR/NWR, however they can have different 3877c478bd9Sstevel@tonic-gate * IDN_SLAB_MINTOTAL. Thus a domain could throttle 3887c478bd9Sstevel@tonic-gate * itself however it wishes. 3897c478bd9Sstevel@tonic-gate */ 3907c478bd9Sstevel@tonic-gate if (((int)dp->dnslabs < IDN_SLAB_MAXPERDOMAIN) || 3917c478bd9Sstevel@tonic-gate !IDN_SLAB_MAXPERDOMAIN) 3927c478bd9Sstevel@tonic-gate serrno = smr_slab_alloc_remote(domid, spp); 3937c478bd9Sstevel@tonic-gate else 3947c478bd9Sstevel@tonic-gate serrno = EDQUOT; 3957c478bd9Sstevel@tonic-gate break; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate default: 3987c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3997c478bd9Sstevel@tonic-gate "IDN: 301: (ALLOC) unknown slab state (%d) " 4007c478bd9Sstevel@tonic-gate "for domain %d", dp->dslab_state, domid); 4017c478bd9Sstevel@tonic-gate serrno = EINVAL; 4027c478bd9Sstevel@tonic-gate break; 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate if (*spp == NULL) { 4067c478bd9Sstevel@tonic-gate PR_SMR("%s: failed to allocate %s slab [serrno = %d]\n", 4077c478bd9Sstevel@tonic-gate proc, (idn.localid == IDN_GET_MASTERID()) ? 4087c478bd9Sstevel@tonic-gate "local" : "remote", serrno); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate if (serrno) { 4127c478bd9Sstevel@tonic-gate IDN_GKSTAT_GLOBAL_EVENT(gk_slabfail, gk_slabfail_last); 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate return (serrno); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate static void 4197c478bd9Sstevel@tonic-gate smr_slab_free_local(int domid, smr_slab_t *sp) 4207c478bd9Sstevel@tonic-gate { 4217c478bd9Sstevel@tonic-gate int rv; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* 4247c478bd9Sstevel@tonic-gate * Do a slaballoc_put just in case there may have 4257c478bd9Sstevel@tonic-gate * been waiters for slabs for this respective domain 4267c478bd9Sstevel@tonic-gate * before we unreserve this slab. 4277c478bd9Sstevel@tonic-gate */ 4287c478bd9Sstevel@tonic-gate rv = smr_slaballoc_put(domid, sp, 0, 0); 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate if (rv == -1) { 4317c478bd9Sstevel@tonic-gate /* 4327c478bd9Sstevel@tonic-gate * Put failed. Must not have been any waiters. 4337c478bd9Sstevel@tonic-gate * Go ahead and unreserve the space. 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate smr_slab_unreserve(domid, sp); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate static void 4407c478bd9Sstevel@tonic-gate smr_slab_free_remote(int domid, smr_slab_t *sp) 4417c478bd9Sstevel@tonic-gate { 4427c478bd9Sstevel@tonic-gate smr_offset_t slab_offset; 4437c478bd9Sstevel@tonic-gate int slab_size; 4447c478bd9Sstevel@tonic-gate int rv; 4457c478bd9Sstevel@tonic-gate int masterid; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate ASSERT(domid == idn.localid); 4487c478bd9Sstevel@tonic-gate ASSERT(idn.localid != IDN_GET_MASTERID()); 4497c478bd9Sstevel@tonic-gate ASSERT(DSLAB_WRITE_HELD(domid)); 4507c478bd9Sstevel@tonic-gate ASSERT(idn_domain[domid].dslab_state == DSLAB_STATE_REMOTE); 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate masterid = IDN_GET_MASTERID(); 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate ASSERT(masterid != IDN_NIL_DOMID); 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate slab_offset = IDN_ADDR2OFFSET(sp->sl_start); 4577c478bd9Sstevel@tonic-gate slab_size = (int)(sp->sl_end - sp->sl_start); 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate /* 4607c478bd9Sstevel@tonic-gate * Do a slaballoc_put just in case there may have 4617c478bd9Sstevel@tonic-gate * been waiters for slabs for this domain before 4627c478bd9Sstevel@tonic-gate * returning back to the master. 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate rv = smr_slaballoc_put(domid, sp, 0, 0); 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if ((rv == -1) && (masterid != IDN_NIL_DOMID)) { 4677c478bd9Sstevel@tonic-gate /* 4687c478bd9Sstevel@tonic-gate * Put failed. No waiters so free the local data 4697c478bd9Sstevel@tonic-gate * structure ship the SMR range off to the master. 4707c478bd9Sstevel@tonic-gate */ 4717c478bd9Sstevel@tonic-gate smr_free_buflist(sp); 4727c478bd9Sstevel@tonic-gate FREESTRUCT(sp, smr_slab_t, 1); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate IDN_DLOCK_SHARED(masterid); 475d3d50737SRafael Vanoni idn_send_cmd(masterid, IDNCMD_SLABFREE, slab_offset, slab_size, 476d3d50737SRafael Vanoni 0); 4777c478bd9Sstevel@tonic-gate IDN_DUNLOCK(masterid); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate /* 4827c478bd9Sstevel@tonic-gate * Free up the list of slabs passed 4837c478bd9Sstevel@tonic-gate */ 4847c478bd9Sstevel@tonic-gate void 4857c478bd9Sstevel@tonic-gate smr_slab_free(int domid, smr_slab_t *sp) 4867c478bd9Sstevel@tonic-gate { 4877c478bd9Sstevel@tonic-gate smr_slab_t *nsp = NULL; 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate ASSERT(DSLAB_WRITE_HELD(domid)); 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate if (sp == NULL) 4927c478bd9Sstevel@tonic-gate return; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate switch (idn_domain[domid].dslab_state) { 4977c478bd9Sstevel@tonic-gate case DSLAB_STATE_UNKNOWN: 498d3d50737SRafael Vanoni cmn_err(CE_WARN, "IDN: 302: no slab free without a master"); 4997c478bd9Sstevel@tonic-gate break; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate case DSLAB_STATE_LOCAL: 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * If I'm the master then put the slabs 5047c478bd9Sstevel@tonic-gate * back to the local SMR pool. 5057c478bd9Sstevel@tonic-gate */ 5067c478bd9Sstevel@tonic-gate for (; sp; sp = nsp) { 5077c478bd9Sstevel@tonic-gate nsp = sp->sl_next; 5087c478bd9Sstevel@tonic-gate smr_slab_free_local(domid, sp); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate break; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate case DSLAB_STATE_REMOTE: 5137c478bd9Sstevel@tonic-gate /* 5147c478bd9Sstevel@tonic-gate * If the domid is my own then I'm freeing 5157c478bd9Sstevel@tonic-gate * a slab back to the Master. 5167c478bd9Sstevel@tonic-gate */ 5177c478bd9Sstevel@tonic-gate for (; sp; sp = nsp) { 5187c478bd9Sstevel@tonic-gate nsp = sp->sl_next; 5197c478bd9Sstevel@tonic-gate smr_slab_free_remote(domid, sp); 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate break; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate default: 5247c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 525d3d50737SRafael Vanoni "IDN: 301: (FREE) unknown slab state (%d) for domain %d", 5267c478bd9Sstevel@tonic-gate idn_domain[domid].dslab_state, domid); 5277c478bd9Sstevel@tonic-gate break; 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * Free up the list of slab data structures ONLY. 5337c478bd9Sstevel@tonic-gate * This is called during a fatal shutdown of the master 5347c478bd9Sstevel@tonic-gate * where we need to garbage collect the locally allocated 5357c478bd9Sstevel@tonic-gate * data structures used to manage slabs allocated to the 5367c478bd9Sstevel@tonic-gate * local domain. Should never be called by a master since 5377c478bd9Sstevel@tonic-gate * the master can do a regular smr_slab_free. 5387c478bd9Sstevel@tonic-gate */ 5397c478bd9Sstevel@tonic-gate void 5407c478bd9Sstevel@tonic-gate smr_slab_garbage_collection(smr_slab_t *sp) 5417c478bd9Sstevel@tonic-gate { 5427c478bd9Sstevel@tonic-gate smr_slab_t *nsp; 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate ASSERT(idn_domain[idn.localid].dvote.v.master == 0); 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate if (sp == NULL) 5477c478bd9Sstevel@tonic-gate return; 5487c478bd9Sstevel@tonic-gate /* 5497c478bd9Sstevel@tonic-gate * Since this is only ever called by a slave, 5507c478bd9Sstevel@tonic-gate * the slab structure size always contains a buflist. 5517c478bd9Sstevel@tonic-gate */ 5527c478bd9Sstevel@tonic-gate for (; sp; sp = nsp) { 5537c478bd9Sstevel@tonic-gate nsp = sp->sl_next; 5547c478bd9Sstevel@tonic-gate smr_free_buflist(sp); 5557c478bd9Sstevel@tonic-gate FREESTRUCT(sp, smr_slab_t, 1); 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* 5607c478bd9Sstevel@tonic-gate * Allocate a SMR buffer on behalf of the local domain 5617c478bd9Sstevel@tonic-gate * which is ultimately targeted for the given domain. 5627c478bd9Sstevel@tonic-gate * 5637c478bd9Sstevel@tonic-gate * IMPORTANT: This routine is going to drop the domain rwlock (drwlock) 5647c478bd9Sstevel@tonic-gate * for the domain on whose behalf the request is being 5657c478bd9Sstevel@tonic-gate * made. This routine canNOT block on trying to 5667c478bd9Sstevel@tonic-gate * reacquire the drwlock. If he does block then somebody 5677c478bd9Sstevel@tonic-gate * must have the write lock on the domain which most likely 5687c478bd9Sstevel@tonic-gate * means the domain is going south anyway, so just bail on 5697c478bd9Sstevel@tonic-gate * this buffer. Higher levels will retry if needed. 5707c478bd9Sstevel@tonic-gate * 5717c478bd9Sstevel@tonic-gate * XXX - Support larger than IDN_SMR_BUFSIZE allocations? 5727c478bd9Sstevel@tonic-gate * 5737c478bd9Sstevel@tonic-gate * Returns: A negative return value indicates lock lost on domid. 5747c478bd9Sstevel@tonic-gate * EINVAL, ENOLINK, ENOLCK(internal) 5757c478bd9Sstevel@tonic-gate * smr_slaballoc_wait 5767c478bd9Sstevel@tonic-gate * (EINVAL, ETIMEDOUT) 5777c478bd9Sstevel@tonic-gate * smr_slabwatier_unregister 5787c478bd9Sstevel@tonic-gate * (0, EINVAL, EBUSY, ENOMEM) 5797c478bd9Sstevel@tonic-gate */ 5807c478bd9Sstevel@tonic-gate int 5817c478bd9Sstevel@tonic-gate smr_buf_alloc(int domid, uint_t len, caddr_t *bufpp) 5827c478bd9Sstevel@tonic-gate { 5837c478bd9Sstevel@tonic-gate register idn_domain_t *dp, *ldp; 5847c478bd9Sstevel@tonic-gate smr_slab_t *sp; 5857c478bd9Sstevel@tonic-gate caddr_t bufp = NULL; 5867c478bd9Sstevel@tonic-gate int serrno; 5877c478bd9Sstevel@tonic-gate procname_t proc = "smr_buf_alloc"; 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate dp = &idn_domain[domid]; 5907c478bd9Sstevel@tonic-gate /* 5917c478bd9Sstevel@tonic-gate * Local domain can only allocate on behalf of 5927c478bd9Sstevel@tonic-gate * itself if this is a priviledged call and the 5937c478bd9Sstevel@tonic-gate * caller is the master. 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate ASSERT((domid != idn.localid) && (domid != IDN_NIL_DOMID)); 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate *bufpp = NULL; 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate if (len > IDN_DATA_SIZE) { 6007c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 601bf30efa4Smathue "IDN: 303: buffer len %d > IDN_DATA_SIZE (%lu)", 6027c478bd9Sstevel@tonic-gate len, IDN_DATA_SIZE); 6037c478bd9Sstevel@tonic-gate IDN_GKSTAT_GLOBAL_EVENT(gk_buffail, gk_buffail_last); 6047c478bd9Sstevel@tonic-gate return (EINVAL); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate /* 6087c478bd9Sstevel@tonic-gate * Need to go to my local slab list to find 6097c478bd9Sstevel@tonic-gate * a buffer. 6107c478bd9Sstevel@tonic-gate */ 6117c478bd9Sstevel@tonic-gate ldp = &idn_domain[idn.localid]; 6127c478bd9Sstevel@tonic-gate /* 6137c478bd9Sstevel@tonic-gate * Now we loop trying to locate a buffer out of our 6147c478bd9Sstevel@tonic-gate * slabs. We continue this until either we find a 6157c478bd9Sstevel@tonic-gate * buffer or we're unable to allocate a slab. Note 6167c478bd9Sstevel@tonic-gate * that new slabs are allocated to the front. 6177c478bd9Sstevel@tonic-gate */ 6187c478bd9Sstevel@tonic-gate DSLAB_LOCK_SHARED(idn.localid); 6197c478bd9Sstevel@tonic-gate sp = ldp->dslab; 6207c478bd9Sstevel@tonic-gate do { 6217c478bd9Sstevel@tonic-gate int spl, all_empty; 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate if (sp == NULL) { 6247c478bd9Sstevel@tonic-gate if ((serrno = smr_slab_alloc(idn.localid, &sp)) != 0) { 6257c478bd9Sstevel@tonic-gate PR_SMR("%s:%d: failed to allocate " 6267c478bd9Sstevel@tonic-gate "slab [serrno = %d]", 6277c478bd9Sstevel@tonic-gate proc, domid, serrno); 6287c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(idn.localid); 6297c478bd9Sstevel@tonic-gate IDN_GKSTAT_GLOBAL_EVENT(gk_buffail, 6307c478bd9Sstevel@tonic-gate gk_buffail_last); 6317c478bd9Sstevel@tonic-gate return (serrno); 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate /* 6347c478bd9Sstevel@tonic-gate * Of course, the world may have changed while 6357c478bd9Sstevel@tonic-gate * we dropped the lock. Better make sure we're 6367c478bd9Sstevel@tonic-gate * still established. 6377c478bd9Sstevel@tonic-gate */ 6387c478bd9Sstevel@tonic-gate if (dp->dstate != IDNDS_CONNECTED) { 6397c478bd9Sstevel@tonic-gate PR_SMR("%s:%d: state changed during slab " 6407c478bd9Sstevel@tonic-gate "alloc (dstate = %s)\n", 6417c478bd9Sstevel@tonic-gate proc, domid, idnds_str[dp->dstate]); 6427c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(idn.localid); 6437c478bd9Sstevel@tonic-gate IDN_GKSTAT_GLOBAL_EVENT(gk_buffail, 6447c478bd9Sstevel@tonic-gate gk_buffail_last); 6457c478bd9Sstevel@tonic-gate return (ENOLINK); 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate /* 6487c478bd9Sstevel@tonic-gate * We were able to allocate a slab. Should 6497c478bd9Sstevel@tonic-gate * be at the front of the list, spin again. 6507c478bd9Sstevel@tonic-gate */ 6517c478bd9Sstevel@tonic-gate sp = ldp->dslab; 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate /* 6547c478bd9Sstevel@tonic-gate * If we have reached here then we have a slab! 6557c478bd9Sstevel@tonic-gate * Hopefully there are free bufs there :-o 6567c478bd9Sstevel@tonic-gate */ 6577c478bd9Sstevel@tonic-gate spl = splhi(); 6587c478bd9Sstevel@tonic-gate all_empty = 1; 6597c478bd9Sstevel@tonic-gate for (; sp && !bufp; sp = sp->sl_next) { 6607c478bd9Sstevel@tonic-gate smr_slabbuf_t *bp; 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate if (sp->sl_free == NULL) 6637c478bd9Sstevel@tonic-gate continue; 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate if (!lock_try(&sp->sl_lock)) { 6667c478bd9Sstevel@tonic-gate all_empty = 0; 6677c478bd9Sstevel@tonic-gate continue; 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate if ((bp = sp->sl_free) == NULL) { 6717c478bd9Sstevel@tonic-gate lock_clear(&sp->sl_lock); 6727c478bd9Sstevel@tonic-gate continue; 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate sp->sl_free = bp->sb_next; 6767c478bd9Sstevel@tonic-gate bp->sb_next = sp->sl_inuse; 6777c478bd9Sstevel@tonic-gate sp->sl_inuse = bp; 6787c478bd9Sstevel@tonic-gate /* 6797c478bd9Sstevel@tonic-gate * Found a free buffer. 6807c478bd9Sstevel@tonic-gate */ 6817c478bd9Sstevel@tonic-gate bp->sb_domid = domid; 6827c478bd9Sstevel@tonic-gate bufp = bp->sb_bufp; 6837c478bd9Sstevel@tonic-gate lock_clear(&sp->sl_lock); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate splx(spl); 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate if (!all_empty && !bufp) { 6887c478bd9Sstevel@tonic-gate /* 6897c478bd9Sstevel@tonic-gate * If we still haven't found a buffer, but 6907c478bd9Sstevel@tonic-gate * there's still possibly a buffer available, 6917c478bd9Sstevel@tonic-gate * then try again. Only if we're absolutely 6927c478bd9Sstevel@tonic-gate * sure all slabs are empty do we attempt 6937c478bd9Sstevel@tonic-gate * to allocate a new one. 6947c478bd9Sstevel@tonic-gate */ 6957c478bd9Sstevel@tonic-gate sp = ldp->dslab; 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate } while (bufp == NULL); 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate *bufpp = bufp; 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate ATOMIC_INC(dp->dio); 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(idn.localid); 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate return (0); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate /* 7097c478bd9Sstevel@tonic-gate * Free a buffer allocated to the local domain back to 7107c478bd9Sstevel@tonic-gate * its respective slab. Slabs are freed via the slab-reap command. 7117c478bd9Sstevel@tonic-gate * XXX - Support larger than IDN_SMR_BUFSIZE allocations? 7127c478bd9Sstevel@tonic-gate */ 7137c478bd9Sstevel@tonic-gate int 7147c478bd9Sstevel@tonic-gate smr_buf_free(int domid, caddr_t bufp, uint_t len) 7157c478bd9Sstevel@tonic-gate { 7167c478bd9Sstevel@tonic-gate register smr_slab_t *sp; 7177c478bd9Sstevel@tonic-gate smr_slabbuf_t *bp, **bpp; 7187c478bd9Sstevel@tonic-gate idn_domain_t *ldp; 7197c478bd9Sstevel@tonic-gate int buffreed; 7207c478bd9Sstevel@tonic-gate int lockheld = (len == (uint_t)-1); 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate /* 7237c478bd9Sstevel@tonic-gate * We should never be free'ing a buffer on 7247c478bd9Sstevel@tonic-gate * behalf of ourselves as we are never the 7257c478bd9Sstevel@tonic-gate * target for allocated SMR buffers. 7267c478bd9Sstevel@tonic-gate */ 7277c478bd9Sstevel@tonic-gate ASSERT(domid != idn.localid); 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate sp = NULL; 7307c478bd9Sstevel@tonic-gate buffreed = 0; 7317c478bd9Sstevel@tonic-gate ldp = &idn_domain[idn.localid]; 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate DSLAB_LOCK_SHARED(idn.localid); 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate if (((uintptr_t)bufp & (IDN_SMR_BUFSIZE-1)) && 7367c478bd9Sstevel@tonic-gate (IDN_ADDR2OFFSET(bufp) % IDN_SMR_BUFSIZE)) { 7377c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 738bf30efa4Smathue "IDN: 304: buffer (0x%p) from domain %d not on a " 739*07d06da5SSurya Prakki "%d boundary", (void *)bufp, domid, IDN_SMR_BUFSIZE); 7407c478bd9Sstevel@tonic-gate goto bfdone; 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate if (!lockheld && (len > IDN_DATA_SIZE)) { 7437c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 7447c478bd9Sstevel@tonic-gate "IDN: 305: buffer length (%d) from domain %d greater " 745bf30efa4Smathue "than IDN_DATA_SIZE (%lu)", 7467c478bd9Sstevel@tonic-gate len, domid, IDN_DATA_SIZE); 7477c478bd9Sstevel@tonic-gate goto bfdone; 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate for (sp = ldp->dslab; sp; sp = sp->sl_next) 7517c478bd9Sstevel@tonic-gate if ((bufp >= sp->sl_start) && (bufp < sp->sl_end)) 7527c478bd9Sstevel@tonic-gate break; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate if (sp) { 7557c478bd9Sstevel@tonic-gate int spl; 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate spl = splhi(); 7587c478bd9Sstevel@tonic-gate while (!lock_try(&sp->sl_lock)) 7597c478bd9Sstevel@tonic-gate ; 7607c478bd9Sstevel@tonic-gate bpp = &sp->sl_inuse; 7617c478bd9Sstevel@tonic-gate for (bp = *bpp; bp; bp = *bpp) { 7627c478bd9Sstevel@tonic-gate if (bp->sb_bufp == bufp) 7637c478bd9Sstevel@tonic-gate break; 7647c478bd9Sstevel@tonic-gate bpp = &bp->sb_next; 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate if (bp) { 7677c478bd9Sstevel@tonic-gate ASSERT(bp->sb_domid == domid); 7687c478bd9Sstevel@tonic-gate buffreed++; 7697c478bd9Sstevel@tonic-gate bp->sb_domid = IDN_NIL_DOMID; 7707c478bd9Sstevel@tonic-gate *bpp = bp->sb_next; 7717c478bd9Sstevel@tonic-gate bp->sb_next = sp->sl_free; 7727c478bd9Sstevel@tonic-gate sp->sl_free = bp; 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate lock_clear(&sp->sl_lock); 7757c478bd9Sstevel@tonic-gate splx(spl); 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate bfdone: 7787c478bd9Sstevel@tonic-gate if (buffreed) { 7797c478bd9Sstevel@tonic-gate ATOMIC_DEC(idn_domain[domid].dio); 7807c478bd9Sstevel@tonic-gate DIOCHECK(domid); 7817c478bd9Sstevel@tonic-gate } else { 7827c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 7837c478bd9Sstevel@tonic-gate "IDN: 306: unknown buffer (0x%p) from domain %d", 784*07d06da5SSurya Prakki (void *)bufp, domid); 7857c478bd9Sstevel@tonic-gate ATOMIC_INC(idn_domain[domid].dioerr); 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(idn.localid); 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate return (sp ? 0 : -1); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate /* 7947c478bd9Sstevel@tonic-gate * Alternative interface to smr_buf_free, but with local drwlock 7957c478bd9Sstevel@tonic-gate * held. 7967c478bd9Sstevel@tonic-gate */ 7977c478bd9Sstevel@tonic-gate /* ARGSUSED2 */ 7987c478bd9Sstevel@tonic-gate int 7997c478bd9Sstevel@tonic-gate smr_buf_free_locked(int domid, caddr_t bufp, uint_t len) 8007c478bd9Sstevel@tonic-gate { 8017c478bd9Sstevel@tonic-gate return (smr_buf_free(domid, bufp, (uint_t)-1)); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* 8057c478bd9Sstevel@tonic-gate * Free any and all buffers associated with the given domain. 8067c478bd9Sstevel@tonic-gate * Assumption is that domain is dead and buffers are not in use. 8077c478bd9Sstevel@tonic-gate * Returns: Number of buffers freed. 8087c478bd9Sstevel@tonic-gate * -1 if error. 8097c478bd9Sstevel@tonic-gate */ 8107c478bd9Sstevel@tonic-gate int 8117c478bd9Sstevel@tonic-gate smr_buf_free_all(int domid) 8127c478bd9Sstevel@tonic-gate { 8137c478bd9Sstevel@tonic-gate register smr_slab_t *sp; 8147c478bd9Sstevel@tonic-gate register smr_slabbuf_t *bp, **bpp; 8157c478bd9Sstevel@tonic-gate idn_domain_t *ldp; 8167c478bd9Sstevel@tonic-gate int nbufsfreed = 0; 8177c478bd9Sstevel@tonic-gate procname_t proc = "smr_buf_free_all"; 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate /* 8207c478bd9Sstevel@tonic-gate * We should never be free'ing buffers on 8217c478bd9Sstevel@tonic-gate * behalf of ourself 8227c478bd9Sstevel@tonic-gate */ 8237c478bd9Sstevel@tonic-gate ASSERT(domid != idn.localid); 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate if (!VALID_DOMAINID(domid)) { 826d3d50737SRafael Vanoni cmn_err(CE_WARN, "IDN: 307: domain ID (%d) invalid", domid); 8277c478bd9Sstevel@tonic-gate return (-1); 8287c478bd9Sstevel@tonic-gate } 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate ldp = &idn_domain[idn.localid]; 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate /* 8337c478bd9Sstevel@tonic-gate * We grab the writer lock so that we don't have any 8347c478bd9Sstevel@tonic-gate * competition during a "free-all" call. 8357c478bd9Sstevel@tonic-gate * No need to grab individual slab locks when holding 8367c478bd9Sstevel@tonic-gate * dslab(writer). 8377c478bd9Sstevel@tonic-gate */ 8387c478bd9Sstevel@tonic-gate DSLAB_LOCK_EXCL(idn.localid); 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate for (sp = ldp->dslab; sp; sp = sp->sl_next) { 8417c478bd9Sstevel@tonic-gate bpp = &sp->sl_inuse; 8427c478bd9Sstevel@tonic-gate for (bp = *bpp; bp; bp = *bpp) { 8437c478bd9Sstevel@tonic-gate if (bp->sb_domid == domid) { 8447c478bd9Sstevel@tonic-gate bp->sb_domid = IDN_NIL_DOMID; 8457c478bd9Sstevel@tonic-gate *bpp = bp->sb_next; 8467c478bd9Sstevel@tonic-gate bp->sb_next = sp->sl_free; 8477c478bd9Sstevel@tonic-gate sp->sl_free = bp; 8487c478bd9Sstevel@tonic-gate nbufsfreed++; 8497c478bd9Sstevel@tonic-gate } else { 8507c478bd9Sstevel@tonic-gate bpp = &bp->sb_next; 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate if (nbufsfreed > 0) { 8567c478bd9Sstevel@tonic-gate ATOMIC_SUB(idn_domain[domid].dio, nbufsfreed); 8577c478bd9Sstevel@tonic-gate idn_domain[domid].dioerr = 0; 8587c478bd9Sstevel@tonic-gate DIOCHECK(domid); 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(idn.localid); 8627c478bd9Sstevel@tonic-gate 863d3d50737SRafael Vanoni PR_SMR("%s: freed %d buffers for domain %d\n", proc, nbufsfreed, domid); 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate return (nbufsfreed); 8667c478bd9Sstevel@tonic-gate } 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate int 8697c478bd9Sstevel@tonic-gate smr_buf_reclaim(int domid, int nbufs) 8707c478bd9Sstevel@tonic-gate { 8717c478bd9Sstevel@tonic-gate int num_reclaimed = 0; 8727c478bd9Sstevel@tonic-gate idn_domain_t *ldp, *dp; 8737c478bd9Sstevel@tonic-gate procname_t proc = "smr_buf_reclaim"; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate ldp = &idn_domain[idn.localid]; 8767c478bd9Sstevel@tonic-gate dp = &idn_domain[domid]; 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate ASSERT(domid != idn.localid); 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate if (ATOMIC_CAS(&dp->dreclaim_inprogress, 0, 1)) { 8817c478bd9Sstevel@tonic-gate /* 8827c478bd9Sstevel@tonic-gate * Reclaim is already in progress, don't 8837c478bd9Sstevel@tonic-gate * bother. 8847c478bd9Sstevel@tonic-gate */ 8857c478bd9Sstevel@tonic-gate PR_DATA("%s: reclaim already in progress\n", proc); 8867c478bd9Sstevel@tonic-gate return (0); 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate 889d3d50737SRafael Vanoni PR_SMR("%s: requested %d buffers from domain %d\n", proc, nbufs, domid); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate if (dp->dio && nbufs) { 8927c478bd9Sstevel@tonic-gate register smr_slab_t *sp; 8937c478bd9Sstevel@tonic-gate int spl; 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate DSLAB_LOCK_SHARED(idn.localid); 8967c478bd9Sstevel@tonic-gate spl = splhi(); 8977c478bd9Sstevel@tonic-gate for (sp = ldp->dslab; sp && nbufs; sp = sp->sl_next) { 8987c478bd9Sstevel@tonic-gate register smr_slabbuf_t *bp, **bpp; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate if (sp->sl_inuse == NULL) 9017c478bd9Sstevel@tonic-gate continue; 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate if (!lock_try(&sp->sl_lock)) 9047c478bd9Sstevel@tonic-gate continue; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate if (sp->sl_inuse == NULL) { 9077c478bd9Sstevel@tonic-gate lock_clear(&sp->sl_lock); 9087c478bd9Sstevel@tonic-gate continue; 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate bpp = &sp->sl_inuse; 9127c478bd9Sstevel@tonic-gate for (bp = *bpp; bp && nbufs; bp = *bpp) { 9137c478bd9Sstevel@tonic-gate if (bp->sb_domid == domid) { 9147c478bd9Sstevel@tonic-gate /* 9157c478bd9Sstevel@tonic-gate * Buffer no longer in use, 9167c478bd9Sstevel@tonic-gate * reclaim it. 9177c478bd9Sstevel@tonic-gate */ 9187c478bd9Sstevel@tonic-gate bp->sb_domid = IDN_NIL_DOMID; 9197c478bd9Sstevel@tonic-gate *bpp = bp->sb_next; 9207c478bd9Sstevel@tonic-gate bp->sb_next = sp->sl_free; 9217c478bd9Sstevel@tonic-gate sp->sl_free = bp; 9227c478bd9Sstevel@tonic-gate num_reclaimed++; 9237c478bd9Sstevel@tonic-gate nbufs--; 9247c478bd9Sstevel@tonic-gate } else { 9257c478bd9Sstevel@tonic-gate bpp = &bp->sb_next; 9267c478bd9Sstevel@tonic-gate } 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate lock_clear(&sp->sl_lock); 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate splx(spl); 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate if (num_reclaimed > 0) { 9337c478bd9Sstevel@tonic-gate ATOMIC_SUB(dp->dio, num_reclaimed); 9347c478bd9Sstevel@tonic-gate DIOCHECK(domid); 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(idn.localid); 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate PR_SMR("%s: reclaimed %d buffers from domain %d\n", 9407c478bd9Sstevel@tonic-gate proc, num_reclaimed, domid); 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate return (num_reclaimed); 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate /* 9467c478bd9Sstevel@tonic-gate * Returns 1 If any buffers are locked for the given slab. 9477c478bd9Sstevel@tonic-gate * 0 If all buffers are free for the given slab. 9487c478bd9Sstevel@tonic-gate * 9497c478bd9Sstevel@tonic-gate * The caller is assumed to have the slab protected so that no 9507c478bd9Sstevel@tonic-gate * new allocations are attempted from it. Also, this is only 9517c478bd9Sstevel@tonic-gate * valid to be called with respect to slabs that were allocated 9527c478bd9Sstevel@tonic-gate * on behalf of the local domain, i.e. the master is not expected 9537c478bd9Sstevel@tonic-gate * to call this function with (slave) slab "representatives". 9547c478bd9Sstevel@tonic-gate */ 9557c478bd9Sstevel@tonic-gate int 9567c478bd9Sstevel@tonic-gate smr_slab_busy(smr_slab_t *sp) 9577c478bd9Sstevel@tonic-gate { 9587c478bd9Sstevel@tonic-gate return ((sp && sp->sl_inuse) ? 1 : 0); 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate int 9627c478bd9Sstevel@tonic-gate smr_slabwaiter_init() 9637c478bd9Sstevel@tonic-gate { 9647c478bd9Sstevel@tonic-gate register int i; 9657c478bd9Sstevel@tonic-gate struct slabwaiter *wp; 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate if (idn.slabwaiter != NULL) 9687c478bd9Sstevel@tonic-gate return (0); 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate /* 9717c478bd9Sstevel@tonic-gate * Initialize the slab waiting area for MAX_DOMAINS. 9727c478bd9Sstevel@tonic-gate */ 9737c478bd9Sstevel@tonic-gate idn.slabwaiter = GETSTRUCT(struct slabwaiter, MAX_DOMAINS); 9747c478bd9Sstevel@tonic-gate wp = idn.slabwaiter; 9757c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_DOMAINS; wp++, i++) { 9767c478bd9Sstevel@tonic-gate wp->w_closed = 0; 9777c478bd9Sstevel@tonic-gate mutex_init(&wp->w_mutex, NULL, MUTEX_DEFAULT, NULL); 9787c478bd9Sstevel@tonic-gate cv_init(&wp->w_cv, NULL, CV_DEFAULT, NULL); 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate return (0); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate void 9857c478bd9Sstevel@tonic-gate smr_slabwaiter_deinit() 9867c478bd9Sstevel@tonic-gate { 9877c478bd9Sstevel@tonic-gate register int i; 9887c478bd9Sstevel@tonic-gate struct slabwaiter *wp; 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate if ((wp = idn.slabwaiter) == NULL) 9917c478bd9Sstevel@tonic-gate return; 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_DOMAINS; wp++, i++) { 9947c478bd9Sstevel@tonic-gate ASSERT(wp->w_nwaiters == 0); 9957c478bd9Sstevel@tonic-gate ASSERT(wp->w_sp == NULL); 9967c478bd9Sstevel@tonic-gate cv_destroy(&wp->w_cv); 9977c478bd9Sstevel@tonic-gate mutex_destroy(&wp->w_mutex); 9987c478bd9Sstevel@tonic-gate } 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate FREESTRUCT(idn.slabwaiter, struct slabwaiter, MAX_DOMAINS); 10017c478bd9Sstevel@tonic-gate idn.slabwaiter = NULL; 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate void 10057c478bd9Sstevel@tonic-gate smr_slabwaiter_open(domainset_t domset) 10067c478bd9Sstevel@tonic-gate { 10077c478bd9Sstevel@tonic-gate int d; 10087c478bd9Sstevel@tonic-gate struct slabwaiter *wp; 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate if ((domset == 0) || !idn.slabwaiter) 10117c478bd9Sstevel@tonic-gate return; 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate wp = idn.slabwaiter; 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate for (d = 0; d < MAX_DOMAINS; wp++, d++) { 10167c478bd9Sstevel@tonic-gate if (!DOMAIN_IN_SET(domset, d)) 10177c478bd9Sstevel@tonic-gate continue; 10187c478bd9Sstevel@tonic-gate mutex_enter(&wp->w_mutex); 10197c478bd9Sstevel@tonic-gate wp->w_closed = 0; 10207c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate void 10257c478bd9Sstevel@tonic-gate smr_slabwaiter_close(domainset_t domset) 10267c478bd9Sstevel@tonic-gate { 10277c478bd9Sstevel@tonic-gate int d; 10287c478bd9Sstevel@tonic-gate struct slabwaiter *wp; 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate if ((domset == 0) || !idn.slabwaiter) 10317c478bd9Sstevel@tonic-gate return; 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate wp = idn.slabwaiter; 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate for (d = 0; d < MAX_DOMAINS; wp++, d++) { 10367c478bd9Sstevel@tonic-gate if (!DOMAIN_IN_SET(domset, d)) 10377c478bd9Sstevel@tonic-gate continue; 10387c478bd9Sstevel@tonic-gate mutex_enter(&wp->w_mutex); 10397c478bd9Sstevel@tonic-gate wp->w_closed = 1; 10407c478bd9Sstevel@tonic-gate cv_broadcast(&wp->w_cv); 10417c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate /* 10467c478bd9Sstevel@tonic-gate * Register the caller with the waiting list for the 10477c478bd9Sstevel@tonic-gate * given domain. 10487c478bd9Sstevel@tonic-gate * 10497c478bd9Sstevel@tonic-gate * Protocol: 10507c478bd9Sstevel@tonic-gate * 1st Local requester: register -> alloc -> 10517c478bd9Sstevel@tonic-gate * put(wakeup|xdc) -> unregister 10527c478bd9Sstevel@tonic-gate * Nth Local requester: register -> wait 10537c478bd9Sstevel@tonic-gate * 1st Remote requester: register -> xdc -> wait 10547c478bd9Sstevel@tonic-gate * Nth Remote requester: register -> wait 10557c478bd9Sstevel@tonic-gate * 10567c478bd9Sstevel@tonic-gate * Remote Responder: local alloc -> put(xdc) 10577c478bd9Sstevel@tonic-gate * Local Handler: xdc -> put(wakeup) 10587c478bd9Sstevel@tonic-gate * 10597c478bd9Sstevel@tonic-gate * E.g. A standard slave allocation request: 10607c478bd9Sstevel@tonic-gate * slave master 10617c478bd9Sstevel@tonic-gate * ----- ------ 10627c478bd9Sstevel@tonic-gate * idn_slab_alloc(remote) 10637c478bd9Sstevel@tonic-gate * - register 10647c478bd9Sstevel@tonic-gate * - xdc -> idn_handler 10657c478bd9Sstevel@tonic-gate * - wait ... 10667c478bd9Sstevel@tonic-gate * idn_slab_alloc(local) 10677c478bd9Sstevel@tonic-gate * - register 10687c478bd9Sstevel@tonic-gate * - alloc 10697c478bd9Sstevel@tonic-gate * - put 10707c478bd9Sstevel@tonic-gate * . wakeup [local] 10717c478bd9Sstevel@tonic-gate * - unregister 10727c478bd9Sstevel@tonic-gate * idn_handler <- - xdc 10737c478bd9Sstevel@tonic-gate * - put DONE 10747c478bd9Sstevel@tonic-gate * . wakeup [local] 10757c478bd9Sstevel@tonic-gate * | 10767c478bd9Sstevel@tonic-gate * V 10777c478bd9Sstevel@tonic-gate * - wait 10787c478bd9Sstevel@tonic-gate * . unregister 10797c478bd9Sstevel@tonic-gate * DONE 10807c478bd9Sstevel@tonic-gate */ 10817c478bd9Sstevel@tonic-gate static int 10827c478bd9Sstevel@tonic-gate smr_slabwaiter_register(int domid) 10837c478bd9Sstevel@tonic-gate { 10847c478bd9Sstevel@tonic-gate struct slabwaiter *wp; 10857c478bd9Sstevel@tonic-gate int nwait; 10867c478bd9Sstevel@tonic-gate procname_t proc = "smr_slabwaiter_register"; 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate ASSERT(domid != IDN_NIL_DOMID); 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate ASSERT(DSLAB_READ_HELD(domid)); 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate wp = &idn.slabwaiter[domid]; 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&wp->w_mutex)); 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate mutex_enter(&wp->w_mutex); 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate nwait = ++(wp->w_nwaiters); 11007c478bd9Sstevel@tonic-gate ASSERT(nwait > 0); 11017c478bd9Sstevel@tonic-gate 1102d3d50737SRafael Vanoni PR_SMR("%s: domain = %d, (new)nwaiters = %d\n", proc, domid, nwait); 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate if (nwait > 1) { 11057c478bd9Sstevel@tonic-gate /* 11067c478bd9Sstevel@tonic-gate * There are already waiters for slab allocations 11077c478bd9Sstevel@tonic-gate * with respect to this domain. 11087c478bd9Sstevel@tonic-gate */ 11097c478bd9Sstevel@tonic-gate PR_SMR("%s: existing waiters for slabs for domain %d\n", 11107c478bd9Sstevel@tonic-gate proc, domid); 11117c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate return (nwait); 11147c478bd9Sstevel@tonic-gate } 11157c478bd9Sstevel@tonic-gate PR_SMR("%s: initial waiter for slabs for domain %d\n", proc, domid); 11167c478bd9Sstevel@tonic-gate /* 11177c478bd9Sstevel@tonic-gate * We are the first requester of a slab allocation for this 11187c478bd9Sstevel@tonic-gate * respective domain. Need to prep waiting area for 11197c478bd9Sstevel@tonic-gate * subsequent arrival of a slab. 11207c478bd9Sstevel@tonic-gate */ 11217c478bd9Sstevel@tonic-gate wp->w_sp = NULL; 11227c478bd9Sstevel@tonic-gate wp->w_done = 0; 11237c478bd9Sstevel@tonic-gate wp->w_serrno = 0; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate return (nwait); 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate /* 11317c478bd9Sstevel@tonic-gate * It is assumed that the caller had previously registered, 11327c478bd9Sstevel@tonic-gate * but wakeup did not occur due to caller never waiting. 11337c478bd9Sstevel@tonic-gate * Thus, slaballoc mutex is still held by caller. 11347c478bd9Sstevel@tonic-gate * 11357c478bd9Sstevel@tonic-gate * Returns: 0 11367c478bd9Sstevel@tonic-gate * EINVAL 11377c478bd9Sstevel@tonic-gate * EBUSY 11387c478bd9Sstevel@tonic-gate * w_serrno (smr_slaballoc_put) 11397c478bd9Sstevel@tonic-gate * (0, ENOLCK, ENOMEM, EDQUOT, EBUSY, ECANCELED) 11407c478bd9Sstevel@tonic-gate */ 11417c478bd9Sstevel@tonic-gate static int 11427c478bd9Sstevel@tonic-gate smr_slabwaiter_unregister(int domid, smr_slab_t **spp) 11437c478bd9Sstevel@tonic-gate { 11447c478bd9Sstevel@tonic-gate struct slabwaiter *wp; 11457c478bd9Sstevel@tonic-gate int serrno = 0; 11467c478bd9Sstevel@tonic-gate procname_t proc = "smr_slabwaiter_unregister"; 11477c478bd9Sstevel@tonic-gate 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate ASSERT(domid != IDN_NIL_DOMID); 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate wp = &idn.slabwaiter[domid]; 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate mutex_enter(&wp->w_mutex); 11547c478bd9Sstevel@tonic-gate 1155d3d50737SRafael Vanoni PR_SMR("%s: domain = %d, nwaiters = %d\n", proc, domid, wp->w_nwaiters); 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate if (wp->w_nwaiters <= 0) { 11587c478bd9Sstevel@tonic-gate /* 11597c478bd9Sstevel@tonic-gate * Hmmm...nobody is registered! 11607c478bd9Sstevel@tonic-gate */ 11617c478bd9Sstevel@tonic-gate PR_SMR("%s: NO WAITERS (domid = %d)\n", proc, domid); 11627c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 11637c478bd9Sstevel@tonic-gate return (EINVAL); 11647c478bd9Sstevel@tonic-gate } 11657c478bd9Sstevel@tonic-gate (wp->w_nwaiters)--; 11667c478bd9Sstevel@tonic-gate /* 11677c478bd9Sstevel@tonic-gate * Is our present under the tree? 11687c478bd9Sstevel@tonic-gate */ 11697c478bd9Sstevel@tonic-gate if (!wp->w_done) { 11707c478bd9Sstevel@tonic-gate /* 11717c478bd9Sstevel@tonic-gate * Bummer...no presents. Let the caller know 11727c478bd9Sstevel@tonic-gate * via a null slab pointer. 11737c478bd9Sstevel@tonic-gate * Note that we don't clean up immediately since 11747c478bd9Sstevel@tonic-gate * message might still come in for other waiters. 11757c478bd9Sstevel@tonic-gate * Thus, late sleepers may still get a chance. 11767c478bd9Sstevel@tonic-gate */ 11777c478bd9Sstevel@tonic-gate PR_SMR("%s: bummer no slab allocated for domain %d\n", 11787c478bd9Sstevel@tonic-gate proc, domid); 11797c478bd9Sstevel@tonic-gate ASSERT(wp->w_sp == NULL); 11807c478bd9Sstevel@tonic-gate (*spp) = NULL; 11817c478bd9Sstevel@tonic-gate serrno = wp->w_closed ? ECANCELED : EBUSY; 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate } else { 11847c478bd9Sstevel@tonic-gate (*spp) = wp->w_sp; 11857c478bd9Sstevel@tonic-gate serrno = wp->w_serrno; 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate #ifdef DEBUG 11887c478bd9Sstevel@tonic-gate if (serrno == 0) { 11897c478bd9Sstevel@tonic-gate register smr_slab_t *sp; 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate ASSERT(wp->w_sp); 11927c478bd9Sstevel@tonic-gate PR_SMR("%s: allocation succeeded (domain %d)\n", 11937c478bd9Sstevel@tonic-gate proc, domid); 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate DSLAB_LOCK_SHARED(domid); 11967c478bd9Sstevel@tonic-gate for (sp = idn_domain[domid].dslab; sp; sp = sp->sl_next) 11977c478bd9Sstevel@tonic-gate if (sp == wp->w_sp) 11987c478bd9Sstevel@tonic-gate break; 11997c478bd9Sstevel@tonic-gate if (sp == NULL) 12007c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 12017c478bd9Sstevel@tonic-gate "%s:%d: slab ptr = NULL", 12027c478bd9Sstevel@tonic-gate proc, domid); 12037c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(domid); 12047c478bd9Sstevel@tonic-gate } else { 12057c478bd9Sstevel@tonic-gate PR_SMR("%s: allocation failed (domain %d) " 12067c478bd9Sstevel@tonic-gate "[serrno = %d]\n", proc, domid, serrno); 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate if (wp->w_nwaiters == 0) { 12117c478bd9Sstevel@tonic-gate /* 12127c478bd9Sstevel@tonic-gate * Last one turns out the lights. 12137c478bd9Sstevel@tonic-gate */ 12147c478bd9Sstevel@tonic-gate PR_SMR("%s: domain %d last waiter, turning out lights\n", 12157c478bd9Sstevel@tonic-gate proc, domid); 12167c478bd9Sstevel@tonic-gate wp->w_sp = NULL; 12177c478bd9Sstevel@tonic-gate wp->w_done = 0; 12187c478bd9Sstevel@tonic-gate wp->w_serrno = 0; 12197c478bd9Sstevel@tonic-gate } 12207c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate return (serrno); 12237c478bd9Sstevel@tonic-gate } 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate /* 12267c478bd9Sstevel@tonic-gate * Called to abort any slaballoc requests on behalf of the 12277c478bd9Sstevel@tonic-gate * given domain. 12287c478bd9Sstevel@tonic-gate */ 12297c478bd9Sstevel@tonic-gate int 12307c478bd9Sstevel@tonic-gate smr_slabwaiter_abort(int domid, int serrno) 12317c478bd9Sstevel@tonic-gate { 12327c478bd9Sstevel@tonic-gate ASSERT(serrno != 0); 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate return (smr_slaballoc_put(domid, NULL, 0, serrno)); 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate 12377c478bd9Sstevel@tonic-gate /* 12387c478bd9Sstevel@tonic-gate * Put ourselves into a timedwait waiting for slab to be 12397c478bd9Sstevel@tonic-gate * allocated. 12407c478bd9Sstevel@tonic-gate * Returns with slaballoc mutex dropped. 12417c478bd9Sstevel@tonic-gate * 12427c478bd9Sstevel@tonic-gate * Returns: EINVAL 12437c478bd9Sstevel@tonic-gate * ETIMEDOUT 12447c478bd9Sstevel@tonic-gate * smr_slabwatier_unregister 12457c478bd9Sstevel@tonic-gate * (0, EINVAL, EBUSY, ENOMEM) 12467c478bd9Sstevel@tonic-gate */ 12477c478bd9Sstevel@tonic-gate static int 12487c478bd9Sstevel@tonic-gate smr_slaballoc_wait(int domid, smr_slab_t **spp) 12497c478bd9Sstevel@tonic-gate { 12507c478bd9Sstevel@tonic-gate struct slabwaiter *wp; 12517c478bd9Sstevel@tonic-gate int serrno = 0, serrno_unreg; 12527c478bd9Sstevel@tonic-gate procname_t proc = "smr_slaballoc_wait"; 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate wp = &idn.slabwaiter[domid]; 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&wp->w_mutex)); 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate mutex_enter(&wp->w_mutex); 12607c478bd9Sstevel@tonic-gate 1261bf30efa4Smathue PR_SMR("%s: domain = %d, nwaiters = %d, wsp = 0x%p\n", 1262*07d06da5SSurya Prakki proc, domid, wp->w_nwaiters, (void *)wp->w_sp); 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate if (wp->w_nwaiters <= 0) { 12657c478bd9Sstevel@tonic-gate /* 12667c478bd9Sstevel@tonic-gate * Hmmm...no waiters registered. 12677c478bd9Sstevel@tonic-gate */ 1268d3d50737SRafael Vanoni PR_SMR("%s: domain %d, no waiters!\n", proc, domid); 12697c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 12707c478bd9Sstevel@tonic-gate return (EINVAL); 12717c478bd9Sstevel@tonic-gate } 12727c478bd9Sstevel@tonic-gate ASSERT(DSLAB_READ_HELD(domid)); 12737c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(domid); 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate if (!wp->w_done && !wp->w_closed) { 12767c478bd9Sstevel@tonic-gate int rv; 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate /* 12797c478bd9Sstevel@tonic-gate * Only wait if data hasn't arrived yet. 12807c478bd9Sstevel@tonic-gate */ 1281d3d50737SRafael Vanoni PR_SMR("%s: domain %d, going to sleep...\n", proc, domid); 12827c478bd9Sstevel@tonic-gate 1283d3d50737SRafael Vanoni rv = cv_reltimedwait_sig(&wp->w_cv, &wp->w_mutex, 1284d3d50737SRafael Vanoni IDN_SLABALLOC_WAITTIME, TR_CLOCK_TICK); 12857c478bd9Sstevel@tonic-gate if (rv == -1) 12867c478bd9Sstevel@tonic-gate serrno = ETIMEDOUT; 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate PR_SMR("%s: domain %d, awakened (reason = %s)\n", 12897c478bd9Sstevel@tonic-gate proc, domid, (rv == -1) ? "TIMEOUT" : "SIGNALED"); 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate /* 12927c478bd9Sstevel@tonic-gate * We've awakened or request already filled! 12937c478bd9Sstevel@tonic-gate * Unregister ourselves. 12947c478bd9Sstevel@tonic-gate */ 12957c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate /* 12987c478bd9Sstevel@tonic-gate * Any gifts will be entered into spp. 12997c478bd9Sstevel@tonic-gate */ 13007c478bd9Sstevel@tonic-gate serrno_unreg = smr_slabwaiter_unregister(domid, spp); 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate /* 13037c478bd9Sstevel@tonic-gate * Leave with reader lock on dslab_lock. 13047c478bd9Sstevel@tonic-gate */ 13057c478bd9Sstevel@tonic-gate DSLAB_LOCK_SHARED(domid); 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate if ((serrno_unreg == EBUSY) && (serrno == ETIMEDOUT)) 13087c478bd9Sstevel@tonic-gate return (serrno); 13097c478bd9Sstevel@tonic-gate else 13107c478bd9Sstevel@tonic-gate return (serrno_unreg); 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate /* 13147c478bd9Sstevel@tonic-gate * A SMR slab was allocated on behalf of the given domain. 13157c478bd9Sstevel@tonic-gate * Wakeup anybody that may have been waiting for the allocation. 13167c478bd9Sstevel@tonic-gate * Note that if the domain is a remote one, i.e. master is allocating 13177c478bd9Sstevel@tonic-gate * on behalf of a slave, it's up to the caller to transmit the 13187c478bd9Sstevel@tonic-gate * allocation response to that domain. 13197c478bd9Sstevel@tonic-gate * The force flag indicates that we want to install the slab for 13207c478bd9Sstevel@tonic-gate * the given user regardless of whether there are waiters or not. 13217c478bd9Sstevel@tonic-gate * This is used primarily in situations where a slave may have timed 13227c478bd9Sstevel@tonic-gate * out before the response actually arrived. In this situation we 13237c478bd9Sstevel@tonic-gate * don't want to send slab back to the master after we went through 13247c478bd9Sstevel@tonic-gate * the trouble of allocating one. Master is _not_ allowed to do this 13257c478bd9Sstevel@tonic-gate * for remote domains. 13267c478bd9Sstevel@tonic-gate * 13277c478bd9Sstevel@tonic-gate * Returns: -1 Non-registered waiter or waiting area garbaged. 13287c478bd9Sstevel@tonic-gate * 0 Successfully performed operation. 13297c478bd9Sstevel@tonic-gate */ 13307c478bd9Sstevel@tonic-gate int 13317c478bd9Sstevel@tonic-gate smr_slaballoc_put(int domid, smr_slab_t *sp, int forceflag, int serrno) 13327c478bd9Sstevel@tonic-gate { 13337c478bd9Sstevel@tonic-gate idn_domain_t *dp; 13347c478bd9Sstevel@tonic-gate struct slabwaiter *wp; 13357c478bd9Sstevel@tonic-gate procname_t proc = "smr_slaballoc_put"; 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate dp = &idn_domain[domid]; 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate ASSERT(!serrno ? DSLAB_WRITE_HELD(domid) : 1); 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate if (domid == IDN_NIL_DOMID) 13437c478bd9Sstevel@tonic-gate return (-1); 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate ASSERT(serrno ? (sp == NULL) : (sp != NULL)); 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate wp = &idn.slabwaiter[domid]; 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate mutex_enter(&wp->w_mutex); 13507c478bd9Sstevel@tonic-gate 1351bf30efa4Smathue PR_SMR("%s: domain = %d, bufp = 0x%p, ebufp = 0x%p, " 1352bf30efa4Smathue "(f = %d, se = %d)\n", proc, domid, 1353*07d06da5SSurya Prakki (sp ? (void *)sp->sl_start : 0), 1354*07d06da5SSurya Prakki (sp ? (void *)sp->sl_end : 0), forceflag, serrno); 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate if (wp->w_nwaiters <= 0) { 13577c478bd9Sstevel@tonic-gate /* 13587c478bd9Sstevel@tonic-gate * There are no waiters!! Must have timed out 13597c478bd9Sstevel@tonic-gate * and left. Oh well... 13607c478bd9Sstevel@tonic-gate */ 13617c478bd9Sstevel@tonic-gate PR_SMR("%s: no slaballoc waiters found for domain %d\n", 13627c478bd9Sstevel@tonic-gate proc, domid); 13637c478bd9Sstevel@tonic-gate if (!forceflag || serrno || !sp) { 13647c478bd9Sstevel@tonic-gate /* 13657c478bd9Sstevel@tonic-gate * No waiters and caller doesn't want to force it. 13667c478bd9Sstevel@tonic-gate */ 13677c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 13687c478bd9Sstevel@tonic-gate return (-1); 13697c478bd9Sstevel@tonic-gate } 13707c478bd9Sstevel@tonic-gate PR_SMR("%s: forcing slab onto domain %d\n", proc, domid); 13717c478bd9Sstevel@tonic-gate ASSERT(domid == idn.localid); 13727c478bd9Sstevel@tonic-gate ASSERT(wp->w_sp == NULL); 13737c478bd9Sstevel@tonic-gate wp->w_done = 0; 13747c478bd9Sstevel@tonic-gate /* 13757c478bd9Sstevel@tonic-gate * Now we fall through and let it be added in the 13767c478bd9Sstevel@tonic-gate * regular manor. 13777c478bd9Sstevel@tonic-gate */ 13787c478bd9Sstevel@tonic-gate } 13797c478bd9Sstevel@tonic-gate if (wp->w_done) { 13807c478bd9Sstevel@tonic-gate /* 13817c478bd9Sstevel@tonic-gate * There's at least one waiter so there has 13827c478bd9Sstevel@tonic-gate * to be a slab structure waiting for us. 13837c478bd9Sstevel@tonic-gate * If everything is going smoothly, there should only 13847c478bd9Sstevel@tonic-gate * be one guy coming through the path of inserting 13857c478bd9Sstevel@tonic-gate * an error or good slab. However, if a disconnect was 13867c478bd9Sstevel@tonic-gate * detected, you may get several guys coming through 13877c478bd9Sstevel@tonic-gate * trying to let everybody know. 13887c478bd9Sstevel@tonic-gate */ 13897c478bd9Sstevel@tonic-gate ASSERT(wp->w_serrno ? 13907c478bd9Sstevel@tonic-gate (wp->w_sp == NULL) : (wp->w_sp != NULL)); 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate cv_broadcast(&wp->w_cv); 13937c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate return (-1); 13967c478bd9Sstevel@tonic-gate } 13977c478bd9Sstevel@tonic-gate if (serrno != 0) { 13987c478bd9Sstevel@tonic-gate /* 13997c478bd9Sstevel@tonic-gate * Bummer...allocation failed. This call is simply 14007c478bd9Sstevel@tonic-gate * to wake up the sleepers and let them know. 14017c478bd9Sstevel@tonic-gate */ 1402d3d50737SRafael Vanoni PR_SMR("%s: slaballoc failed for domain %d\n", proc, domid); 14037c478bd9Sstevel@tonic-gate wp->w_serrno = serrno; 14047c478bd9Sstevel@tonic-gate wp->w_done = 1; 14057c478bd9Sstevel@tonic-gate cv_broadcast(&wp->w_cv); 14067c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate return (0); 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate PR_SMR("%s: putting slab into struct (domid=%d, localid=%d)\n", 14117c478bd9Sstevel@tonic-gate proc, domid, idn.localid); 14127c478bd9Sstevel@tonic-gate /* 14137c478bd9Sstevel@tonic-gate * Prep the slab structure. 14147c478bd9Sstevel@tonic-gate */ 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate if (domid == idn.localid) { 14177c478bd9Sstevel@tonic-gate /* 14187c478bd9Sstevel@tonic-gate * Allocation was indeed for me. 14197c478bd9Sstevel@tonic-gate * Slab may or may not be locked when 14207c478bd9Sstevel@tonic-gate * we reach. Normally they will be locked 14217c478bd9Sstevel@tonic-gate * if we're being called on behalf of a 14227c478bd9Sstevel@tonic-gate * free, and not locked if on behalf of 14237c478bd9Sstevel@tonic-gate * a new allocation request. 14247c478bd9Sstevel@tonic-gate */ 14257c478bd9Sstevel@tonic-gate lock_clear(&sp->sl_lock); 14267c478bd9Sstevel@tonic-gate smr_alloc_buflist(sp); 14277c478bd9Sstevel@tonic-gate #ifdef DEBUG 14287c478bd9Sstevel@tonic-gate } else { 14297c478bd9Sstevel@tonic-gate uint_t rv; 14307c478bd9Sstevel@tonic-gate /* 14317c478bd9Sstevel@tonic-gate * Slab was not allocated on my behalf. Must be 14327c478bd9Sstevel@tonic-gate * a master request on behalf of some other domain. 14337c478bd9Sstevel@tonic-gate * Prep appropriately. Slab should have been locked 14347c478bd9Sstevel@tonic-gate * by smr_slab_reserve. 14357c478bd9Sstevel@tonic-gate */ 14367c478bd9Sstevel@tonic-gate rv = lock_try(&sp->sl_lock); 14377c478bd9Sstevel@tonic-gate ASSERT(!rv); 14387c478bd9Sstevel@tonic-gate ASSERT(sp->sl_domid == (short)domid); 14397c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate /* 14437c478bd9Sstevel@tonic-gate * Slab is ready to go. Insert it into the domain's 14447c478bd9Sstevel@tonic-gate * slab list so once we wake everybody up they'll find it. 14457c478bd9Sstevel@tonic-gate * You better have write lock if you're putting treasures 14467c478bd9Sstevel@tonic-gate * there. 14477c478bd9Sstevel@tonic-gate */ 14487c478bd9Sstevel@tonic-gate ASSERT(DSLAB_WRITE_HELD(domid)); 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate sp->sl_next = dp->dslab; 14517c478bd9Sstevel@tonic-gate dp->dslab = sp; 14527c478bd9Sstevel@tonic-gate dp->dnslabs++; 14537c478bd9Sstevel@tonic-gate 14547c478bd9Sstevel@tonic-gate /* 14557c478bd9Sstevel@tonic-gate * It's possible to fall through here without waiters. 14567c478bd9Sstevel@tonic-gate * This is a case where forceflag was set. 14577c478bd9Sstevel@tonic-gate */ 14587c478bd9Sstevel@tonic-gate if (wp->w_nwaiters > 0) { 14597c478bd9Sstevel@tonic-gate wp->w_sp = sp; 14607c478bd9Sstevel@tonic-gate wp->w_serrno = serrno; 14617c478bd9Sstevel@tonic-gate wp->w_done = 1; 14627c478bd9Sstevel@tonic-gate cv_broadcast(&wp->w_cv); 14637c478bd9Sstevel@tonic-gate } else { 14647c478bd9Sstevel@tonic-gate ASSERT(forceflag); 14657c478bd9Sstevel@tonic-gate wp->w_sp = NULL; 14667c478bd9Sstevel@tonic-gate wp->w_serrno = 0; 14677c478bd9Sstevel@tonic-gate wp->w_done = 0; 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate mutex_exit(&wp->w_mutex); 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate return (0); 14727c478bd9Sstevel@tonic-gate } 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate /* 14757c478bd9Sstevel@tonic-gate * Get the slab representing [bufp,ebufp] from the respective 14767c478bd9Sstevel@tonic-gate * domain's pool if all the buffers are free. Remove them from 14777c478bd9Sstevel@tonic-gate * the domain's list and return it. 14787c478bd9Sstevel@tonic-gate * If bufp == NULL, then return however many free ones you 14797c478bd9Sstevel@tonic-gate * can find. 14807c478bd9Sstevel@tonic-gate * List of slabs are returned locked (sl_lock). 14817c478bd9Sstevel@tonic-gate * XXX - Need minimum limit to make sure we don't free up _all_ 14827c478bd9Sstevel@tonic-gate * of our slabs! However, during a shutdown we will need 14837c478bd9Sstevel@tonic-gate * method to free them all up regardless of locking. 14847c478bd9Sstevel@tonic-gate */ 14857c478bd9Sstevel@tonic-gate smr_slab_t * 14867c478bd9Sstevel@tonic-gate smr_slaballoc_get(int domid, caddr_t bufp, caddr_t ebufp) 14877c478bd9Sstevel@tonic-gate { 14887c478bd9Sstevel@tonic-gate idn_domain_t *dp; 14897c478bd9Sstevel@tonic-gate smr_slab_t *retsp, *sp, **psp; 14907c478bd9Sstevel@tonic-gate int foundit, islocal = 0; 14917c478bd9Sstevel@tonic-gate int nslabs; 14927c478bd9Sstevel@tonic-gate procname_t proc = "smr_slaballoc_get"; 14937c478bd9Sstevel@tonic-gate 1494bf30efa4Smathue PR_SMR("%s: getting slab for domain %d [bufp=0x%p, ebufp=0x%p]\n", 1495*07d06da5SSurya Prakki proc, domid, (void *)bufp, (void *)ebufp); 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate dp = &idn_domain[domid]; 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate ASSERT(DSLAB_WRITE_HELD(domid)); 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate if ((sp = dp->dslab) == NULL) { 1502d3d50737SRafael Vanoni PR_SMR("%s: oops, no slabs for domain %d\n", proc, domid); 15037c478bd9Sstevel@tonic-gate return (NULL); 15047c478bd9Sstevel@tonic-gate } 15057c478bd9Sstevel@tonic-gate /* 15067c478bd9Sstevel@tonic-gate * If domid is myself then I'm trying to get a slab out 15077c478bd9Sstevel@tonic-gate * of my local pool. Otherwise, I'm the master and 15087c478bd9Sstevel@tonic-gate * I'm trying to get the slab representative from the 15097c478bd9Sstevel@tonic-gate * global pool. 15107c478bd9Sstevel@tonic-gate */ 15117c478bd9Sstevel@tonic-gate if (domid == idn.localid) 15127c478bd9Sstevel@tonic-gate islocal = 1; 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate if (bufp != NULL) { 15157c478bd9Sstevel@tonic-gate nslabs = -1; 15167c478bd9Sstevel@tonic-gate } else { 15177c478bd9Sstevel@tonic-gate nslabs = *(int *)ebufp; 15187c478bd9Sstevel@tonic-gate if (nslabs == 0) { 15197c478bd9Sstevel@tonic-gate PR_SMR("%s: requested nslabs (%d) <= 0\n", 15207c478bd9Sstevel@tonic-gate proc, nslabs); 15217c478bd9Sstevel@tonic-gate return (NULL); 15227c478bd9Sstevel@tonic-gate } else if (nslabs < 0) { 15237c478bd9Sstevel@tonic-gate /* 15247c478bd9Sstevel@tonic-gate * Caller wants them all! 15257c478bd9Sstevel@tonic-gate */ 15267c478bd9Sstevel@tonic-gate nslabs = (int)dp->dnslabs; 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate } 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate retsp = NULL; 15317c478bd9Sstevel@tonic-gate foundit = 0; 15327c478bd9Sstevel@tonic-gate for (psp = &dp->dslab; sp; sp = *psp) { 15337c478bd9Sstevel@tonic-gate int isbusy; 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate if (bufp && (sp->sl_start != bufp)) { 15367c478bd9Sstevel@tonic-gate psp = &sp->sl_next; 15377c478bd9Sstevel@tonic-gate continue; 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate if (bufp && (ebufp > sp->sl_end)) { 1541bf30efa4Smathue PR_SMR("%s: bufp/ebufp (0x%p/0x%p) " 1542*07d06da5SSurya Prakki "expected (0x%p/0x%p)\n", proc, (void *)bufp, 1543*07d06da5SSurya Prakki (void *)ebufp, (void *)sp->sl_start, 1544*07d06da5SSurya Prakki (void *)sp->sl_end); 15457c478bd9Sstevel@tonic-gate ASSERT(0); 15467c478bd9Sstevel@tonic-gate } 15477c478bd9Sstevel@tonic-gate /* 15487c478bd9Sstevel@tonic-gate * We found the desired slab. Make sure 15497c478bd9Sstevel@tonic-gate * it's free. 15507c478bd9Sstevel@tonic-gate */ 15517c478bd9Sstevel@tonic-gate foundit++; 15527c478bd9Sstevel@tonic-gate isbusy = 0; 15537c478bd9Sstevel@tonic-gate if (islocal) { 15547c478bd9Sstevel@tonic-gate int spl; 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate /* 15577c478bd9Sstevel@tonic-gate * Some of the buffers in the slab 15587c478bd9Sstevel@tonic-gate * are still in use. Unlock the 15597c478bd9Sstevel@tonic-gate * buffers we locked and bail out. 15607c478bd9Sstevel@tonic-gate */ 15617c478bd9Sstevel@tonic-gate spl = splhi(); 15627c478bd9Sstevel@tonic-gate if (!lock_try(&sp->sl_lock)) { 15637c478bd9Sstevel@tonic-gate isbusy = 1; 15647c478bd9Sstevel@tonic-gate foundit--; 15657c478bd9Sstevel@tonic-gate } else if (sp->sl_inuse) { 15667c478bd9Sstevel@tonic-gate lock_clear(&sp->sl_lock); 15677c478bd9Sstevel@tonic-gate isbusy = 1; 15687c478bd9Sstevel@tonic-gate foundit--; 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate splx(spl); 15717c478bd9Sstevel@tonic-gate } else { 15727c478bd9Sstevel@tonic-gate /* 15737c478bd9Sstevel@tonic-gate * If not local, then I'm the master getting 15747c478bd9Sstevel@tonic-gate * a slab from one of the slaves. In this case, 15757c478bd9Sstevel@tonic-gate * their slab structs will always be locked. 15767c478bd9Sstevel@tonic-gate */ 15777c478bd9Sstevel@tonic-gate ASSERT(!lock_try(&sp->sl_lock)); 15787c478bd9Sstevel@tonic-gate } 15797c478bd9Sstevel@tonic-gate if (!isbusy) { 15807c478bd9Sstevel@tonic-gate /* 15817c478bd9Sstevel@tonic-gate * Delete the entry from the list and slap 15827c478bd9Sstevel@tonic-gate * it onto our return list. 15837c478bd9Sstevel@tonic-gate */ 15847c478bd9Sstevel@tonic-gate *psp = sp->sl_next; 15857c478bd9Sstevel@tonic-gate sp->sl_next = retsp; 15867c478bd9Sstevel@tonic-gate retsp = sp; 15877c478bd9Sstevel@tonic-gate } else { 15887c478bd9Sstevel@tonic-gate psp = &sp->sl_next; 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate /* 15917c478bd9Sstevel@tonic-gate * If bufp == NULL (alternate interface) and we haven't 15927c478bd9Sstevel@tonic-gate * found the desired number of slabs yet, keep looking. 15937c478bd9Sstevel@tonic-gate */ 15947c478bd9Sstevel@tonic-gate if (bufp || (foundit == nslabs)) 15957c478bd9Sstevel@tonic-gate break; 15967c478bd9Sstevel@tonic-gate } 15977c478bd9Sstevel@tonic-gate dp->dnslabs -= (short)foundit; 15987c478bd9Sstevel@tonic-gate 15997c478bd9Sstevel@tonic-gate if (foundit) { 1600d3d50737SRafael Vanoni PR_SMR("%s: found %d free slabs (domid = %d)\n", proc, foundit, 1601d3d50737SRafael Vanoni domid); 16027c478bd9Sstevel@tonic-gate } else { 1603d3d50737SRafael Vanoni PR_SMR("%s: no free slabs found (domid = %d)\n", proc, domid); 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate /* 16077c478bd9Sstevel@tonic-gate * If this is the alternate interface, need to return 16087c478bd9Sstevel@tonic-gate * the number of slabs found in the ebufp parameter. 16097c478bd9Sstevel@tonic-gate */ 16107c478bd9Sstevel@tonic-gate if (bufp == NULL) 16117c478bd9Sstevel@tonic-gate *(int *)ebufp = foundit; 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate return (retsp); 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate /* 16177c478bd9Sstevel@tonic-gate * Wrapper to hide alternate interface to smr_slaballoc_get() 16187c478bd9Sstevel@tonic-gate */ 16197c478bd9Sstevel@tonic-gate smr_slab_t * 16207c478bd9Sstevel@tonic-gate smr_slaballoc_get_n(int domid, int *nslabs) 16217c478bd9Sstevel@tonic-gate { 16227c478bd9Sstevel@tonic-gate smr_slab_t *sp; 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate ASSERT(DSLAB_WRITE_HELD(domid)); 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate sp = smr_slaballoc_get(domid, NULL, (caddr_t)nslabs); 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate return (sp); 16297c478bd9Sstevel@tonic-gate } 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate /* 16327c478bd9Sstevel@tonic-gate * Only called by master. Initialize slab pool based on local SMR. 16337c478bd9Sstevel@tonic-gate * Returns number of slabs initialized. 16347c478bd9Sstevel@tonic-gate * reserved_size = Length of area at the front of the NWR portion 16357c478bd9Sstevel@tonic-gate * of the SMR to reserve and not make available for 16367c478bd9Sstevel@tonic-gate * slab allocations. Must be a IDN_SMR_BUFSIZE multiple. 16377c478bd9Sstevel@tonic-gate * reserved_area = Pointer to reserved area, if any. 16387c478bd9Sstevel@tonic-gate */ 16397c478bd9Sstevel@tonic-gate int 16407c478bd9Sstevel@tonic-gate smr_slabpool_init(size_t reserved_size, caddr_t *reserved_area) 16417c478bd9Sstevel@tonic-gate { 16427c478bd9Sstevel@tonic-gate size_t nwr_available; 16437c478bd9Sstevel@tonic-gate int minperpool, ntotslabs, nxslabs, nslabs; 16447c478bd9Sstevel@tonic-gate register int p, pp; 16457c478bd9Sstevel@tonic-gate register caddr_t bufp; 16467c478bd9Sstevel@tonic-gate register smr_slab_t *sp; 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate ASSERT(IDN_GLOCK_IS_EXCL()); 16497c478bd9Sstevel@tonic-gate ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate *reserved_area = NULL; 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate nwr_available = MB2B(IDN_NWR_SIZE) - reserved_size; 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate if ((idn.localid != IDN_GET_MASTERID()) || 16567c478bd9Sstevel@tonic-gate (nwr_available < IDN_SLAB_SIZE) || 16577c478bd9Sstevel@tonic-gate (idn.slabpool != NULL) || 16587c478bd9Sstevel@tonic-gate ((reserved_size != 0) && (reserved_size & (IDN_SMR_BUFSIZE-1)))) { 16597c478bd9Sstevel@tonic-gate return (-1); 16607c478bd9Sstevel@tonic-gate } 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate idn.slabpool = GETSTRUCT(struct slabpool, 1); 16637c478bd9Sstevel@tonic-gate idn.slabpool->ntotslabs = ntotslabs = nwr_available / IDN_SLAB_SIZE; 16647c478bd9Sstevel@tonic-gate ASSERT(ntotslabs > 0); 16657c478bd9Sstevel@tonic-gate minperpool = (ntotslabs < IDN_SLAB_MINPERPOOL) ? 16667c478bd9Sstevel@tonic-gate 1 : IDN_SLAB_MINPERPOOL; 16677c478bd9Sstevel@tonic-gate idn.slabpool->npools = (ntotslabs + (minperpool - 1)) / minperpool; 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate if ((idn.slabpool->npools & 1) == 0) { 16707c478bd9Sstevel@tonic-gate /* 16717c478bd9Sstevel@tonic-gate * npools needs to be odd for hashing algorithm. 16727c478bd9Sstevel@tonic-gate */ 16737c478bd9Sstevel@tonic-gate idn.slabpool->npools++; 16747c478bd9Sstevel@tonic-gate } 16757c478bd9Sstevel@tonic-gate ASSERT(idn.slabpool->npools > 0); 16767c478bd9Sstevel@tonic-gate minperpool = (ntotslabs < idn.slabpool->npools) ? 16777c478bd9Sstevel@tonic-gate 1 : (ntotslabs / idn.slabpool->npools); 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate /* 16807c478bd9Sstevel@tonic-gate * Calculate the number of extra slabs that will need to 16817c478bd9Sstevel@tonic-gate * be alloted to the pools. This number will be less than 16827c478bd9Sstevel@tonic-gate * npools. Only one extra slab is allocated to each pool 16837c478bd9Sstevel@tonic-gate * until we have assigned all the extra slabs. 16847c478bd9Sstevel@tonic-gate */ 16857c478bd9Sstevel@tonic-gate if (ntotslabs > (idn.slabpool->npools * minperpool)) 16867c478bd9Sstevel@tonic-gate nxslabs = ntotslabs - (idn.slabpool->npools * minperpool); 16877c478bd9Sstevel@tonic-gate else 16887c478bd9Sstevel@tonic-gate nxslabs = 0; 16897c478bd9Sstevel@tonic-gate ASSERT((nxslabs >= 0) && (nxslabs < idn.slabpool->npools)); 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate idn.slabpool->pool = GETSTRUCT(struct smr_slabtbl, 16927c478bd9Sstevel@tonic-gate idn.slabpool->npools); 16937c478bd9Sstevel@tonic-gate sp = GETSTRUCT(smr_slab_t, idn.slabpool->ntotslabs); 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate idn.slabpool->savep = sp; 16967c478bd9Sstevel@tonic-gate bufp = idn.smr.vaddr + reserved_size; 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate for (p = nslabs = 0; 16997c478bd9Sstevel@tonic-gate (p < idn.slabpool->npools) && (ntotslabs > 0); 17007c478bd9Sstevel@tonic-gate p++, ntotslabs -= nslabs) { 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate nslabs = (ntotslabs < minperpool) ? ntotslabs : minperpool; 17037c478bd9Sstevel@tonic-gate if (nxslabs > 0) { 17047c478bd9Sstevel@tonic-gate nslabs++; 17057c478bd9Sstevel@tonic-gate nxslabs--; 17067c478bd9Sstevel@tonic-gate } 17077c478bd9Sstevel@tonic-gate idn.slabpool->pool[p].sarray = sp; 17087c478bd9Sstevel@tonic-gate for (pp = 0; pp < nslabs; pp++) { 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate sp->sl_next = NULL; 17117c478bd9Sstevel@tonic-gate sp->sl_start = bufp; 17127c478bd9Sstevel@tonic-gate sp->sl_end = bufp = sp->sl_start + IDN_SLAB_SIZE; 17137c478bd9Sstevel@tonic-gate sp->sl_lock = 0; 17147c478bd9Sstevel@tonic-gate sp->sl_domid = (short)IDN_NIL_DOMID; 17157c478bd9Sstevel@tonic-gate 17167c478bd9Sstevel@tonic-gate sp++; 17177c478bd9Sstevel@tonic-gate } 17187c478bd9Sstevel@tonic-gate idn.slabpool->pool[p].nfree = nslabs; 17197c478bd9Sstevel@tonic-gate idn.slabpool->pool[p].nslabs = nslabs; 17207c478bd9Sstevel@tonic-gate } 17217c478bd9Sstevel@tonic-gate ASSERT((ntotslabs == 0) && (nxslabs == 0)); 17227c478bd9Sstevel@tonic-gate /* 17237c478bd9Sstevel@tonic-gate * We should be at the end of the SMR at this point. 17247c478bd9Sstevel@tonic-gate */ 1725d3d50737SRafael Vanoni ASSERT(bufp == (idn.smr.vaddr + reserved_size 17267c478bd9Sstevel@tonic-gate + (idn.slabpool->ntotslabs * IDN_SLAB_SIZE))); 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate if (reserved_size != 0) 17297c478bd9Sstevel@tonic-gate *reserved_area = idn.smr.vaddr; 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate return (0); 17327c478bd9Sstevel@tonic-gate } 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate void 17357c478bd9Sstevel@tonic-gate smr_slabpool_deinit() 17367c478bd9Sstevel@tonic-gate { 17377c478bd9Sstevel@tonic-gate if (idn.slabpool == NULL) 17387c478bd9Sstevel@tonic-gate return; 17397c478bd9Sstevel@tonic-gate 17407c478bd9Sstevel@tonic-gate FREESTRUCT(idn.slabpool->savep, smr_slab_t, idn.slabpool->ntotslabs); 17417c478bd9Sstevel@tonic-gate FREESTRUCT(idn.slabpool->pool, struct smr_slabtbl, 17427c478bd9Sstevel@tonic-gate idn.slabpool->npools); 17437c478bd9Sstevel@tonic-gate FREESTRUCT(idn.slabpool, struct slabpool, 1); 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate idn.slabpool = NULL; 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate void 17497c478bd9Sstevel@tonic-gate smr_alloc_buflist(smr_slab_t *sp) 17507c478bd9Sstevel@tonic-gate { 17517c478bd9Sstevel@tonic-gate int n, nbufs; 17527c478bd9Sstevel@tonic-gate caddr_t sbufp; 17537c478bd9Sstevel@tonic-gate smr_slabbuf_t *hp, *bp; 17547c478bd9Sstevel@tonic-gate 17557c478bd9Sstevel@tonic-gate if (sp->sl_head) 17567c478bd9Sstevel@tonic-gate return; 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate nbufs = (sp->sl_end - sp->sl_start) / IDN_SMR_BUFSIZE; 17597c478bd9Sstevel@tonic-gate ASSERT(nbufs > 0); 17607c478bd9Sstevel@tonic-gate if (nbufs <= 0) { 17617c478bd9Sstevel@tonic-gate sp->sl_head = sp->sl_free = sp->sl_inuse = NULL; 17627c478bd9Sstevel@tonic-gate return; 17637c478bd9Sstevel@tonic-gate } 17647c478bd9Sstevel@tonic-gate 17657c478bd9Sstevel@tonic-gate hp = GETSTRUCT(smr_slabbuf_t, nbufs); 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate sbufp = sp->sl_start; 17687c478bd9Sstevel@tonic-gate for (n = 0, bp = hp; n < nbufs; bp++, n++) { 17697c478bd9Sstevel@tonic-gate bp->sb_bufp = sbufp; 17707c478bd9Sstevel@tonic-gate bp->sb_domid = IDN_NIL_DOMID; 17717c478bd9Sstevel@tonic-gate bp->sb_next = bp + 1; 17727c478bd9Sstevel@tonic-gate sbufp += IDN_SMR_BUFSIZE; 17737c478bd9Sstevel@tonic-gate } 17747c478bd9Sstevel@tonic-gate (--bp)->sb_next = NULL; 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate sp->sl_head = sp->sl_free = hp; 17777c478bd9Sstevel@tonic-gate sp->sl_inuse = NULL; 17787c478bd9Sstevel@tonic-gate } 17797c478bd9Sstevel@tonic-gate 17807c478bd9Sstevel@tonic-gate void 17817c478bd9Sstevel@tonic-gate smr_free_buflist(smr_slab_t *sp) 17827c478bd9Sstevel@tonic-gate { 17837c478bd9Sstevel@tonic-gate int nbufs; 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate if (sp->sl_head == NULL) 17867c478bd9Sstevel@tonic-gate return; 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate nbufs = (sp->sl_end - sp->sl_start) / IDN_SMR_BUFSIZE; 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate FREESTRUCT(sp->sl_head, smr_slabbuf_t, nbufs); 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate sp->sl_head = sp->sl_free = sp->sl_inuse = NULL; 17937c478bd9Sstevel@tonic-gate } 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate /* 17967c478bd9Sstevel@tonic-gate * Returns: 0 Successfully located a slab. 17977c478bd9Sstevel@tonic-gate * -1 Failure. 17987c478bd9Sstevel@tonic-gate */ 17997c478bd9Sstevel@tonic-gate static smr_slab_t * 18007c478bd9Sstevel@tonic-gate smr_slab_reserve(int domid) 18017c478bd9Sstevel@tonic-gate { 18027c478bd9Sstevel@tonic-gate register int p, nextp, s, nexts; 18037c478bd9Sstevel@tonic-gate register smr_slab_t *spa; 18047c478bd9Sstevel@tonic-gate int startp, starts; 18057c478bd9Sstevel@tonic-gate int foundone = 0; 18067c478bd9Sstevel@tonic-gate int spl; 18077c478bd9Sstevel@tonic-gate procname_t proc = "smr_slab_reserve"; 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate p = startp = SMR_SLABPOOL_HASH(domid); 18107c478bd9Sstevel@tonic-gate nextp = -1; 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate spl = splhi(); 18137c478bd9Sstevel@tonic-gate while ((nextp != startp) && !foundone) { 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate s = starts = SMR_SLAB_HASH(p, domid); 18167c478bd9Sstevel@tonic-gate nexts = -1; 18177c478bd9Sstevel@tonic-gate spa = &(idn.slabpool->pool[p].sarray[0]); 18187c478bd9Sstevel@tonic-gate 18197c478bd9Sstevel@tonic-gate while ((nexts != starts) && !foundone) { 18207c478bd9Sstevel@tonic-gate if (lock_try(&spa[s].sl_lock)) { 18217c478bd9Sstevel@tonic-gate foundone = 1; 18227c478bd9Sstevel@tonic-gate break; 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate nexts = SMR_SLAB_HASHSTEP(p, s); 18257c478bd9Sstevel@tonic-gate s = nexts; 18267c478bd9Sstevel@tonic-gate } 18277c478bd9Sstevel@tonic-gate if (foundone) 18287c478bd9Sstevel@tonic-gate break; 18297c478bd9Sstevel@tonic-gate nextp = SMR_SLABPOOL_HASHSTEP(p); 18307c478bd9Sstevel@tonic-gate p = nextp; 18317c478bd9Sstevel@tonic-gate } 18327c478bd9Sstevel@tonic-gate splx(spl); 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate if (foundone) { 18357c478bd9Sstevel@tonic-gate ASSERT((&spa[s] >= idn.slabpool->savep) && 18367c478bd9Sstevel@tonic-gate (&spa[s] < (idn.slabpool->savep + 18377c478bd9Sstevel@tonic-gate idn.slabpool->ntotslabs))); 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate spa[s].sl_domid = (short)domid; 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate ATOMIC_DEC(idn.slabpool->pool[p].nfree); 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate if (domid == idn.localid) { 18447c478bd9Sstevel@tonic-gate smr_slab_t *nsp; 18457c478bd9Sstevel@tonic-gate /* 18467c478bd9Sstevel@tonic-gate * Caller is actually reserving a slab for 18477c478bd9Sstevel@tonic-gate * themself which means they'll need the full 18487c478bd9Sstevel@tonic-gate * slab structure to represent all of the I/O 18497c478bd9Sstevel@tonic-gate * buffers. The "spa" is just a representative 18507c478bd9Sstevel@tonic-gate * and doesn't contain the space to manage the 18517c478bd9Sstevel@tonic-gate * individual buffers. Need to alloc a full-size 18527c478bd9Sstevel@tonic-gate * struct. 18537c478bd9Sstevel@tonic-gate * Note that this results in the returning 18547c478bd9Sstevel@tonic-gate * smr_slab_t structure being unlocked. 18557c478bd9Sstevel@tonic-gate */ 18567c478bd9Sstevel@tonic-gate ASSERT(idn.localid == IDN_GET_MASTERID()); 18577c478bd9Sstevel@tonic-gate nsp = GETSTRUCT(smr_slab_t, 1); 18587c478bd9Sstevel@tonic-gate nsp->sl_start = spa[s].sl_start; 18597c478bd9Sstevel@tonic-gate nsp->sl_end = spa[s].sl_end; 18607c478bd9Sstevel@tonic-gate smr_alloc_buflist(nsp); 18617c478bd9Sstevel@tonic-gate spa = nsp; 18627c478bd9Sstevel@tonic-gate PR_SMR("%s: allocated full slab struct for domain %d\n", 18637c478bd9Sstevel@tonic-gate proc, domid); 18647c478bd9Sstevel@tonic-gate } else { 18657c478bd9Sstevel@tonic-gate /* 18667c478bd9Sstevel@tonic-gate * Slab structure gets returned locked. 18677c478bd9Sstevel@tonic-gate */ 18687c478bd9Sstevel@tonic-gate spa += s; 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate 1871bf30efa4Smathue PR_SMR("%s: allocated slab 0x%p (start=0x%p, size=%lu) for " 1872*07d06da5SSurya Prakki "domain %d\n", proc, (void *)spa, (void *)spa->sl_start, 18737c478bd9Sstevel@tonic-gate spa->sl_end - spa->sl_start, domid); 18747c478bd9Sstevel@tonic-gate } else { 18757c478bd9Sstevel@tonic-gate PR_SMR("%s: FAILED to allocate for domain %d\n", 18767c478bd9Sstevel@tonic-gate proc, domid); 18777c478bd9Sstevel@tonic-gate spa = NULL; 18787c478bd9Sstevel@tonic-gate } 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate return (spa); 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate static void 18847c478bd9Sstevel@tonic-gate smr_slab_unreserve(int domid, smr_slab_t *sp) 18857c478bd9Sstevel@tonic-gate { 18867c478bd9Sstevel@tonic-gate register int p, nextp, s, nexts; 18877c478bd9Sstevel@tonic-gate register smr_slab_t *spa; 18887c478bd9Sstevel@tonic-gate int foundit = 0; 18897c478bd9Sstevel@tonic-gate int startp, starts; 18907c478bd9Sstevel@tonic-gate caddr_t bufp; 18917c478bd9Sstevel@tonic-gate procname_t proc = "smr_slab_unreserve"; 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate bufp = sp->sl_start; 18947c478bd9Sstevel@tonic-gate p = startp = SMR_SLABPOOL_HASH(domid); 18957c478bd9Sstevel@tonic-gate nextp = -1; 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate while ((nextp != startp) && !foundit) { 18987c478bd9Sstevel@tonic-gate 18997c478bd9Sstevel@tonic-gate s = starts = SMR_SLAB_HASH(p, domid); 19007c478bd9Sstevel@tonic-gate nexts = -1; 19017c478bd9Sstevel@tonic-gate spa = &(idn.slabpool->pool[p].sarray[0]); 19027c478bd9Sstevel@tonic-gate 19037c478bd9Sstevel@tonic-gate while ((nexts != starts) && !foundit) { 19047c478bd9Sstevel@tonic-gate if (spa[s].sl_start == bufp) { 19057c478bd9Sstevel@tonic-gate foundit = 1; 19067c478bd9Sstevel@tonic-gate break; 19077c478bd9Sstevel@tonic-gate } 19087c478bd9Sstevel@tonic-gate nexts = SMR_SLAB_HASHSTEP(p, s); 19097c478bd9Sstevel@tonic-gate s = nexts; 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate if (foundit) 19127c478bd9Sstevel@tonic-gate break; 19137c478bd9Sstevel@tonic-gate nextp = SMR_SLABPOOL_HASHSTEP(p); 19147c478bd9Sstevel@tonic-gate p = nextp; 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate if (foundit) { 19177c478bd9Sstevel@tonic-gate ASSERT((&spa[s] >= idn.slabpool->savep) && 19187c478bd9Sstevel@tonic-gate (&spa[s] < (idn.slabpool->savep + 19197c478bd9Sstevel@tonic-gate idn.slabpool->ntotslabs))); 19207c478bd9Sstevel@tonic-gate ASSERT(!lock_try(&spa[s].sl_lock)); 19217c478bd9Sstevel@tonic-gate ASSERT(spa[s].sl_domid == (short)domid); 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate spa[s].sl_next = NULL; 19247c478bd9Sstevel@tonic-gate spa[s].sl_domid = (short)IDN_NIL_DOMID; 19257c478bd9Sstevel@tonic-gate lock_clear(&spa[s].sl_lock); 19267c478bd9Sstevel@tonic-gate 19277c478bd9Sstevel@tonic-gate ATOMIC_INC(idn.slabpool->pool[p].nfree); 19287c478bd9Sstevel@tonic-gate 1929bf30efa4Smathue PR_SMR("%s: freed (bufp=0x%p) for domain %d\n", 1930*07d06da5SSurya Prakki proc, (void *)bufp, domid); 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate if (domid == idn.localid) { 19337c478bd9Sstevel@tonic-gate /* 19347c478bd9Sstevel@tonic-gate * Caller is actually unreserving a slab of their 19357c478bd9Sstevel@tonic-gate * own. Note that only the master calls this 19367c478bd9Sstevel@tonic-gate * routine. Since the master's local slab 19377c478bd9Sstevel@tonic-gate * structures do not get entered into the global 19387c478bd9Sstevel@tonic-gate * "representative" pool, we need to free up the 19397c478bd9Sstevel@tonic-gate * data structure that was passed in. 19407c478bd9Sstevel@tonic-gate */ 19417c478bd9Sstevel@tonic-gate ASSERT(idn.localid == IDN_GET_MASTERID()); 19427c478bd9Sstevel@tonic-gate ASSERT(sp != &spa[s]); 19437c478bd9Sstevel@tonic-gate 19447c478bd9Sstevel@tonic-gate smr_free_buflist(sp); 19457c478bd9Sstevel@tonic-gate FREESTRUCT(sp, smr_slab_t, 1); 19467c478bd9Sstevel@tonic-gate } else { 19477c478bd9Sstevel@tonic-gate ASSERT(sp == &spa[s]); 19487c478bd9Sstevel@tonic-gate } 19497c478bd9Sstevel@tonic-gate } else { 19507c478bd9Sstevel@tonic-gate /* 19517c478bd9Sstevel@tonic-gate * Couldn't find slab entry for given buf! 19527c478bd9Sstevel@tonic-gate */ 1953bf30efa4Smathue PR_SMR("%s: FAILED to free (bufp=0x%p) for domain %d\n", 1954*07d06da5SSurya Prakki proc, (void *)bufp, domid); 19557c478bd9Sstevel@tonic-gate } 19567c478bd9Sstevel@tonic-gate } 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate /* 19597c478bd9Sstevel@tonic-gate * The Reap Protocol: 19607c478bd9Sstevel@tonic-gate * master slave 19617c478bd9Sstevel@tonic-gate * ------ ----- 19627c478bd9Sstevel@tonic-gate * smr_slab_reap_global 19637c478bd9Sstevel@tonic-gate * - idn_broadcast_cmd(SLABREAP) -> idn_recv_cmd(SLABREAP) 19647c478bd9Sstevel@tonic-gate * . idn_local_cmd(SLABREAP) - idn_recv_slabreap_req 19657c478bd9Sstevel@tonic-gate * - smr_slab_reap . smr_slab_reap 19667c478bd9Sstevel@tonic-gate * . smr_slaballoc_get_n - smr_slaballoc_get_n 19677c478bd9Sstevel@tonic-gate * . smr_slab_free - smr_slab_free 19687c478bd9Sstevel@tonic-gate * - smr_slab_free_local . smr_slab_free_remote 19697c478bd9Sstevel@tonic-gate * . smr_slab_unreserve 19707c478bd9Sstevel@tonic-gate * <- - idn_send_cmd(SLABFREE) 19717c478bd9Sstevel@tonic-gate * idn_recv_cmd(SLABFREE) 19727c478bd9Sstevel@tonic-gate * - idn_recv_slabfree_req 19737c478bd9Sstevel@tonic-gate * . smr_slaballoc_get 19747c478bd9Sstevel@tonic-gate * . smr_slab_free 19757c478bd9Sstevel@tonic-gate * - smr_slab_free_local 19767c478bd9Sstevel@tonic-gate * . smr_slab_unreserve 19777c478bd9Sstevel@tonic-gate * . idn_send_slabfree_resp -> idn_recv_cmd(SLABFREE | ack) 19787c478bd9Sstevel@tonic-gate * - idn_recv_slabfree_resp 19797c478bd9Sstevel@tonic-gate * 19807c478bd9Sstevel@tonic-gate * idn_recv_cmd(SLABREAP | ack) <- . idn_send_slabreap_resp 19817c478bd9Sstevel@tonic-gate * - idn_recv_slabreap_resp DONE 19827c478bd9Sstevel@tonic-gate * DONE 19837c478bd9Sstevel@tonic-gate * 19847c478bd9Sstevel@tonic-gate * Check available slabs and if we're below the threshold, kick 19857c478bd9Sstevel@tonic-gate * off reaping to all remote domains. There is no guarantee remote 19867c478bd9Sstevel@tonic-gate * domains will be able to free up any. 19877c478bd9Sstevel@tonic-gate */ 19887c478bd9Sstevel@tonic-gate static void 19897c478bd9Sstevel@tonic-gate smr_slab_reap_global() 19907c478bd9Sstevel@tonic-gate { 19917c478bd9Sstevel@tonic-gate register int p, npools; 19927c478bd9Sstevel@tonic-gate register int total_free = 0; 19937c478bd9Sstevel@tonic-gate register struct smr_slabtbl *tblp; 19947c478bd9Sstevel@tonic-gate static clock_t reap_last = 0; 19957c478bd9Sstevel@tonic-gate procname_t proc = "smr_slab_reap_global"; 1996d3d50737SRafael Vanoni clock_t now; 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); 19997c478bd9Sstevel@tonic-gate 20007c478bd9Sstevel@tonic-gate DSLAB_LOCK_SHARED(idn.localid); 20017c478bd9Sstevel@tonic-gate if (idn_domain[idn.localid].dslab_state != DSLAB_STATE_LOCAL) { 20027c478bd9Sstevel@tonic-gate PR_SMR("%s: only allowed by master (%d)\n", 20037c478bd9Sstevel@tonic-gate proc, IDN_GET_MASTERID()); 20047c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(idn.localid); 20057c478bd9Sstevel@tonic-gate return; 20067c478bd9Sstevel@tonic-gate } 20077c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(idn.localid); 20087c478bd9Sstevel@tonic-gate 2009d3d50737SRafael Vanoni now = ddi_get_lbolt(); 2010d3d50737SRafael Vanoni if ((now > 0) && (now > reap_last) && 2011d3d50737SRafael Vanoni ((now - reap_last) < IDN_REAP_INTERVAL)) 20127c478bd9Sstevel@tonic-gate return; 20137c478bd9Sstevel@tonic-gate 2014d3d50737SRafael Vanoni reap_last = now; 20157c478bd9Sstevel@tonic-gate 20167c478bd9Sstevel@tonic-gate ASSERT(idn.slabpool); 20177c478bd9Sstevel@tonic-gate 20187c478bd9Sstevel@tonic-gate npools = idn.slabpool->npools; 20197c478bd9Sstevel@tonic-gate tblp = idn.slabpool->pool; 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate for (p = 0; p < npools; tblp++, p++) 20227c478bd9Sstevel@tonic-gate total_free += tblp->nfree; 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate if (total_free <= IDN_SLAB_THRESHOLD) { 20257c478bd9Sstevel@tonic-gate int diff, reap_per_domain; 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate PR_SMR("%s: kicking off reaping " 2028bf30efa4Smathue "(total_free = %d, min = %d)\n", 20297c478bd9Sstevel@tonic-gate proc, total_free, IDN_SLAB_THRESHOLD); 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate diff = IDN_SLAB_THRESHOLD - total_free; 2032d3d50737SRafael Vanoni reap_per_domain = (diff < idn.ndomains) ? 2033d3d50737SRafael Vanoni 1 : (diff / idn.ndomains); 20347c478bd9Sstevel@tonic-gate 20357c478bd9Sstevel@tonic-gate idn_broadcast_cmd(IDNCMD_SLABREAP, reap_per_domain, 0, 0); 20367c478bd9Sstevel@tonic-gate } 20377c478bd9Sstevel@tonic-gate } 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate void 20407c478bd9Sstevel@tonic-gate smr_slab_reap(int domid, int *nslabs) 20417c478bd9Sstevel@tonic-gate { 20427c478bd9Sstevel@tonic-gate register int d; 20437c478bd9Sstevel@tonic-gate int nreclaimed; 20447c478bd9Sstevel@tonic-gate smr_slab_t *sp; 20457c478bd9Sstevel@tonic-gate domainset_t reapset; 20467c478bd9Sstevel@tonic-gate procname_t proc = "smr_slab_reap"; 20477c478bd9Sstevel@tonic-gate 20487c478bd9Sstevel@tonic-gate /* 20497c478bd9Sstevel@tonic-gate * Should only be called on behalf of local 20507c478bd9Sstevel@tonic-gate * domain. 20517c478bd9Sstevel@tonic-gate */ 20527c478bd9Sstevel@tonic-gate if (domid != idn.localid) { 20537c478bd9Sstevel@tonic-gate PR_SMR("%s: called by domain %d, should only be local (%d)\n", 20547c478bd9Sstevel@tonic-gate proc, domid, idn.localid); 20557c478bd9Sstevel@tonic-gate ASSERT(0); 20567c478bd9Sstevel@tonic-gate return; 20577c478bd9Sstevel@tonic-gate } 20587c478bd9Sstevel@tonic-gate /* 20597c478bd9Sstevel@tonic-gate * Try and reclaim some buffers so we can possibly 20607c478bd9Sstevel@tonic-gate * free up some slabs. 20617c478bd9Sstevel@tonic-gate */ 20627c478bd9Sstevel@tonic-gate reapset = idn.domset.ds_connected; 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate IDN_GKSTAT_GLOBAL_EVENT(gk_reaps, gk_reap_last); 20657c478bd9Sstevel@tonic-gate 20667c478bd9Sstevel@tonic-gate nreclaimed = 0; 20677c478bd9Sstevel@tonic-gate for (d = 0; d < MAX_DOMAINS; d++) { 20687c478bd9Sstevel@tonic-gate int nr; 20697c478bd9Sstevel@tonic-gate idn_domain_t *dp; 20707c478bd9Sstevel@tonic-gate 20717c478bd9Sstevel@tonic-gate if (!DOMAIN_IN_SET(reapset, d)) 20727c478bd9Sstevel@tonic-gate continue; 20737c478bd9Sstevel@tonic-gate 20747c478bd9Sstevel@tonic-gate IDN_DLOCK_SHARED(d); 20757c478bd9Sstevel@tonic-gate 20767c478bd9Sstevel@tonic-gate dp = &idn_domain[d]; 20777c478bd9Sstevel@tonic-gate if ((d == idn.localid) || (dp->dcpu < 0)) { 20787c478bd9Sstevel@tonic-gate IDN_DUNLOCK(d); 20797c478bd9Sstevel@tonic-gate continue; 20807c478bd9Sstevel@tonic-gate } 20817c478bd9Sstevel@tonic-gate /* 20827c478bd9Sstevel@tonic-gate * Clean up any dead I/O errors if possible. 20837c478bd9Sstevel@tonic-gate */ 20847c478bd9Sstevel@tonic-gate if (dp->dioerr > 0) { 20857c478bd9Sstevel@tonic-gate idn_domain_t *ldp; 20867c478bd9Sstevel@tonic-gate register int cnt; 20877c478bd9Sstevel@tonic-gate register smr_slabbuf_t *bp; 20887c478bd9Sstevel@tonic-gate /* 20897c478bd9Sstevel@tonic-gate * We need to grab the writer lock to prevent 20907c478bd9Sstevel@tonic-gate * anybody from allocating buffers while we 20917c478bd9Sstevel@tonic-gate * traverse the slabs outstanding. 20927c478bd9Sstevel@tonic-gate */ 20937c478bd9Sstevel@tonic-gate cnt = 0; 20947c478bd9Sstevel@tonic-gate ldp = &idn_domain[idn.localid]; 20957c478bd9Sstevel@tonic-gate IDN_DLOCK_EXCL(idn.localid); 20967c478bd9Sstevel@tonic-gate DSLAB_LOCK_EXCL(idn.localid); 20977c478bd9Sstevel@tonic-gate for (sp = ldp->dslab; sp; sp = sp->sl_next) 20987c478bd9Sstevel@tonic-gate for (bp = sp->sl_inuse; bp; bp = bp->sb_next) 20997c478bd9Sstevel@tonic-gate if (bp->sb_domid == d) 21007c478bd9Sstevel@tonic-gate cnt++; 21017c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(idn.localid); 21027c478bd9Sstevel@tonic-gate ASSERT((dp->dio + dp->dioerr) >= cnt); 21037c478bd9Sstevel@tonic-gate dp->dio = cnt; 21047c478bd9Sstevel@tonic-gate dp->dioerr = 0; 21057c478bd9Sstevel@tonic-gate IDN_DUNLOCK(idn.localid); 21067c478bd9Sstevel@tonic-gate } 21077c478bd9Sstevel@tonic-gate if ((dp->dstate == IDNDS_CONNECTED) && 21087c478bd9Sstevel@tonic-gate ((nr = idn_reclaim_mboxdata(d, 0, -1)) > 0)) 21097c478bd9Sstevel@tonic-gate nreclaimed += nr; 21107c478bd9Sstevel@tonic-gate 21117c478bd9Sstevel@tonic-gate IDN_DUNLOCK(d); 21127c478bd9Sstevel@tonic-gate } 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate DSLAB_LOCK_EXCL(domid); 21157c478bd9Sstevel@tonic-gate sp = smr_slaballoc_get_n(domid, nslabs); 21167c478bd9Sstevel@tonic-gate if (sp) { 21177c478bd9Sstevel@tonic-gate IDN_GKSTAT_ADD(gk_reap_count, (ulong_t)(*nslabs)); 21187c478bd9Sstevel@tonic-gate smr_slab_free(domid, sp); 21197c478bd9Sstevel@tonic-gate } 21207c478bd9Sstevel@tonic-gate DSLAB_UNLOCK(domid); 21217c478bd9Sstevel@tonic-gate } 21227c478bd9Sstevel@tonic-gate 21237c478bd9Sstevel@tonic-gate /* 21247c478bd9Sstevel@tonic-gate * --------------------------------------------------------------------- 21257c478bd9Sstevel@tonic-gate * Remap the (IDN) shared memory region to a new physical address. 21267c478bd9Sstevel@tonic-gate * Caller is expected to have performed a ecache flush if needed. 21277c478bd9Sstevel@tonic-gate * --------------------------------------------------------------------- 21287c478bd9Sstevel@tonic-gate */ 21297c478bd9Sstevel@tonic-gate void 21307c478bd9Sstevel@tonic-gate smr_remap(struct as *as, register caddr_t vaddr, 21317c478bd9Sstevel@tonic-gate register pfn_t new_pfn, uint_t mblen) 21327c478bd9Sstevel@tonic-gate { 21337c478bd9Sstevel@tonic-gate tte_t tte; 21347c478bd9Sstevel@tonic-gate size_t blen; 21357c478bd9Sstevel@tonic-gate pgcnt_t p, npgs; 21367c478bd9Sstevel@tonic-gate procname_t proc = "smr_remap"; 21377c478bd9Sstevel@tonic-gate 21387c478bd9Sstevel@tonic-gate if (va_to_pfn(vaddr) == new_pfn) { 2139bf30efa4Smathue PR_REMAP("%s: vaddr (0x%p) already mapped to pfn (0x%lx)\n", 2140*07d06da5SSurya Prakki proc, (void *)vaddr, new_pfn); 21417c478bd9Sstevel@tonic-gate return; 21427c478bd9Sstevel@tonic-gate } 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate blen = MB2B(mblen); 21457c478bd9Sstevel@tonic-gate npgs = btopr(blen); 21467c478bd9Sstevel@tonic-gate ASSERT(npgs != 0); 21477c478bd9Sstevel@tonic-gate 2148bf30efa4Smathue PR_REMAP("%s: va = 0x%p, pfn = 0x%lx, npgs = %ld, mb = %d MB (%ld)\n", 2149*07d06da5SSurya Prakki proc, (void *)vaddr, new_pfn, npgs, mblen, blen); 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate /* 21527c478bd9Sstevel@tonic-gate * Unmap the SMR virtual address from it's current 21537c478bd9Sstevel@tonic-gate * mapping. 21547c478bd9Sstevel@tonic-gate */ 21557c478bd9Sstevel@tonic-gate hat_unload(as->a_hat, vaddr, blen, HAT_UNLOAD_UNLOCK); 21567c478bd9Sstevel@tonic-gate 21577c478bd9Sstevel@tonic-gate if (new_pfn == PFN_INVALID) 21587c478bd9Sstevel@tonic-gate return; 21597c478bd9Sstevel@tonic-gate 21607c478bd9Sstevel@tonic-gate /* 21617c478bd9Sstevel@tonic-gate * Map the SMR to the new physical address space, 21627c478bd9Sstevel@tonic-gate * presumably a remote pfn. Cannot use hat_devload 21637c478bd9Sstevel@tonic-gate * because it will think pfn represents non-memory, 21647c478bd9Sstevel@tonic-gate * i.e. space since it may beyond his physmax. 21657c478bd9Sstevel@tonic-gate */ 21667c478bd9Sstevel@tonic-gate for (p = 0; p < npgs; p++) { 2167d3d50737SRafael Vanoni sfmmu_memtte(&tte, new_pfn, PROT_READ | PROT_WRITE | HAT_NOSYNC, 21687c478bd9Sstevel@tonic-gate TTE8K); 21697c478bd9Sstevel@tonic-gate sfmmu_tteload(as->a_hat, &tte, vaddr, NULL, HAT_LOAD_LOCK); 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate vaddr += MMU_PAGESIZE; 21727c478bd9Sstevel@tonic-gate new_pfn++; 21737c478bd9Sstevel@tonic-gate } 21747c478bd9Sstevel@tonic-gate 21757c478bd9Sstevel@tonic-gate PR_REMAP("%s: remapped %ld pages (expected %ld)\n", 21767c478bd9Sstevel@tonic-gate proc, npgs, btopr(MB2B(mblen))); 21777c478bd9Sstevel@tonic-gate } 2178