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