xref: /titanic_41/usr/src/cmd/lvm/rpc.metamedd/med_db.c (revision 1410cb930a3e26032c59c6835837a28c47366b3c)
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