1*0Sstevel@tonic-gate /*- 2*0Sstevel@tonic-gate * See the file LICENSE for redistribution information. 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * Copyright (c) 1996, 1997, 1998 5*0Sstevel@tonic-gate * Sleepycat Software. All rights reserved. 6*0Sstevel@tonic-gate */ 7*0Sstevel@tonic-gate /* 8*0Sstevel@tonic-gate * Copyright (c) 1995, 1996 9*0Sstevel@tonic-gate * The President and Fellows of Harvard University. All rights reserved. 10*0Sstevel@tonic-gate * 11*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 12*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 13*0Sstevel@tonic-gate * are met: 14*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 15*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 16*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 17*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 18*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 19*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 20*0Sstevel@tonic-gate * must display the following acknowledgement: 21*0Sstevel@tonic-gate * This product includes software developed by the University of 22*0Sstevel@tonic-gate * California, Berkeley and its contributors. 23*0Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 24*0Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 25*0Sstevel@tonic-gate * without specific prior written permission. 26*0Sstevel@tonic-gate * 27*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37*0Sstevel@tonic-gate * SUCH DAMAGE. 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #include "config.h" 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #ifndef lint 43*0Sstevel@tonic-gate static const char sccsid[] = "@(#)log_rec.c 10.26 (Sleepycat) 10/21/98"; 44*0Sstevel@tonic-gate #endif /* not lint */ 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES 47*0Sstevel@tonic-gate #include <sys/types.h> 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate #include <errno.h> 50*0Sstevel@tonic-gate #include <string.h> 51*0Sstevel@tonic-gate #endif 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #include "db_int.h" 54*0Sstevel@tonic-gate #include "shqueue.h" 55*0Sstevel@tonic-gate #include "log.h" 56*0Sstevel@tonic-gate #include "db_dispatch.h" 57*0Sstevel@tonic-gate #include "common_ext.h" 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate static int __log_do_open __P((DB_LOG *, 60*0Sstevel@tonic-gate u_int8_t *, char *, DBTYPE, u_int32_t)); 61*0Sstevel@tonic-gate static int __log_lid_to_fname __P((DB_LOG *, u_int32_t, FNAME **)); 62*0Sstevel@tonic-gate static int __log_open_file __P((DB_LOG *, __log_register_args *)); 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate /* 65*0Sstevel@tonic-gate * PUBLIC: int __log_register_recover 66*0Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 67*0Sstevel@tonic-gate */ 68*0Sstevel@tonic-gate int 69*0Sstevel@tonic-gate __log_register_recover(logp, dbtp, lsnp, redo, info) 70*0Sstevel@tonic-gate DB_LOG *logp; 71*0Sstevel@tonic-gate DBT *dbtp; 72*0Sstevel@tonic-gate DB_LSN *lsnp; 73*0Sstevel@tonic-gate int redo; 74*0Sstevel@tonic-gate void *info; 75*0Sstevel@tonic-gate { 76*0Sstevel@tonic-gate DB_ENTRY *dbe; 77*0Sstevel@tonic-gate __log_register_args *argp; 78*0Sstevel@tonic-gate int ret; 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate #ifdef DEBUG_RECOVER 81*0Sstevel@tonic-gate __log_register_print(logp, dbtp, lsnp, redo, info); 82*0Sstevel@tonic-gate #endif 83*0Sstevel@tonic-gate COMPQUIET(info, NULL); 84*0Sstevel@tonic-gate COMPQUIET(lsnp, NULL); 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate F_SET(logp, DBC_RECOVER); 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate if ((ret = __log_register_read(dbtp->data, &argp)) != 0) 89*0Sstevel@tonic-gate goto out; 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate if ((argp->opcode == LOG_CHECKPOINT && redo == TXN_OPENFILES) || 92*0Sstevel@tonic-gate (argp->opcode == LOG_OPEN && 93*0Sstevel@tonic-gate (redo == TXN_REDO || redo == TXN_OPENFILES || 94*0Sstevel@tonic-gate redo == TXN_FORWARD_ROLL)) || 95*0Sstevel@tonic-gate (argp->opcode == LOG_CLOSE && 96*0Sstevel@tonic-gate (redo == TXN_UNDO || redo == TXN_BACKWARD_ROLL))) { 97*0Sstevel@tonic-gate /* 98*0Sstevel@tonic-gate * If we are redoing an open or undoing a close, then we need 99*0Sstevel@tonic-gate * to open a file. 100*0Sstevel@tonic-gate */ 101*0Sstevel@tonic-gate ret = __log_open_file(logp, argp); 102*0Sstevel@tonic-gate if (ret == ENOENT) { 103*0Sstevel@tonic-gate if (redo == TXN_OPENFILES) 104*0Sstevel@tonic-gate __db_err(logp->dbenv, "warning: %s: %s", 105*0Sstevel@tonic-gate argp->name.data, strerror(ENOENT)); 106*0Sstevel@tonic-gate ret = 0; 107*0Sstevel@tonic-gate } 108*0Sstevel@tonic-gate } else if (argp->opcode != LOG_CHECKPOINT && 109*0Sstevel@tonic-gate argp->opcode != LOG_CLOSE) { 110*0Sstevel@tonic-gate /* 111*0Sstevel@tonic-gate * If we are undoing an open, then we need to close the file. 112*0Sstevel@tonic-gate * Note that we do *not* close the file if we are redoing a 113*0Sstevel@tonic-gate * close, because we do not log the reference counts on log 114*0Sstevel@tonic-gate * files and we may have had the file open multiple times, 115*0Sstevel@tonic-gate * and therefore, this close should just dec a reference 116*0Sstevel@tonic-gate * count. However, since we only do one open during a 117*0Sstevel@tonic-gate * checkpoint, this will inadvertently close the file. 118*0Sstevel@tonic-gate * 119*0Sstevel@tonic-gate * If the file is deleted, then we can just ignore this close. 120*0Sstevel@tonic-gate * Otherwise, we should usually have a valid dbp we should 121*0Sstevel@tonic-gate * close or whose reference count should be decremented. 122*0Sstevel@tonic-gate * However, if we shut down without closing a file, we 123*0Sstevel@tonic-gate * may, in fact, not have the file open, and that's OK. 124*0Sstevel@tonic-gate */ 125*0Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 126*0Sstevel@tonic-gate if (argp->id < logp->dbentry_cnt) { 127*0Sstevel@tonic-gate dbe = &logp->dbentry[argp->id]; 128*0Sstevel@tonic-gate if (dbe->dbp != NULL && --dbe->refcount == 0) { 129*0Sstevel@tonic-gate ret = dbe->dbp->close(dbe->dbp, 0); 130*0Sstevel@tonic-gate if (dbe->name != NULL) { 131*0Sstevel@tonic-gate __os_freestr(dbe->name); 132*0Sstevel@tonic-gate dbe->name = NULL; 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate (void)__log_rem_logid(logp, argp->id); 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate UNLOCK_LOGTHREAD(logp); 138*0Sstevel@tonic-gate } else if (argp->opcode == LOG_CHECKPOINT && redo == TXN_UNDO && 139*0Sstevel@tonic-gate (argp->id >= logp->dbentry_cnt || 140*0Sstevel@tonic-gate (!logp->dbentry[argp->id].deleted && 141*0Sstevel@tonic-gate logp->dbentry[argp->id].dbp == NULL))) { 142*0Sstevel@tonic-gate /* 143*0Sstevel@tonic-gate * It's a checkpoint and we are rolling backward. It 144*0Sstevel@tonic-gate * is possible that the system was shut down and thus 145*0Sstevel@tonic-gate * ended with a stable checkpoint; this file was never 146*0Sstevel@tonic-gate * closed and has therefore not been reopened yet. If 147*0Sstevel@tonic-gate * so, we need to try to open it. 148*0Sstevel@tonic-gate */ 149*0Sstevel@tonic-gate ret = __log_open_file(logp, argp); 150*0Sstevel@tonic-gate if (ret == ENOENT) { 151*0Sstevel@tonic-gate __db_err(logp->dbenv, "warning: %s: %s", 152*0Sstevel@tonic-gate argp->name.data, strerror(ENOENT)); 153*0Sstevel@tonic-gate ret = 0; 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate out: F_CLR(logp, DBC_RECOVER); 158*0Sstevel@tonic-gate if (argp != NULL) 159*0Sstevel@tonic-gate __os_free(argp, 0); 160*0Sstevel@tonic-gate return (ret); 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate /* Hand coded routines. */ 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate /* 166*0Sstevel@tonic-gate * Called during log_register recovery. Make sure that we have an 167*0Sstevel@tonic-gate * entry in the dbentry table for this ndx. 168*0Sstevel@tonic-gate * Returns 0 on success, non-zero on error. 169*0Sstevel@tonic-gate */ 170*0Sstevel@tonic-gate static int 171*0Sstevel@tonic-gate __log_open_file(lp, argp) 172*0Sstevel@tonic-gate DB_LOG *lp; 173*0Sstevel@tonic-gate __log_register_args *argp; 174*0Sstevel@tonic-gate { 175*0Sstevel@tonic-gate DB_ENTRY *dbe; 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate if (argp->name.size == 0) 178*0Sstevel@tonic-gate return(0); 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* 181*0Sstevel@tonic-gate * Because of reference counting, we cannot automatically close files 182*0Sstevel@tonic-gate * during recovery, so when we're opening, we have to check that the 183*0Sstevel@tonic-gate * name we are opening is what we expect. If it's not, then we close 184*0Sstevel@tonic-gate * the old file and open the new one. 185*0Sstevel@tonic-gate */ 186*0Sstevel@tonic-gate LOCK_LOGTHREAD(lp); 187*0Sstevel@tonic-gate if (argp->id < lp->dbentry_cnt) 188*0Sstevel@tonic-gate dbe = &lp->dbentry[argp->id]; 189*0Sstevel@tonic-gate else 190*0Sstevel@tonic-gate dbe = NULL; 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate if (dbe != NULL && (dbe->deleted == 1 || dbe->dbp != NULL) && 193*0Sstevel@tonic-gate dbe->name != NULL && argp->name.data != NULL && 194*0Sstevel@tonic-gate strncmp(argp->name.data, dbe->name, argp->name.size) == 0) { 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate dbe->refcount++; 197*0Sstevel@tonic-gate UNLOCK_LOGTHREAD(lp); 198*0Sstevel@tonic-gate return (0); 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate UNLOCK_LOGTHREAD(lp); 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate if (dbe != NULL && dbe->dbp != NULL) { 203*0Sstevel@tonic-gate (void)dbe->dbp->close(dbe->dbp, 0); 204*0Sstevel@tonic-gate if (dbe->name != NULL) 205*0Sstevel@tonic-gate __os_freestr(dbe->name); 206*0Sstevel@tonic-gate dbe->name = NULL; 207*0Sstevel@tonic-gate (void)__log_rem_logid(lp, argp->id); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate return (__log_do_open(lp, 212*0Sstevel@tonic-gate argp->uid.data, argp->name.data, argp->ftype, argp->id)); 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate /* 216*0Sstevel@tonic-gate * __log_do_open -- 217*0Sstevel@tonic-gate * Open files referenced in the log. This is the part of the open that 218*0Sstevel@tonic-gate * is not protected by the thread mutex. 219*0Sstevel@tonic-gate */ 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate static int 222*0Sstevel@tonic-gate __log_do_open(lp, uid, name, ftype, ndx) 223*0Sstevel@tonic-gate DB_LOG *lp; 224*0Sstevel@tonic-gate u_int8_t *uid; 225*0Sstevel@tonic-gate char *name; 226*0Sstevel@tonic-gate DBTYPE ftype; 227*0Sstevel@tonic-gate u_int32_t ndx; 228*0Sstevel@tonic-gate { 229*0Sstevel@tonic-gate DB *dbp; 230*0Sstevel@tonic-gate int ret; 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate dbp = NULL; 233*0Sstevel@tonic-gate if ((ret = db_open(name, ftype, 0, 0, lp->dbenv, NULL, &dbp)) == 0) { 234*0Sstevel@tonic-gate /* 235*0Sstevel@tonic-gate * Verify that we are opening the same file that we were 236*0Sstevel@tonic-gate * referring to when we wrote this log record. 237*0Sstevel@tonic-gate */ 238*0Sstevel@tonic-gate if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) { 239*0Sstevel@tonic-gate (void)dbp->close(dbp, 0); 240*0Sstevel@tonic-gate dbp = NULL; 241*0Sstevel@tonic-gate ret = ENOENT; 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate if (ret == 0 || ret == ENOENT) 246*0Sstevel@tonic-gate (void)__log_add_logid(lp, dbp, name, ndx); 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate return (ret); 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate /* 252*0Sstevel@tonic-gate * __log_add_logid -- 253*0Sstevel@tonic-gate * Adds a DB entry to the log's DB entry table. 254*0Sstevel@tonic-gate * 255*0Sstevel@tonic-gate * PUBLIC: int __log_add_logid __P((DB_LOG *, DB *, const char *, u_int32_t)); 256*0Sstevel@tonic-gate */ 257*0Sstevel@tonic-gate int 258*0Sstevel@tonic-gate __log_add_logid(logp, dbp, name, ndx) 259*0Sstevel@tonic-gate DB_LOG *logp; 260*0Sstevel@tonic-gate DB *dbp; 261*0Sstevel@tonic-gate const char *name; 262*0Sstevel@tonic-gate u_int32_t ndx; 263*0Sstevel@tonic-gate { 264*0Sstevel@tonic-gate u_int32_t i; 265*0Sstevel@tonic-gate int ret; 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate ret = 0; 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate /* 272*0Sstevel@tonic-gate * Check if we need to grow the table. Note, ndx is 0-based (the 273*0Sstevel@tonic-gate * index into the DB entry table) an dbentry_cnt is 1-based, the 274*0Sstevel@tonic-gate * number of available slots. 275*0Sstevel@tonic-gate */ 276*0Sstevel@tonic-gate if (logp->dbentry_cnt <= ndx) { 277*0Sstevel@tonic-gate if ((ret = __os_realloc(&logp->dbentry, 278*0Sstevel@tonic-gate (ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY))) != 0) 279*0Sstevel@tonic-gate goto err; 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate /* Initialize the new entries. */ 282*0Sstevel@tonic-gate for (i = logp->dbentry_cnt; i < ndx + DB_GROW_SIZE; i++) { 283*0Sstevel@tonic-gate logp->dbentry[i].dbp = NULL; 284*0Sstevel@tonic-gate logp->dbentry[i].deleted = 0; 285*0Sstevel@tonic-gate logp->dbentry[i].name = NULL; 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate logp->dbentry_cnt = i; 289*0Sstevel@tonic-gate } 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate /* Make space for the name and copy it in. */ 292*0Sstevel@tonic-gate if (name != NULL) { 293*0Sstevel@tonic-gate if ((ret = __os_malloc(strlen(name) + 1, 294*0Sstevel@tonic-gate NULL, &logp->dbentry[ndx].name)) != 0) 295*0Sstevel@tonic-gate goto err; 296*0Sstevel@tonic-gate strcpy(logp->dbentry[ndx].name, name); 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate if (logp->dbentry[ndx].deleted == 0 && logp->dbentry[ndx].dbp == NULL) { 300*0Sstevel@tonic-gate logp->dbentry[ndx].dbp = dbp; 301*0Sstevel@tonic-gate logp->dbentry[ndx].refcount = 1; 302*0Sstevel@tonic-gate logp->dbentry[ndx].deleted = dbp == NULL; 303*0Sstevel@tonic-gate } else 304*0Sstevel@tonic-gate logp->dbentry[ndx].refcount++; 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate err: UNLOCK_LOGTHREAD(logp); 308*0Sstevel@tonic-gate return (ret); 309*0Sstevel@tonic-gate } 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate /* 313*0Sstevel@tonic-gate * __db_fileid_to_db -- 314*0Sstevel@tonic-gate * Return the DB corresponding to the specified fileid. 315*0Sstevel@tonic-gate * 316*0Sstevel@tonic-gate * PUBLIC: int __db_fileid_to_db __P((DB_LOG *, DB **, u_int32_t)); 317*0Sstevel@tonic-gate */ 318*0Sstevel@tonic-gate int 319*0Sstevel@tonic-gate __db_fileid_to_db(logp, dbpp, ndx) 320*0Sstevel@tonic-gate DB_LOG *logp; 321*0Sstevel@tonic-gate DB **dbpp; 322*0Sstevel@tonic-gate u_int32_t ndx; 323*0Sstevel@tonic-gate { 324*0Sstevel@tonic-gate int ret; 325*0Sstevel@tonic-gate char *name; 326*0Sstevel@tonic-gate FNAME *fname; 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate ret = 0; 329*0Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate /* 332*0Sstevel@tonic-gate * Under XA, a process different than the one issuing DB 333*0Sstevel@tonic-gate * operations may abort a transaction. In this case, 334*0Sstevel@tonic-gate * recovery routines are run by a process that does not 335*0Sstevel@tonic-gate * necessarily have the file open. In this case, we must 336*0Sstevel@tonic-gate * open the file explicitly. 337*0Sstevel@tonic-gate */ 338*0Sstevel@tonic-gate if (ndx >= logp->dbentry_cnt || 339*0Sstevel@tonic-gate (!logp->dbentry[ndx].deleted && logp->dbentry[ndx].dbp == NULL)) { 340*0Sstevel@tonic-gate if (__log_lid_to_fname(logp, ndx, &fname) != 0) { 341*0Sstevel@tonic-gate /* Couldn't find entry; this is a fatal error. */ 342*0Sstevel@tonic-gate ret = EINVAL; 343*0Sstevel@tonic-gate goto err; 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate name = R_ADDR(logp, fname->name_off); 346*0Sstevel@tonic-gate /* 347*0Sstevel@tonic-gate * __log_do_open is called without protection of the 348*0Sstevel@tonic-gate * log thread lock. 349*0Sstevel@tonic-gate */ 350*0Sstevel@tonic-gate UNLOCK_LOGTHREAD(logp); 351*0Sstevel@tonic-gate /* 352*0Sstevel@tonic-gate * At this point, we are not holding the thread lock, so 353*0Sstevel@tonic-gate * exit directly instead of going through the exit code 354*0Sstevel@tonic-gate * at the bottom. If the __log_do_open succeeded, then 355*0Sstevel@tonic-gate * we don't need to do any of the remaining error checking 356*0Sstevel@tonic-gate * at the end of this routine. 357*0Sstevel@tonic-gate */ 358*0Sstevel@tonic-gate if ((ret = __log_do_open(logp, 359*0Sstevel@tonic-gate fname->ufid, name, fname->s_type, ndx)) != 0) 360*0Sstevel@tonic-gate return (ret); 361*0Sstevel@tonic-gate *dbpp = logp->dbentry[ndx].dbp; 362*0Sstevel@tonic-gate return (0); 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate /* 366*0Sstevel@tonic-gate * Return DB_DELETED if the file has been deleted 367*0Sstevel@tonic-gate * (it's not an error). 368*0Sstevel@tonic-gate */ 369*0Sstevel@tonic-gate if (logp->dbentry[ndx].deleted) { 370*0Sstevel@tonic-gate ret = DB_DELETED; 371*0Sstevel@tonic-gate goto err; 372*0Sstevel@tonic-gate } 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate /* 375*0Sstevel@tonic-gate * Otherwise return 0, but if we don't have a corresponding DB, 376*0Sstevel@tonic-gate * it's an error. 377*0Sstevel@tonic-gate */ 378*0Sstevel@tonic-gate if ((*dbpp = logp->dbentry[ndx].dbp) == NULL) 379*0Sstevel@tonic-gate ret = ENOENT; 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate err: UNLOCK_LOGTHREAD(logp); 382*0Sstevel@tonic-gate return (ret); 383*0Sstevel@tonic-gate } 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate /* 386*0Sstevel@tonic-gate * Close files that were opened by the recovery daemon. 387*0Sstevel@tonic-gate * 388*0Sstevel@tonic-gate * PUBLIC: void __log_close_files __P((DB_LOG *)); 389*0Sstevel@tonic-gate */ 390*0Sstevel@tonic-gate void 391*0Sstevel@tonic-gate __log_close_files(logp) 392*0Sstevel@tonic-gate DB_LOG *logp; 393*0Sstevel@tonic-gate { 394*0Sstevel@tonic-gate u_int32_t i; 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 397*0Sstevel@tonic-gate for (i = 0; i < logp->dbentry_cnt; i++) 398*0Sstevel@tonic-gate if (logp->dbentry[i].dbp) { 399*0Sstevel@tonic-gate logp->dbentry[i].dbp->close(logp->dbentry[i].dbp, 0); 400*0Sstevel@tonic-gate logp->dbentry[i].dbp = NULL; 401*0Sstevel@tonic-gate logp->dbentry[i].deleted = 0; 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate F_CLR(logp, DBC_RECOVER); 404*0Sstevel@tonic-gate UNLOCK_LOGTHREAD(logp); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate /* 408*0Sstevel@tonic-gate * PUBLIC: void __log_rem_logid __P((DB_LOG *, u_int32_t)); 409*0Sstevel@tonic-gate */ 410*0Sstevel@tonic-gate void 411*0Sstevel@tonic-gate __log_rem_logid(logp, ndx) 412*0Sstevel@tonic-gate DB_LOG *logp; 413*0Sstevel@tonic-gate u_int32_t ndx; 414*0Sstevel@tonic-gate { 415*0Sstevel@tonic-gate LOCK_LOGTHREAD(logp); 416*0Sstevel@tonic-gate if (--logp->dbentry[ndx].refcount == 0) { 417*0Sstevel@tonic-gate logp->dbentry[ndx].dbp = NULL; 418*0Sstevel@tonic-gate logp->dbentry[ndx].deleted = 0; 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate UNLOCK_LOGTHREAD(logp); 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate /* 424*0Sstevel@tonic-gate * __log_lid_to_fname -- 425*0Sstevel@tonic-gate * Traverse the shared-memory region looking for the entry that 426*0Sstevel@tonic-gate * matches the passed log fileid. Returns 0 on success; -1 on error. 427*0Sstevel@tonic-gate */ 428*0Sstevel@tonic-gate static int 429*0Sstevel@tonic-gate __log_lid_to_fname(dblp, lid, fnamep) 430*0Sstevel@tonic-gate DB_LOG *dblp; 431*0Sstevel@tonic-gate u_int32_t lid; 432*0Sstevel@tonic-gate FNAME **fnamep; 433*0Sstevel@tonic-gate { 434*0Sstevel@tonic-gate FNAME *fnp; 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname); 437*0Sstevel@tonic-gate fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) { 438*0Sstevel@tonic-gate if (fnp->ref == 0) /* Entry not in use. */ 439*0Sstevel@tonic-gate continue; 440*0Sstevel@tonic-gate if (fnp->id == lid) { 441*0Sstevel@tonic-gate *fnamep = fnp; 442*0Sstevel@tonic-gate return (0); 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate return (-1); 446*0Sstevel@tonic-gate } 447