Home | History | Annotate | Download | only in rpc.metamedd
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include "med_local.h"
     27 #include "med_hash.h"
     28 #include <sys/lvm/mdio.h>
     29 #include <sys/lvm/md_mdiox.h>
     30 #include <sys/lvm/md_crc.h>
     31 
     32 static	int		med_db_is_inited = 0;
     33 static	Cache		*med_db_cache = (Cache *) NULL;
     34 static	med_rec_t	*med_db_medrp = NULL;
     35 static	int		med_db_nma = 0;
     36 static	int		med_db_nmu = 0;
     37 static	int		rec_size = roundup(sizeof (med_rec_t), DEV_BSIZE);
     38 static	char 		*rec_buf = NULL;
     39 static	int		dbfd = -1;
     40 
     41 #define		OP_FLAGS	(O_RDWR | O_SYNC)
     42 #define		CR_FLAGS	(OP_FLAGS | O_CREAT)
     43 
     44 #define	HASHSIZE	151
     45 #define	BSZ		4
     46 
     47 #ifdef DEBUG
     48 void
     49 med_pr(void *keyp, int keyl, void *datap, int datal)
     50 {
     51 	med_med_t	*medp = (med_med_t *)keyp;
     52 	int		medridx = *(int *)datap;
     53 	med_rec_t	*medrp = &med_db_medrp[medridx];
     54 
     55 	med_eprintf(
     56 	    "key (%d)[keyp=0x%08x]: setno=%ld, setname=<%s>, caller=<%s>\n",
     57 	    keyl, (unsigned)keyp, medp->med_setno, medp->med_setname,
     58 	    medp->med_caller);
     59 	med_eprintf("data(%d)[datap=0x%x08][medrp=0x%x08]: medridx=%d\n",
     60 	    datal, (unsigned)datap, (unsigned)medrp, medridx);
     61 }
     62 #endif	/* DEBUG */
     63 
     64 static int
     65 med_hash(void *datap, int datalen, int hsz)
     66 {
     67 	med_med_t	*medp = (med_med_t *)datap;
     68 	int		i = datalen;
     69 	char		*cp;
     70 
     71 	i = 0;
     72 	cp = medp->med_setname;
     73 	while (*cp != '\0')
     74 		i += *cp++;
     75 
     76 	cp = medp->med_caller;
     77 	while (*cp != '\0')
     78 		i += *cp++;
     79 
     80 	i *= medp->med_setno;
     81 
     82 	return (i % hsz);
     83 }
     84 
     85 /*ARGSUSED*/
     86 static int
     87 med_comp(void *datap1, void *datap2, int datalen)
     88 {
     89 	med_med_t	*medp1 = (med_med_t *)datap1;
     90 	med_med_t	*medp2 = (med_med_t *)datap2;
     91 	int		ret;
     92 
     93 
     94 	ret = medp1->med_setno - medp2->med_setno;
     95 
     96 	if (ret != 0)
     97 		return (ret);
     98 
     99 	ret = strcmp(medp1->med_caller, medp2->med_caller);
    100 
    101 	if (ret != 0)
    102 		return (ret);
    103 
    104 	return (strcmp(medp1->med_setname, medp2->med_setname));
    105 }
    106 
    107 static void
    108 med_kfree(void *keyp)
    109 {
    110 	med_med_t	*medp = (med_med_t *)keyp;
    111 
    112 	(void) Free(medp->med_caller);
    113 	(void) Free(medp->med_setname);
    114 	(void) Free(keyp);
    115 }
    116 
    117 static int
    118 add_key(med_med_t *medp, int medridx)
    119 {
    120 	Item		*itemp;
    121 	int		len;
    122 	med_med_t	*tmedp;
    123 
    124 	if (med_db_cache == (Cache *) NULL) {
    125 		len = init_cache(&med_db_cache, HASHSIZE, BSZ, med_hash,
    126 		    med_comp, med_kfree, (void (*)())NULL);
    127 		if (len == -1) {
    128 			med_eprintf("add_key(): init_cache() failed.\n");
    129 			return (-1);
    130 		}
    131 	}
    132 
    133 	len = sizeof (med_med_t);
    134 
    135 	if ((itemp = lookup_cache(med_db_cache, medp, len)) == Null_Item) {
    136 		if ((itemp = (Item *) Malloc(sizeof (*itemp))) == NULL) {
    137 			med_eprintf("add_key(): itemp = Malloc(%d)\n",
    138 			    sizeof (*itemp));
    139 			return (-1);
    140 		}
    141 		if ((tmedp = itemp->key = Malloc(len)) == NULL) {
    142 			med_eprintf("add_key(): itemp->key = Malloc(%d)\n",
    143 			    len);
    144 			return (-1);
    145 		}
    146 
    147 		*tmedp = *medp;			/* structure assignment */
    148 
    149 		tmedp->med_caller = Malloc(strlen(medp->med_caller) + 1);
    150 		if (tmedp->med_caller == NULL) {
    151 			med_eprintf(
    152 			    "add_key(): tmedp->med_caller = Malloc(%d)\n",
    153 			    strlen(medp->med_caller) + 1);
    154 			return (-1);
    155 		}
    156 		(void) strcpy(tmedp->med_caller, medp->med_caller);
    157 
    158 		tmedp->med_setname = Malloc(strlen(medp->med_setname) + 1);
    159 		if (tmedp->med_setname == NULL) {
    160 			med_eprintf(
    161 			    "add_key(): tmedp->med_setname = Malloc(%d)\n",
    162 			    strlen(medp->med_setname) + 1);
    163 			return (-1);
    164 		}
    165 		(void) strcpy(tmedp->med_setname, medp->med_setname);
    166 
    167 		itemp->keyl = len;
    168 
    169 		if ((itemp->data = Malloc(sizeof (int))) == NULL) {
    170 			med_eprintf("add_key(): itemp->data = Malloc(%d)\n",
    171 			    sizeof (med_rec_t *));
    172 			return (-1);
    173 		}
    174 
    175 		*(int *)itemp->data = medridx;
    176 
    177 		itemp->datal = sizeof (int);
    178 
    179 		if (add_cache(med_db_cache, itemp) == -1) {
    180 			med_eprintf("add_key(): add_cache() failed.\n");
    181 			return (-1);
    182 		}
    183 		return (0);
    184 	}
    185 	return (1);
    186 }
    187 
    188 static int
    189 del_key(med_med_t *medp)
    190 {
    191 	Item		*itemp;
    192 	int		len;
    193 
    194 	if (med_db_cache == (Cache *) NULL)
    195 		return (0);
    196 
    197 	len = sizeof (med_med_t);
    198 
    199 	if ((itemp = lookup_cache(med_db_cache, medp, len)) == Null_Item)
    200 		return (0);
    201 
    202 	(void) del_cache(med_db_cache, itemp);
    203 
    204 	return (0);
    205 }
    206 
    207 static int
    208 find_key(med_med_t *medp)
    209 {
    210 	Item		*itemp;
    211 	int		len;
    212 
    213 	if (med_db_cache == (Cache *) NULL)
    214 		return (-1);
    215 
    216 	len = sizeof (med_med_t);
    217 
    218 	if ((itemp = lookup_cache(med_db_cache, medp, len)) == Null_Item)
    219 		return (-1);
    220 
    221 	return (*(int *)itemp->data);
    222 }
    223 
    224 static int
    225 add_db_keys(int medridx, med_err_t *medep)
    226 {
    227 	med_med_t	med;
    228 	med_rec_t	*medrp;
    229 	int		i;
    230 
    231 	medrp = &med_db_medrp[medridx];
    232 	med.med_setno = medrp->med_rec_sn;
    233 	med.med_setname = medrp->med_rec_snm;
    234 
    235 	for (i = 0; i < MD_MAXSIDES; i++) {
    236 		if (medrp->med_rec_nodes[i][0] == '\0')
    237 			continue;
    238 		med.med_caller  = medrp->med_rec_nodes[i];
    239 		if (add_key(&med, medridx) == -1)
    240 			return (med_error(medep, MDE_MED_DBKEYADDFAIL,
    241 			    medrp->med_rec_nodes[i]));
    242 	}
    243 
    244 	/*
    245 	 * Looping through the actual list of mediator hosts
    246 	 * because a mediator host may not actually be a host
    247 	 * in the diskset and so access for such a host needs
    248 	 * to be added.
    249 	 */
    250 	for (i = 0; i < MED_MAX_HOSTS; i++) {
    251 		if ((medrp->med_rec_meds.n_cnt > 0) &&
    252 		    (medrp->med_rec_meds.n_lst[i].a_cnt != 0)) {
    253 			med.med_caller  =
    254 			    medrp->med_rec_meds.n_lst[i].a_nm[0];
    255 			if (add_key(&med, medridx) == -1)
    256 				return (med_error(medep, MDE_MED_DBKEYADDFAIL,
    257 				    medrp->med_rec_meds.n_lst[i].a_nm[0]));
    258 		}
    259 	}
    260 	return (0);
    261 }
    262 
    263 static int
    264 del_db_keys(int medridx, med_err_t *medep)
    265 {
    266 	med_med_t	med;
    267 	med_rec_t	*medrp;
    268 	int		i;
    269 
    270 	medrp = &med_db_medrp[medridx];
    271 	med.med_setno = medrp->med_rec_sn;
    272 	med.med_setname = medrp->med_rec_snm;
    273 
    274 	for (i = 0; i < MD_MAXSIDES; i++) {
    275 		if (medrp->med_rec_nodes[i][0] == '\0')
    276 			continue;
    277 		med.med_caller  = medrp->med_rec_nodes[i];
    278 		if (del_key(&med) == -1)
    279 			return (med_error(medep, MDE_MED_DBKEYDELFAIL,
    280 			    medrp->med_rec_nodes[i]));
    281 	}
    282 
    283 	for (i = 0; i < MED_MAX_HOSTS; i++) {
    284 		if ((medrp->med_rec_meds.n_cnt > 0) &&
    285 		    (medrp->med_rec_meds.n_lst[i].a_cnt != 0)) {
    286 			med.med_caller  =
    287 			    medrp->med_rec_meds.n_lst[i].a_nm[0];
    288 			if (del_key(&med) == -1)
    289 				return (med_error(medep, MDE_MED_DBKEYDELFAIL,
    290 				    medrp->med_rec_meds.n_lst[i].a_nm[0]));
    291 		}
    292 	}
    293 	return (0);
    294 }
    295 
    296 static int
    297 alloc_rec_buf(med_err_t *medep)
    298 {
    299 	if (rec_buf == NULL) {
    300 		if ((rec_buf = Malloc(rec_size)) == NULL)
    301 			return (med_error(medep, errno,
    302 			    "alloc_rec_buf: Malloc()"));
    303 	}
    304 
    305 	(void) memset(rec_buf, '\0', rec_size);
    306 	return (0);
    307 }
    308 
    309 static void
    310 free_rec_buf(void)
    311 {
    312 	if (rec_buf == NULL)
    313 		return;
    314 
    315 	Free(rec_buf);
    316 	rec_buf = NULL;
    317 }
    318 
    319 static int
    320 write_hdr(
    321 	int		dbfd,
    322 	med_err_t	*medep
    323 )
    324 {
    325 	med_db_hdr_t	dbh;
    326 
    327 	if (alloc_rec_buf(medep))
    328 		return (-1);
    329 
    330 	(void) memset(&dbh, '\0', sizeof (med_db_hdr_t));
    331 
    332 	/* Setup the new hdr record */
    333 	dbh.med_dbh_mag = MED_DB_MAGIC;
    334 	dbh.med_dbh_rev = MED_DB_REV;
    335 	dbh.med_dbh_nm = med_db_nmu;
    336 
    337 	/* Checksum new header */
    338 	crcgen(&dbh, &dbh.med_dbh_cks, sizeof (med_db_hdr_t), NULL);
    339 
    340 	/* Position to the beginning of the file */
    341 	if (lseek(dbfd, 0, SEEK_SET) == -1)
    342 		return (med_error(medep, errno, "write_hdr: lseek()"));
    343 
    344 	/* Copy the header into the output buffer */
    345 	(void) memmove(rec_buf, &dbh, sizeof (med_db_hdr_t));
    346 
    347 	/* Write out the header */
    348 	if (write(dbfd, rec_buf, rec_size) == -1)
    349 		return (med_error(medep, errno, "write_hdr: write()"));
    350 
    351 	return (0);
    352 }
    353 
    354 static int
    355 write_rec(
    356 	int		dbfd,
    357 	med_rec_t	*medrp,
    358 	med_err_t	*medep
    359 )
    360 {
    361 	uint_t		save_flags = 0;
    362 	uint_t		save_cks = 0;
    363 
    364 	if (alloc_rec_buf(medep))
    365 		return (-1);
    366 
    367 	if (medrp->med_rec_data.med_dat_fl) {
    368 		save_flags = medrp->med_rec_data.med_dat_fl;
    369 		save_cks = medrp->med_rec_data.med_dat_cks;
    370 		medrp->med_rec_data.med_dat_fl = 0;
    371 		/* Checksum the new data */
    372 		crcgen(&medrp->med_rec_data, &medrp->med_rec_data.med_dat_cks,
    373 		    sizeof (med_data_t), NULL);
    374 	}
    375 
    376 	/* Checksum record */
    377 	crcgen(medrp, &medrp->med_rec_cks, sizeof (med_rec_t), NULL);
    378 
    379 	/* Load the record into the output buffer */
    380 	(void) memmove(rec_buf, medrp, sizeof (med_rec_t));
    381 
    382 	if (save_flags) {
    383 		medrp->med_rec_data.med_dat_fl = save_flags;
    384 		medrp->med_rec_data.med_dat_cks = save_cks;
    385 		/* Re-checksum the updated record */
    386 		crcgen(medrp, &medrp->med_rec_cks, sizeof (med_rec_t), NULL);
    387 	}
    388 
    389 	/* Write out the record */
    390 	if (write(dbfd, rec_buf, rec_size) == -1)
    391 		return (med_error(medep, errno, "write_rec: write()"));
    392 
    393 	return (0);
    394 }
    395 
    396 static int
    397 open_dbfile(med_err_t *medep)
    398 {
    399 	if (dbfd != -1)
    400 		return (0);
    401 
    402 	/* Open the database file */
    403 	if ((dbfd = open(MED_DB_FILE, OP_FLAGS, 0644)) == -1) {
    404 		if (errno != ENOENT)
    405 			return (med_error(medep, errno, "open_dbfile: open()"));
    406 
    407 		if ((dbfd = open(MED_DB_FILE, CR_FLAGS, 0644)) == -1)
    408 			return (med_error(medep, errno,
    409 			    "open_dbfile: open(create)"));
    410 	}
    411 
    412 	/* Try to take an advisory lock on the file */
    413 	if (lockf(dbfd, F_TLOCK, (off_t)0) == -1) {
    414 		(void) med_error(medep, errno, "open_dbfile: lockf(F_TLOCK)");
    415 		medde_perror(medep, "");
    416 		med_exit(1);
    417 	}
    418 
    419 	return (0);
    420 }
    421 
    422 static int
    423 close_dbfile(med_err_t *medep)
    424 {
    425 	if (dbfd == -1)
    426 		return (0);
    427 
    428 	/* Make sure we are at the beginning of the file */
    429 	if (lseek(dbfd, 0, SEEK_SET) == -1)
    430 		return (med_error(medep, errno, "close_dbfile: lseek()"));
    431 
    432 	/* Release the advisory lock on the file */
    433 	if (lockf(dbfd, F_ULOCK, 0LL) == -1) {
    434 		(void) med_error(medep, errno, "close_dbfile: lockf(F_ULOCK)");
    435 		medde_perror(medep, "");
    436 		med_exit(1);
    437 	}
    438 
    439 	if (close(dbfd) == -1)
    440 		return (med_error(medep, errno, "close_dbfile: close()"));
    441 
    442 	dbfd = -1;
    443 
    444 	return (0);
    445 }
    446 
    447 static int
    448 med_db_del_rec(med_med_t *medp, med_err_t *medep)
    449 {
    450 	med_rec_t	*medrp = NULL;
    451 	int		i;
    452 	int		medridx = -1;
    453 
    454 
    455 	if (! med_db_is_inited)
    456 		return (med_error(medep, MDE_MED_DBNOTINIT, "med_db_del_rec"));
    457 
    458 	if ((medridx = find_key(medp)) == -1)
    459 		return (0);
    460 
    461 	/* Delete the old keys */
    462 	if (del_db_keys(medridx, medep))
    463 		return (-1);
    464 
    465 	medrp = &med_db_medrp[medridx];
    466 
    467 	/* Mark the record in core as deleted */
    468 	medrp->med_rec_fl |= MED_RFL_DEL;
    469 
    470 	/* Decrement the used slot count */
    471 	med_db_nmu--;
    472 
    473 	/* Get ready to re-write the file */
    474 	if (ftruncate(dbfd, 0) == -1)
    475 		return (med_error(medep, errno, "med_db_del_rec: ftruncate()"));
    476 
    477 	if (write_hdr(dbfd, medep))
    478 		return (-1);
    479 
    480 	for (i = 0; i < med_db_nma; i++) {
    481 		medrp = &med_db_medrp[i];
    482 
    483 		if (medrp->med_rec_fl & MED_RFL_DEL)
    484 			continue;
    485 
    486 		/* Determine our location in the file */
    487 		if ((medrp->med_rec_foff = lseek(dbfd, 0, SEEK_CUR)) == -1)
    488 			return (med_error(medep, errno,
    489 			    "med_db_del_rec: lseek()"));
    490 
    491 		if (write_rec(dbfd, medrp, medep))
    492 			return (-1);
    493 	}
    494 	return (0);
    495 }
    496 
    497 static int
    498 cmp_medrec(med_rec_t *omedrp, med_rec_t *nmedrp)
    499 {
    500 	int	ret;
    501 	int	i;
    502 
    503 	if (omedrp->med_rec_mag != nmedrp->med_rec_mag)
    504 		return (0);
    505 
    506 	if (omedrp->med_rec_rev != nmedrp->med_rec_rev)
    507 		return (0);
    508 
    509 	/* Can't compare checksums, since the new record has no data yet */
    510 
    511 	/* Can't compare flags, since the in-core may have golden */
    512 
    513 	if (omedrp->med_rec_sn != nmedrp->med_rec_sn)
    514 		return (0);
    515 
    516 	if (strcmp(omedrp->med_rec_snm, nmedrp->med_rec_snm) != 0)
    517 		return (0);
    518 
    519 	for (i = 0; i < MD_MAXSIDES; i++) {
    520 		if (omedrp->med_rec_nodes[i][0] == '\0' &&
    521 		    nmedrp->med_rec_nodes[i][0] == '\0')
    522 			continue;
    523 
    524 		ret = strcmp(omedrp->med_rec_nodes[i],
    525 		    nmedrp->med_rec_nodes[i]);
    526 		if (ret != 0)
    527 			return (0);
    528 	}
    529 
    530 	ret = memcmp(&omedrp->med_rec_meds, &nmedrp->med_rec_meds,
    531 	    sizeof (md_h_arr_t));
    532 	if (ret != 0)
    533 		return (0);
    534 
    535 	return (1);
    536 }
    537 
    538 /*
    539  * Exported routines
    540  */
    541 
    542 int
    543 med_db_init(med_err_t *medep)
    544 {
    545 	int		i;
    546 	int		err = 0;
    547 	int		ret;
    548 	struct	stat	statb;
    549 	med_db_hdr_t	*dbhp;
    550 	med_rec_t	*medrp;
    551 	int		nm;
    552 	off_t		cur_off;
    553 
    554 	if (med_db_is_inited)
    555 		return (0);
    556 
    557 	if (open_dbfile(medep))
    558 		return (-1);
    559 
    560 	if (fstat(dbfd, &statb) == -1)
    561 		return (med_error(medep, errno, "med_db_init: fstat()"));
    562 
    563 	/* Empty file */
    564 	if (statb.st_size == 0)
    565 		goto out;
    566 
    567 	/* File should be a multiple of the record size */
    568 	if (((int)(statb.st_size % (off_t)rec_size)) != 0)
    569 		return (med_error(medep, MDE_MED_DBSZBAD, "med_db_init"));
    570 
    571 	if (alloc_rec_buf(medep))
    572 		return (-1);
    573 
    574 	/* Read in the file header */
    575 	if ((ret = read(dbfd, rec_buf, rec_size)) == -1)
    576 		return (med_error(medep, errno, "med_db_init: read(hdr)"));
    577 
    578 	if (ret != rec_size)
    579 		return (med_error(medep, MDE_MED_DBHDRSZBAD, "med_db_init"));
    580 
    581 	/*LINTED*/
    582 	dbhp = (med_db_hdr_t *)rec_buf;
    583 
    584 	/* Header magic is not OK */
    585 	if (dbhp->med_dbh_mag != MED_DB_MAGIC)
    586 		return (med_error(medep, MDE_MED_DBHDRMAGBAD, "med_db_init"));
    587 
    588 	/* Header revision is not OK */
    589 	if (dbhp->med_dbh_rev != MED_DB_REV)
    590 		return (med_error(medep, MDE_MED_DBHDRREVBAD, "med_db_init"));
    591 
    592 	/* Header checksum is not OK */
    593 	if (crcchk(dbhp, &dbhp->med_dbh_cks, sizeof (med_db_hdr_t), NULL))
    594 		return (med_error(medep, MDE_MED_DBHDRCKSBAD, "med_db_init"));
    595 
    596 	/* File size does not add up */
    597 	if (((off_t)((dbhp->med_dbh_nm * rec_size) + rec_size))
    598 	    != statb.st_size)
    599 		return (med_error(medep, MDE_MED_DBSZBAD, "med_db_init"));
    600 
    601 	if ((nm = dbhp->med_dbh_nm) > 0) {
    602 		/* Allocate space to hold the records to be read next */
    603 		med_db_medrp = (med_rec_t *)Calloc(nm, sizeof (med_rec_t));
    604 		if (med_db_medrp == NULL)
    605 			return (med_error(medep, errno,
    606 			    "med_db_init: Calloc(med_db_medrp)"));
    607 	}
    608 
    609 	/* Read in all the records */
    610 	for (i = 0; i < nm; i++) {
    611 		if ((cur_off = lseek(dbfd, 0, SEEK_CUR)) == -1) {
    612 			err = med_error(medep, errno,
    613 			    "med_db_init: lseek()");
    614 			goto out;
    615 		}
    616 
    617 		(void) memset(rec_buf, '\0', rec_size);
    618 
    619 		if ((ret = read(dbfd, rec_buf, rec_size)) == -1) {
    620 			err = med_error(medep, errno,
    621 			    "med_db_init: read() rec");
    622 			goto out;
    623 		}
    624 
    625 		if (ret != rec_size) {
    626 			err = med_error(medep, MDE_MED_DBRECSZBAD,
    627 			    "med_db_init");
    628 			goto out;
    629 		}
    630 
    631 		/*LINTED*/
    632 		medrp = (med_rec_t *)rec_buf;
    633 
    634 		/* Record magic is not OK */
    635 		if (medrp->med_rec_mag != MED_REC_MAGIC) {
    636 			err = med_error(medep, MDE_MED_DBRECMAGBAD,
    637 			    "med_db_init");
    638 			goto out;
    639 		}
    640 
    641 		/* Record revision is not OK */
    642 		if (medrp->med_rec_rev != MED_REC_REV) {
    643 			err = med_error(medep, MDE_MED_DBRECREVBAD,
    644 			    "med_db_init");
    645 			goto out;
    646 		}
    647 
    648 		/* Record checksum is not OK */
    649 		ret = crcchk(medrp, &medrp->med_rec_cks, sizeof (med_rec_t),
    650 		    NULL);
    651 		if (ret) {
    652 			err = med_error(medep, MDE_MED_DBRECCKSBAD,
    653 			    "med_db_init");
    654 			goto out;
    655 		}
    656 
    657 		/* Record is not where it is supposed to be */
    658 		if (medrp->med_rec_foff != cur_off) {
    659 			err = med_error(medep, MDE_MED_DBRECOFFBAD,
    660 			    "med_db_init");
    661 			goto out;
    662 		}
    663 
    664 		med_db_medrp[i] = *medrp;	/* structure assignment */
    665 	}
    666 
    667 	/* Add the keys to access this record */
    668 	for (i = 0; i < nm; i++)
    669 		if ((err = add_db_keys(i, medep)) == -1)
    670 			goto out;
    671 
    672 	med_db_nma = nm;
    673 	med_db_nmu = nm;
    674 
    675 out:
    676 	if (err && med_db_medrp != NULL)
    677 		Free(med_db_medrp);
    678 
    679 	if (!err)
    680 		med_db_is_inited = 1;
    681 
    682 	return (err);
    683 }
    684 
    685 med_rec_t *
    686 med_db_get_rec(med_med_t *medp, med_err_t *medep)
    687 {
    688 	int		medridx = -1;
    689 
    690 	if ((medridx = find_key(medp)) == -1) {
    691 		(void) med_error(medep, MDE_MED_DBRECNOENT, "med_db_get_rec");
    692 		return (NULL);
    693 	}
    694 
    695 	return (&med_db_medrp[medridx]);
    696 }
    697 
    698 med_data_t *
    699 med_db_get_data(med_med_t *medp, med_err_t *medep)
    700 {
    701 	int		medridx = -1;
    702 
    703 	if ((medridx = find_key(medp)) == -1) {
    704 		(void) med_error(medep, MDE_MED_DBRECNOENT, "med_db_get_data");
    705 		return (NULL);
    706 	}
    707 
    708 	return (&med_db_medrp[medridx].med_rec_data);
    709 }
    710 
    711 int
    712 med_db_put_rec(med_med_t *medp, med_rec_t *nmedrp, med_err_t *medep)
    713 {
    714 	med_rec_t	*medrp = NULL;
    715 	med_rec_t	*tmedrp = NULL;
    716 	int		i;
    717 	int		found = 0;
    718 	int		medridx = -1;
    719 
    720 
    721 	if (! med_db_is_inited)
    722 		return (med_error(medep, MDE_MED_DBNOTINIT, "med_db_put_rec"));
    723 
    724 	if (medp->med_setno != nmedrp->med_rec_sn)
    725 		return (med_error(medep, MDE_MED_DBARGSMISMATCH,
    726 		    "med_db_put_rec"));
    727 
    728 	/* See if we are still considered a mediator - is this a delete? */
    729 	for (i = 0; i < MED_MAX_HOSTS; i++) {
    730 		if (nmedrp->med_rec_meds.n_lst[i].a_cnt == 0)
    731 			continue;
    732 
    733 		if (strcmp(nmedrp->med_rec_meds.n_lst[i].a_nm[0],
    734 		    mynode()) == 0) {
    735 			found = 1;
    736 			break;
    737 		}
    738 	}
    739 
    740 	/* If it is a delete, make it happen */
    741 	if (! found)
    742 		return (med_db_del_rec(medp, medep));
    743 
    744 	/* See if there is an existing record */
    745 	if ((medridx = find_key(medp)) != -1) {
    746 
    747 		medrp = &med_db_medrp[medridx];
    748 
    749 		/* Delete the old keys */
    750 		if (del_db_keys(medridx, medep))
    751 			return (-1);
    752 
    753 		/* Decrement the used slot count */
    754 		med_db_nmu--;
    755 	} else {
    756 		for (i = 0; i < MED_MAX_HOSTS; i++) {
    757 			med_med_t	tmed;
    758 
    759 			if (nmedrp->med_rec_meds.n_lst[i].a_cnt == 0)
    760 				continue;
    761 
    762 			if (strcmp(nmedrp->med_rec_meds.n_lst[i].a_nm[0],
    763 			    medp->med_caller) == 0)
    764 				continue;
    765 
    766 			tmed = *medp;		/* structure assignment */
    767 
    768 			tmed.med_caller =
    769 			    Strdup(nmedrp->med_rec_meds.n_lst[i].a_nm[0]);
    770 
    771 			medridx = find_key(&tmed);
    772 
    773 			Free(tmed.med_caller);
    774 
    775 			if (medridx != -1) {
    776 				medrp = &med_db_medrp[medridx];
    777 
    778 				if (cmp_medrec(medrp, nmedrp))
    779 					return (0);
    780 			}
    781 		}
    782 	}
    783 
    784 	/* Allocate more space if needed */
    785 	if ((med_db_nmu + 1) > med_db_nma) {
    786 
    787 		/* Allocate more space to hold the new record */
    788 		tmedrp = (med_rec_t *)Calloc((med_db_nmu + 1),
    789 		    sizeof (med_rec_t));
    790 		if (tmedrp == NULL)
    791 			return (med_error(medep, errno,
    792 			    "med_db_put_rec: Re-Calloc(tmedrp)"));
    793 
    794 		/* Copy the existing information into the new area */
    795 		for (i = 0; i < med_db_nma; i++)
    796 			tmedrp[i] = med_db_medrp[i]; /* structure assignment */
    797 
    798 		med_db_nmu++;
    799 		med_db_nma = med_db_nmu;
    800 
    801 		if (med_db_medrp)
    802 			Free(med_db_medrp);
    803 
    804 		med_db_medrp = tmedrp;
    805 
    806 		medridx = med_db_nma - 1;
    807 
    808 		/* Initialize */
    809 		medrp = &med_db_medrp[medridx];
    810 		medrp->med_rec_mag = MED_REC_MAGIC;
    811 		medrp->med_rec_rev = MED_REC_REV;
    812 		medrp->med_rec_sn = nmedrp->med_rec_sn;
    813 		(void) strcpy(medrp->med_rec_snm, nmedrp->med_rec_snm);
    814 
    815 		/* Calculate the record offset */
    816 		medrp->med_rec_foff = (off_t)(((med_db_nma - 1) * rec_size) +
    817 		    rec_size);
    818 	} else {
    819 		/*
    820 		 * We did not find the record, but have space allocated.
    821 		 * Find an empty slot.
    822 		 */
    823 		if (medrp == NULL) {
    824 			for (i = 0; i < med_db_nma; i++) {
    825 				medrp = &med_db_medrp[i];
    826 
    827 				if (! (medrp->med_rec_fl & MED_RFL_DEL))
    828 					continue;
    829 
    830 				medridx = i;
    831 
    832 				/* Mark as no longer deleted */
    833 				medrp->med_rec_fl &= ~MED_RFL_DEL;
    834 
    835 				/* Initialize */
    836 				medrp->med_rec_mag = MED_REC_MAGIC;
    837 				medrp->med_rec_rev = MED_REC_REV;
    838 				medrp->med_rec_sn = nmedrp->med_rec_sn;
    839 				(void) strcpy(medrp->med_rec_snm,
    840 				    nmedrp->med_rec_snm);
    841 
    842 				/* Calculate the new offset of the record */
    843 				medrp->med_rec_foff = (off_t)
    844 				    ((med_db_nmu * rec_size) + rec_size);
    845 
    846 				/* Clear the old data */
    847 				(void) memset(&medrp->med_rec_data, '\0',
    848 				    sizeof (med_data_t));
    849 
    850 				break;
    851 			}
    852 		}
    853 		med_db_nmu++;
    854 	}
    855 
    856 	assert(medridx != -1);
    857 
    858 	/* Update the record with the new information */
    859 	medrp->med_rec_meds = nmedrp->med_rec_meds;  /* structure assignment */
    860 
    861 	for (i = 0; i < MD_MAXSIDES; i++)
    862 		(void) strcpy(medrp->med_rec_nodes[i],
    863 		    nmedrp->med_rec_nodes[i]);
    864 
    865 	if (write_hdr(dbfd, medep))
    866 		return (-1);
    867 
    868 	/* Position to record location */
    869 	if (lseek(dbfd, medrp->med_rec_foff, SEEK_SET) == -1)
    870 		return (med_error(medep, errno, "med_db_put_rec: lseek(rec)"));
    871 
    872 	if (write_rec(dbfd, medrp, medep))
    873 		return (-1);
    874 
    875 	/* Add the keys for this record */
    876 	if (add_db_keys(medridx, medep))
    877 		return (-1);
    878 
    879 	return (0);
    880 }
    881 
    882 int
    883 med_db_put_data(med_med_t *medp, med_data_t *meddp, med_err_t *medep)
    884 {
    885 	med_rec_t	*medrp = NULL;
    886 	int		medridx = -1;
    887 
    888 
    889 	if (! med_db_is_inited)
    890 		return (med_error(medep, MDE_MED_DBNOTINIT, "med_db_put_data"));
    891 
    892 	if (medp->med_setno != meddp->med_dat_sn)
    893 		return (med_error(medep, MDE_MED_DBARGSMISMATCH,
    894 		    "med_db_put_data"));
    895 
    896 	if ((medridx = find_key(medp)) == -1)
    897 		return (med_error(medep, MDE_MED_DBRECNOENT,
    898 		    "med_db_put_data"));
    899 
    900 	medrp = &med_db_medrp[medridx];
    901 
    902 	medrp->med_rec_data = *meddp;		/* structure assignment */
    903 
    904 	/* Go to location of the record */
    905 	if (lseek(dbfd, medrp->med_rec_foff, SEEK_SET) == -1)
    906 		return (med_error(medep, errno, "med_db_put_data: lseek()"));
    907 
    908 	if (write_rec(dbfd, medrp, medep))
    909 		return (-1);
    910 
    911 	return (0);
    912 }
    913 
    914 int
    915 med_db_finit(med_err_t *medep)
    916 {
    917 	des_cache(&med_db_cache);
    918 	Free(med_db_medrp);
    919 	free_rec_buf();
    920 	if (close_dbfile(medep))
    921 		return (-1);
    922 	return (0);
    923 }
    924