1*7c478bd9Sstevel@tonic-gate /*- 2*7c478bd9Sstevel@tonic-gate * See the file LICENSE for redistribution information. 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 1996, 1997, 1998 5*7c478bd9Sstevel@tonic-gate * Sleepycat Software. All rights reserved. 6*7c478bd9Sstevel@tonic-gate */ 7*7c478bd9Sstevel@tonic-gate /* 8*7c478bd9Sstevel@tonic-gate * Copyright (c) 1990, 1993, 1994, 1995, 1996 9*7c478bd9Sstevel@tonic-gate * Keith Bostic. All rights reserved. 10*7c478bd9Sstevel@tonic-gate */ 11*7c478bd9Sstevel@tonic-gate /* 12*7c478bd9Sstevel@tonic-gate * Copyright (c) 1990, 1993, 1994, 1995 13*7c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 14*7c478bd9Sstevel@tonic-gate * 15*7c478bd9Sstevel@tonic-gate * This code is derived from software contributed to Berkeley by 16*7c478bd9Sstevel@tonic-gate * Mike Olson. 17*7c478bd9Sstevel@tonic-gate * 18*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 19*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 20*7c478bd9Sstevel@tonic-gate * are met: 21*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 22*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 23*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 24*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 25*7c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 26*7c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 27*7c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 28*7c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 29*7c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 30*7c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 31*7c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 32*7c478bd9Sstevel@tonic-gate * without specific prior written permission. 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 35*7c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37*7c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 38*7c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39*7c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40*7c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41*7c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42*7c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43*7c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44*7c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #include "config.h" 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #ifndef lint 50*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)bt_open.c 10.39 (Sleepycat) 11/21/98"; 51*7c478bd9Sstevel@tonic-gate #endif /* not lint */ 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES 54*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #include <errno.h> 57*7c478bd9Sstevel@tonic-gate #include <limits.h> 58*7c478bd9Sstevel@tonic-gate #include <string.h> 59*7c478bd9Sstevel@tonic-gate #endif 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #include "db_int.h" 62*7c478bd9Sstevel@tonic-gate #include "db_page.h" 63*7c478bd9Sstevel@tonic-gate #include "btree.h" 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * __bam_open -- 67*7c478bd9Sstevel@tonic-gate * Open a btree. 68*7c478bd9Sstevel@tonic-gate * 69*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_open __P((DB *, DB_INFO *)); 70*7c478bd9Sstevel@tonic-gate */ 71*7c478bd9Sstevel@tonic-gate int 72*7c478bd9Sstevel@tonic-gate __bam_open(dbp, dbinfo) 73*7c478bd9Sstevel@tonic-gate DB *dbp; 74*7c478bd9Sstevel@tonic-gate DB_INFO *dbinfo; 75*7c478bd9Sstevel@tonic-gate { 76*7c478bd9Sstevel@tonic-gate BTREE *t; 77*7c478bd9Sstevel@tonic-gate int ret; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate /* Allocate and initialize the private btree structure. */ 80*7c478bd9Sstevel@tonic-gate if ((ret = __os_calloc(1, sizeof(BTREE), &t)) != 0) 81*7c478bd9Sstevel@tonic-gate return (ret); 82*7c478bd9Sstevel@tonic-gate dbp->internal = t; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate /* 85*7c478bd9Sstevel@tonic-gate * Intention is to make sure all of the user's selections are okay 86*7c478bd9Sstevel@tonic-gate * here and then use them without checking. 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate if (dbinfo == NULL) { 89*7c478bd9Sstevel@tonic-gate t->bt_minkey = DEFMINKEYPAGE; 90*7c478bd9Sstevel@tonic-gate t->bt_compare = __bam_defcmp; 91*7c478bd9Sstevel@tonic-gate t->bt_prefix = __bam_defpfx; 92*7c478bd9Sstevel@tonic-gate } else { 93*7c478bd9Sstevel@tonic-gate /* Minimum number of keys per page. */ 94*7c478bd9Sstevel@tonic-gate if (dbinfo->bt_minkey == 0) 95*7c478bd9Sstevel@tonic-gate t->bt_minkey = DEFMINKEYPAGE; 96*7c478bd9Sstevel@tonic-gate else { 97*7c478bd9Sstevel@tonic-gate if (dbinfo->bt_minkey < 2) 98*7c478bd9Sstevel@tonic-gate goto einval; 99*7c478bd9Sstevel@tonic-gate t->bt_minkey = dbinfo->bt_minkey; 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate /* Maximum number of keys per page. */ 103*7c478bd9Sstevel@tonic-gate if (dbinfo->bt_maxkey == 0) 104*7c478bd9Sstevel@tonic-gate t->bt_maxkey = 0; 105*7c478bd9Sstevel@tonic-gate else { 106*7c478bd9Sstevel@tonic-gate if (dbinfo->bt_maxkey < 1) 107*7c478bd9Sstevel@tonic-gate goto einval; 108*7c478bd9Sstevel@tonic-gate t->bt_maxkey = dbinfo->bt_maxkey; 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* 112*7c478bd9Sstevel@tonic-gate * If no comparison, use default comparison. If no comparison 113*7c478bd9Sstevel@tonic-gate * and no prefix, use default prefix. (We can't default the 114*7c478bd9Sstevel@tonic-gate * prefix if the user supplies a comparison routine; shortening 115*7c478bd9Sstevel@tonic-gate * the keys may break their comparison algorithm. We don't 116*7c478bd9Sstevel@tonic-gate * permit the user to specify a prefix routine if they didn't 117*7c478bd9Sstevel@tonic-gate * also specify a comparison routine, they can't know enough 118*7c478bd9Sstevel@tonic-gate * about our comparison routine to get it right.) 119*7c478bd9Sstevel@tonic-gate */ 120*7c478bd9Sstevel@tonic-gate if ((t->bt_compare = dbinfo->bt_compare) == NULL) { 121*7c478bd9Sstevel@tonic-gate if (dbinfo->bt_prefix != NULL) 122*7c478bd9Sstevel@tonic-gate goto einval; 123*7c478bd9Sstevel@tonic-gate t->bt_compare = __bam_defcmp; 124*7c478bd9Sstevel@tonic-gate t->bt_prefix = __bam_defpfx; 125*7c478bd9Sstevel@tonic-gate } else 126*7c478bd9Sstevel@tonic-gate t->bt_prefix = dbinfo->bt_prefix; 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate /* Initialize the remaining fields/methods of the DB. */ 130*7c478bd9Sstevel@tonic-gate dbp->am_close = __bam_close; 131*7c478bd9Sstevel@tonic-gate dbp->del = __bam_delete; 132*7c478bd9Sstevel@tonic-gate dbp->stat = __bam_stat; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate /* Start up the tree. */ 135*7c478bd9Sstevel@tonic-gate if ((ret = __bam_read_root(dbp)) != 0) 136*7c478bd9Sstevel@tonic-gate goto err; 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* Set the overflow page size. */ 139*7c478bd9Sstevel@tonic-gate __bam_setovflsize(dbp); 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate return (0); 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate einval: ret = EINVAL; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate err: __os_free(t, sizeof(BTREE)); 146*7c478bd9Sstevel@tonic-gate return (ret); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate /* 150*7c478bd9Sstevel@tonic-gate * __bam_close -- 151*7c478bd9Sstevel@tonic-gate * Close a btree. 152*7c478bd9Sstevel@tonic-gate * 153*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_close __P((DB *)); 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate int 156*7c478bd9Sstevel@tonic-gate __bam_close(dbp) 157*7c478bd9Sstevel@tonic-gate DB *dbp; 158*7c478bd9Sstevel@tonic-gate { 159*7c478bd9Sstevel@tonic-gate __os_free(dbp->internal, sizeof(BTREE)); 160*7c478bd9Sstevel@tonic-gate dbp->internal = NULL; 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate return (0); 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * __bam_setovflsize -- 167*7c478bd9Sstevel@tonic-gate * 168*7c478bd9Sstevel@tonic-gate * PUBLIC: void __bam_setovflsize __P((DB *)); 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate void 171*7c478bd9Sstevel@tonic-gate __bam_setovflsize(dbp) 172*7c478bd9Sstevel@tonic-gate DB *dbp; 173*7c478bd9Sstevel@tonic-gate { 174*7c478bd9Sstevel@tonic-gate BTREE *t; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate t = dbp->internal; 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate /* 179*7c478bd9Sstevel@tonic-gate * !!! 180*7c478bd9Sstevel@tonic-gate * Correction for recno, which doesn't know anything about minimum 181*7c478bd9Sstevel@tonic-gate * keys per page. 182*7c478bd9Sstevel@tonic-gate */ 183*7c478bd9Sstevel@tonic-gate if (t->bt_minkey == 0) 184*7c478bd9Sstevel@tonic-gate t->bt_minkey = DEFMINKEYPAGE; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * The btree data structure requires that at least two key/data pairs 188*7c478bd9Sstevel@tonic-gate * can fit on a page, but other than that there's no fixed requirement. 189*7c478bd9Sstevel@tonic-gate * Translate the minimum number of items into the bytes a key/data pair 190*7c478bd9Sstevel@tonic-gate * can use before being placed on an overflow page. We calculate for 191*7c478bd9Sstevel@tonic-gate * the worst possible alignment by assuming every item requires the 192*7c478bd9Sstevel@tonic-gate * maximum alignment for padding. 193*7c478bd9Sstevel@tonic-gate * 194*7c478bd9Sstevel@tonic-gate * Recno uses the btree bt_ovflsize value -- it's close enough. 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate t->bt_ovflsize = (dbp->pgsize - P_OVERHEAD) / (t->bt_minkey * P_INDX) 197*7c478bd9Sstevel@tonic-gate - (BKEYDATA_PSIZE(0) + ALIGN(1, 4)); 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate /* 201*7c478bd9Sstevel@tonic-gate * __bam_read_root -- 202*7c478bd9Sstevel@tonic-gate * Check (and optionally create) a tree. 203*7c478bd9Sstevel@tonic-gate * 204*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_read_root __P((DB *)); 205*7c478bd9Sstevel@tonic-gate */ 206*7c478bd9Sstevel@tonic-gate int 207*7c478bd9Sstevel@tonic-gate __bam_read_root(dbp) 208*7c478bd9Sstevel@tonic-gate DB *dbp; 209*7c478bd9Sstevel@tonic-gate { 210*7c478bd9Sstevel@tonic-gate BTMETA *meta; 211*7c478bd9Sstevel@tonic-gate BTREE *t; 212*7c478bd9Sstevel@tonic-gate DBC *dbc; 213*7c478bd9Sstevel@tonic-gate DB_LOCK metalock, rootlock; 214*7c478bd9Sstevel@tonic-gate PAGE *root; 215*7c478bd9Sstevel@tonic-gate db_pgno_t pgno; 216*7c478bd9Sstevel@tonic-gate int ret, t_ret; 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate ret = 0; 219*7c478bd9Sstevel@tonic-gate t = dbp->internal; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate /* Get a cursor. */ 222*7c478bd9Sstevel@tonic-gate if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) 223*7c478bd9Sstevel@tonic-gate return (ret); 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* Get, and optionally create the metadata page. */ 226*7c478bd9Sstevel@tonic-gate pgno = PGNO_METADATA; 227*7c478bd9Sstevel@tonic-gate if ((ret = 228*7c478bd9Sstevel@tonic-gate __bam_lget(dbc, 0, PGNO_METADATA, DB_LOCK_WRITE, &metalock)) != 0) 229*7c478bd9Sstevel@tonic-gate goto err; 230*7c478bd9Sstevel@tonic-gate if ((ret = 231*7c478bd9Sstevel@tonic-gate memp_fget(dbp->mpf, &pgno, DB_MPOOL_CREATE, (PAGE **)&meta)) != 0) { 232*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, metalock); 233*7c478bd9Sstevel@tonic-gate goto err; 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * If the magic number is correct, we're not creating the tree. 238*7c478bd9Sstevel@tonic-gate * Correct any fields that may not be right. Note, all of the 239*7c478bd9Sstevel@tonic-gate * local flags were set by db_open(3). 240*7c478bd9Sstevel@tonic-gate */ 241*7c478bd9Sstevel@tonic-gate if (meta->magic != 0) { 242*7c478bd9Sstevel@tonic-gate t->bt_maxkey = meta->maxkey; 243*7c478bd9Sstevel@tonic-gate t->bt_minkey = meta->minkey; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, (PAGE *)meta, 0); 246*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, metalock); 247*7c478bd9Sstevel@tonic-gate goto done; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate /* Initialize the tree structure metadata information. */ 251*7c478bd9Sstevel@tonic-gate memset(meta, 0, sizeof(BTMETA)); 252*7c478bd9Sstevel@tonic-gate ZERO_LSN(meta->lsn); 253*7c478bd9Sstevel@tonic-gate meta->pgno = PGNO_METADATA; 254*7c478bd9Sstevel@tonic-gate meta->magic = DB_BTREEMAGIC; 255*7c478bd9Sstevel@tonic-gate meta->version = DB_BTREEVERSION; 256*7c478bd9Sstevel@tonic-gate meta->pagesize = dbp->pgsize; 257*7c478bd9Sstevel@tonic-gate meta->maxkey = t->bt_maxkey; 258*7c478bd9Sstevel@tonic-gate meta->minkey = t->bt_minkey; 259*7c478bd9Sstevel@tonic-gate meta->free = PGNO_INVALID; 260*7c478bd9Sstevel@tonic-gate if (dbp->type == DB_RECNO) 261*7c478bd9Sstevel@tonic-gate F_SET(meta, BTM_RECNO); 262*7c478bd9Sstevel@tonic-gate if (F_ISSET(dbp, DB_AM_DUP)) 263*7c478bd9Sstevel@tonic-gate F_SET(meta, BTM_DUP); 264*7c478bd9Sstevel@tonic-gate if (F_ISSET(dbp, DB_RE_FIXEDLEN)) 265*7c478bd9Sstevel@tonic-gate F_SET(meta, BTM_FIXEDLEN); 266*7c478bd9Sstevel@tonic-gate if (F_ISSET(dbp, DB_BT_RECNUM)) 267*7c478bd9Sstevel@tonic-gate F_SET(meta, BTM_RECNUM); 268*7c478bd9Sstevel@tonic-gate if (F_ISSET(dbp, DB_RE_RENUMBER)) 269*7c478bd9Sstevel@tonic-gate F_SET(meta, BTM_RENUMBER); 270*7c478bd9Sstevel@tonic-gate memcpy(meta->uid, dbp->fileid, DB_FILE_ID_LEN); 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* Create and initialize a root page. */ 273*7c478bd9Sstevel@tonic-gate pgno = PGNO_ROOT; 274*7c478bd9Sstevel@tonic-gate if ((ret = 275*7c478bd9Sstevel@tonic-gate __bam_lget(dbc, 0, PGNO_ROOT, DB_LOCK_WRITE, &rootlock)) != 0) 276*7c478bd9Sstevel@tonic-gate goto err; 277*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &pgno, DB_MPOOL_CREATE, &root)) != 0) { 278*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, rootlock); 279*7c478bd9Sstevel@tonic-gate goto err; 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate P_INIT(root, dbp->pgsize, PGNO_ROOT, PGNO_INVALID, 282*7c478bd9Sstevel@tonic-gate PGNO_INVALID, 1, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE); 283*7c478bd9Sstevel@tonic-gate ZERO_LSN(root->lsn); 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* Release the metadata and root pages. */ 286*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0) 287*7c478bd9Sstevel@tonic-gate goto err; 288*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(dbp->mpf, root, DB_MPOOL_DIRTY)) != 0) 289*7c478bd9Sstevel@tonic-gate goto err; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate /* 292*7c478bd9Sstevel@tonic-gate * Flush the metadata and root pages to disk -- since the user can't 293*7c478bd9Sstevel@tonic-gate * transaction protect open, the pages have to exist during recovery. 294*7c478bd9Sstevel@tonic-gate * 295*7c478bd9Sstevel@tonic-gate * XXX 296*7c478bd9Sstevel@tonic-gate * It's not useful to return not-yet-flushed here -- convert it to 297*7c478bd9Sstevel@tonic-gate * an error. 298*7c478bd9Sstevel@tonic-gate */ 299*7c478bd9Sstevel@tonic-gate if ((ret = memp_fsync(dbp->mpf)) == DB_INCOMPLETE) 300*7c478bd9Sstevel@tonic-gate ret = EINVAL; 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate /* Release the locks. */ 303*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, metalock); 304*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, rootlock); 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate err: 307*7c478bd9Sstevel@tonic-gate done: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) 308*7c478bd9Sstevel@tonic-gate ret = t_ret; 309*7c478bd9Sstevel@tonic-gate return (ret); 310*7c478bd9Sstevel@tonic-gate } 311