xref: /illumos-gate/usr/src/lib/librsm/common/rsmlib.c (revision 7257d1b4)
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 /*
23  * Copyright 2008 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 <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <ctype.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39 #include <sys/uio.h>
40 #include <sys/sysmacros.h>
41 #include <sys/resource.h>
42 #include <errno.h>
43 #include <assert.h>
44 #include <fcntl.h>
45 #include <dlfcn.h>
46 #include <sched.h>
47 #include <stropts.h>
48 #include <poll.h>
49 
50 #include <rsmapi.h>
51 #include <sys/rsm/rsmndi.h>
52 #include <rsmlib_in.h>
53 #include <sys/rsm/rsm.h>
54 
55 /* lint -w2 */
56 extern void __rsmloopback_init_ops(rsm_segops_t *);
57 extern void __rsmdefault_setops(rsm_segops_t *);
58 
59 typedef void (*rsm_access_func_t)(void *, void *, rsm_access_size_t);
60 
61 #ifdef DEBUG
62 
63 #define	RSMLOG_BUF_SIZE 256
64 FILE *rsmlog_fd = NULL;
65 static mutex_t rsmlog_lock;
66 int rsmlibdbg_category = RSM_LIBRARY;
67 int rsmlibdbg_level = RSM_ERR;
68 void dbg_printf(int category, int level, char *fmt, ...);
69 
70 #endif /* DEBUG */
71 
72 rsm_node_id_t rsm_local_nodeid = 0;
73 
74 static rsm_controller_t *controller_list = NULL;
75 
76 static rsm_segops_t loopback_ops;
77 
78 #define	MAX_STRLEN	80
79 
80 #define	RSM_IOTYPE_PUTGET	1
81 #define	RSM_IOTYPE_SCATGATH	2
82 
83 #define	RSMFILE_BUFSIZE		256
84 
85 #pragma init(_rsm_librsm_init)
86 
87 static mutex_t _rsm_lock;
88 
89 static int _rsm_fd = -1;
90 static rsm_gnum_t *bar_va, bar_fixed = 0;
91 static rsm_pollfd_table_t pollfd_table;
92 
93 static int _rsm_get_hwaddr(rsmapi_controller_handle_t handle,
94 rsm_node_id_t, rsm_addr_t *hwaddrp);
95 static int _rsm_get_nodeid(rsmapi_controller_handle_t,
96 rsm_addr_t, rsm_node_id_t *);
97 static int __rsm_import_implicit_map(rsmseg_handle_t *, int);
98 static int __rsm_intr_signal_wait_common(struct pollfd [], minor_t [],
99     nfds_t, int, int *);
100 
101 static	rsm_lib_funcs_t lib_functions = {
102 	RSM_LIB_FUNCS_VERSION,
103 	_rsm_get_hwaddr,
104 	_rsm_get_nodeid
105 };
106 
107 rsm_topology_t *tp;
108 
109 
110 /*
111  * service module function templates:
112  */
113 
114 /*
115  * The _rsm_librsm_init function is called the first time an application
116  * references the RSMAPI library
117  */
118 int
119 _rsm_librsm_init()
120 {
121 	rsm_ioctlmsg_t 		msg;
122 	int e, tmpfd;
123 	int i;
124 	char logname[MAXNAMELEN];
125 
126 	mutex_init(&_rsm_lock, USYNC_THREAD, NULL);
127 
128 #ifdef DEBUG
129 	mutex_init(&rsmlog_lock, USYNC_THREAD, NULL);
130 	sprintf(logname, "%s.%d", TRACELOG, getpid());
131 	rsmlog_fd = fopen(logname, "w+F");
132 	if (rsmlog_fd == NULL) {
133 		fprintf(stderr, "Log file open failed\n");
134 		return (errno);
135 	}
136 
137 #endif /* DEBUG */
138 
139 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
140 	    "_rsm_librsm_init: enter\n"));
141 
142 	/* initialize the pollfd_table */
143 	mutex_init(&pollfd_table.lock, USYNC_THREAD, NULL);
144 
145 	for (i = 0; i < RSM_MAX_BUCKETS; i++) {
146 		pollfd_table.buckets[i] = NULL;
147 	}
148 
149 	/* open /dev/rsm and mmap barrier generation pages */
150 	mutex_lock(&_rsm_lock);
151 	_rsm_fd = open(DEVRSM, O_RDONLY);
152 	if (_rsm_fd < 0) {
153 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
154 		    "unable to open /dev/rsm\n"));
155 		mutex_unlock(&_rsm_lock);
156 		return (errno);
157 	}
158 
159 	/*
160 	 * DUP the opened file descriptor to something greater than
161 	 * STDERR_FILENO so that we never use the STDIN_FILENO,
162 	 * STDOUT_FILENO or STDERR_FILENO.
163 	 */
164 	tmpfd = fcntl(_rsm_fd, F_DUPFD, 3);
165 	if (tmpfd < 0) {
166 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
167 		    "F_DUPFD failed\n"));
168 	} else {
169 		(void) close(_rsm_fd);
170 		_rsm_fd = tmpfd;
171 	}
172 
173 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
174 	    "_rsm_fd is %d\n", _rsm_fd));
175 
176 	if (fcntl(_rsm_fd, F_SETFD, FD_CLOEXEC) < 0) {
177 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
178 		"F_SETFD failed\n"));
179 	}
180 
181 	/* get mapping generation number page info */
182 	if (ioctl(_rsm_fd, RSM_IOCTL_BAR_INFO, &msg) < 0) {
183 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
184 		    "RSM_IOCTL_BAR_INFO failed\n"));
185 		mutex_unlock(&_rsm_lock);
186 		return (errno);
187 	}
188 
189 	/*
190 	 * bar_va is mapped to the mapping generation number page
191 	 * in order to support close barrier
192 	 */
193 	/* LINTED */
194 	bar_va = (rsm_gnum_t *)mmap(NULL, msg.len,
195 	    PROT_READ, MAP_SHARED, _rsm_fd, msg.off);
196 	if (bar_va == (rsm_gnum_t *)MAP_FAILED) {
197 		bar_va = NULL;
198 		mutex_unlock(&_rsm_lock);
199 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
200 		    "unable to map barrier page\n"));
201 		return (RSMERR_MAP_FAILED);
202 	}
203 
204 	mutex_unlock(&_rsm_lock);
205 
206 	/* get local nodeid */
207 	e = rsm_get_interconnect_topology(&tp);
208 	if (e != RSM_SUCCESS) {
209 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
210 		    "unable to obtain topology data\n"));
211 		return (e);
212 	} else
213 		rsm_local_nodeid = tp->topology_hdr.local_nodeid;
214 
215 	rsm_free_interconnect_topology(tp);
216 
217 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
218 	    "_rsm_librsm_init: exit\n"));
219 
220 	return (RSM_SUCCESS);
221 }
222 
223 static int
224 _rsm_loopbackload(caddr_t name, int unit, rsm_controller_t **chdl)
225 {
226 	rsm_controller_t *p;
227 	rsm_ioctlmsg_t msg;
228 
229 	DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_DEBUG_VERBOSE,
230 	    "_rsm_loopbackload: enter\n"));
231 	/*
232 	 * For now do this, but we should open some file and read the
233 	 * list of supported controllers and there numbers.
234 	 */
235 
236 	p = (rsm_controller_t *)malloc(sizeof (*p) + strlen(name) + 1);
237 	if (!p) {
238 		DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
239 		    "not enough memory\n"));
240 		return (RSMERR_INSUFFICIENT_MEM);
241 	}
242 
243 	msg.cname = name;
244 	msg.cname_len = strlen(name) +1;
245 	msg.cnum = unit;
246 	msg.arg = (caddr_t)&p->cntr_attr;
247 	if (ioctl(_rsm_fd, RSM_IOCTL_ATTR, &msg) < 0) {
248 		int error = errno;
249 		free((void *)p);
250 		DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
251 		    "RSM_IOCTL_ATTR failed\n"));
252 		return (error);
253 	}
254 
255 	__rsmloopback_init_ops(&loopback_ops);
256 	__rsmdefault_setops(&loopback_ops);
257 	p->cntr_segops = &loopback_ops;
258 
259 	/*
260 	 * Should add this entry into list
261 	 */
262 	p->cntr_fd = _rsm_fd;
263 	p->cntr_name = strcpy((char *)(p+1), name);
264 	p->cntr_unit = unit;
265 	p->cntr_refcnt = 1;
266 
267 
268 	mutex_init(&p->cntr_lock, USYNC_THREAD, NULL);
269 	cond_init(&p->cntr_cv, USYNC_THREAD, NULL);
270 	p->cntr_rqlist = NULL;
271 	p->cntr_segops->rsm_get_lib_attr(&p->cntr_lib_attr);
272 	p->cntr_next = controller_list;
273 	controller_list = p;
274 
275 	*chdl = p;
276 
277 	DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_DEBUG_VERBOSE,
278 	    "_rsm_loopbackload: exit\n"));
279 	return (RSM_SUCCESS);
280 
281 }
282 
283 static int
284 _rsm_modload(caddr_t name, int unit, rsmapi_controller_handle_t *controller)
285 {
286 	int error = RSM_SUCCESS;
287 	char clib[MAX_STRLEN];
288 	rsm_controller_t *p = NULL;
289 	void *dlh;
290 	rsm_attach_entry_t fptr;
291 	rsm_ioctlmsg_t msg;
292 
293 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
294 	    "_rsm_modload: enter\n"));
295 
296 	(void) sprintf(clib, "%s.so", name);
297 
298 	/* found entry, try to load library */
299 	dlh = dlopen(clib, RTLD_LAZY);
300 	if (dlh == NULL) {
301 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
302 		    "unable to find plugin library\n"));
303 		error = RSMERR_CTLR_NOT_PRESENT;
304 		goto skiplib;
305 	}
306 
307 	(void) sprintf(clib, "%s_opendevice", name);
308 
309 	fptr = (rsm_attach_entry_t)dlsym(dlh, clib); /* lint !e611 */
310 	if (fptr != NULL) {
311 		/* allocate new lib structure */
312 		/* get ops handler, attr and ops */
313 		p = (rsm_controller_t *)malloc(sizeof (*p) + strlen(name) + 1);
314 		if (p != NULL) {
315 			error = fptr(unit, &p->cntr_segops);
316 		} else {
317 			error = RSMERR_INSUFFICIENT_MEM;
318 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
319 			    "not enough memory\n"));
320 		}
321 	} else {
322 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
323 		    "can't find symbol %s\n", clib));
324 		error = RSMERR_CTLR_NOT_PRESENT;
325 		(void) dlclose(dlh);
326 	}
327 
328 skiplib:
329 	if ((error != RSM_SUCCESS) || (p == NULL)) {
330 		if (p != NULL)
331 			free((void *)p);
332 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
333 		    "_rsm_modload error %d\n", error));
334 		return (error);
335 	}
336 
337 	/* check the version number */
338 	if (p->cntr_segops->rsm_version != RSM_LIB_VERSION) {
339 		/* bad version number */
340 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
341 		    "wrong version; "
342 		    "found %d, expected %d\n",
343 		    p->cntr_segops->rsm_version, RSM_LIB_VERSION));
344 		free(p);
345 		return (RSMERR_BAD_LIBRARY_VERSION);
346 	} else {
347 		/* pass the fuctions to NDI library */
348 		if ((p->cntr_segops->rsm_register_lib_funcs == NULL) ||
349 		    (p->cntr_segops->rsm_register_lib_funcs(
350 		    &lib_functions) != RSM_SUCCESS)) {
351 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
352 			    "RSMNDI library not registering lib functions\n"));
353 		}
354 
355 		/* get controller attributes */
356 		msg.cnum = unit;
357 		msg.cname = name;
358 		msg.cname_len = strlen(name) +1;
359 		msg.arg = (caddr_t)&p->cntr_attr;
360 		if (ioctl(_rsm_fd, RSM_IOCTL_ATTR, &msg) < 0) {
361 			error = errno;
362 			free((void *)p);
363 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
364 			    "RSM_IOCTL_ATTR failed\n"));
365 			return (error);
366 		}
367 
368 		/* set controller access functions */
369 		__rsmdefault_setops(p->cntr_segops);
370 
371 		mutex_init(&p->cntr_lock, USYNC_THREAD, NULL);
372 		cond_init(&p->cntr_cv, USYNC_THREAD, NULL);
373 		p->cntr_rqlist = NULL;
374 		p->cntr_segops->rsm_get_lib_attr(&p->cntr_lib_attr);
375 		/* insert into list of controllers */
376 		p->cntr_name = strcpy((char *)(p+1), name);
377 		p->cntr_fd = _rsm_fd;
378 		p->cntr_unit = unit;
379 		p->cntr_refcnt = 1;	/* first reference */
380 		p->cntr_next = controller_list;
381 		controller_list = p;
382 		*controller = (rsmapi_controller_handle_t)p;
383 		errno = RSM_SUCCESS;
384 	}
385 
386 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
387 	    "_rsm_modload: exit\n"));
388 	return (error);
389 }
390 
391 /*
392  * inserts a given segment handle into the pollfd table, this is called
393  * when rsm_memseg_get_pollfd() is called the first time on a segment handle.
394  * Returns RSM_SUCCESS if successful otherwise the error code is returned
395  */
396 static int
397 _rsm_insert_pollfd_table(int segfd, minor_t segrnum)
398 {
399 	int i;
400 	int hash;
401 	rsm_pollfd_chunk_t *chunk;
402 
403 	hash = RSM_POLLFD_HASH(segfd);
404 
405 	mutex_lock(&pollfd_table.lock);
406 
407 	chunk = pollfd_table.buckets[hash];
408 	while (chunk) {
409 		if (chunk->nfree > 0)
410 			break;
411 		chunk = chunk->next;
412 	}
413 
414 	if (!chunk) { /* couldn't find a free chunk - allocate a new one */
415 		chunk = malloc(sizeof (rsm_pollfd_chunk_t));
416 		if (!chunk) {
417 			mutex_unlock(&pollfd_table.lock);
418 			return (RSMERR_INSUFFICIENT_MEM);
419 		}
420 		chunk->nfree = RSM_POLLFD_PER_CHUNK - 1;
421 		chunk->fdarray[0].fd = segfd;
422 		chunk->fdarray[0].segrnum = segrnum;
423 		for (i = 1; i < RSM_POLLFD_PER_CHUNK; i++) {
424 			chunk->fdarray[i].fd = -1;
425 			chunk->fdarray[i].segrnum = 0;
426 		}
427 		/* insert this into the hash table */
428 		chunk->next = pollfd_table.buckets[hash];
429 		pollfd_table.buckets[hash] = chunk;
430 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
431 		    "rsm_insert_pollfd: new chunk(%p) @ %d for %d:%d\n",
432 		    chunk, hash, segfd, segrnum));
433 	} else { /* a chunk with free slot was found */
434 		for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
435 			if (chunk->fdarray[i].fd == -1) {
436 				chunk->fdarray[i].fd = segfd;
437 				chunk->fdarray[i].segrnum = segrnum;
438 				chunk->nfree--;
439 				break;
440 			}
441 		}
442 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
443 		    "rsm_insert_pollfd: inserted @ %d for %d:%d chunk(%p)\n",
444 		    hash, segfd, segrnum, chunk));
445 		assert(i < RSM_POLLFD_PER_CHUNK);
446 	}
447 
448 	mutex_unlock(&pollfd_table.lock);
449 	return (RSM_SUCCESS);
450 }
451 
452 /*
453  * Given a file descriptor returns the corresponding segment handles
454  * resource number, if the fd is not found returns 0. 0 is not a valid
455  * minor number for a rsmapi segment since it is used for the barrier
456  * resource.
457  */
458 static minor_t
459 _rsm_lookup_pollfd_table(int segfd)
460 {
461 	int i;
462 	rsm_pollfd_chunk_t	*chunk;
463 
464 	if (segfd < 0)
465 		return (0);
466 
467 	mutex_lock(&pollfd_table.lock);
468 
469 	chunk = pollfd_table.buckets[RSM_POLLFD_HASH(segfd)];
470 	while (chunk) {
471 		assert(chunk->nfree < RSM_POLLFD_PER_CHUNK);
472 
473 		for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
474 			if (chunk->fdarray[i].fd == segfd) {
475 				mutex_unlock(&pollfd_table.lock);
476 				DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
477 				    "rsm_lookup_pollfd: found(%d) rnum(%d)\n",
478 				    segfd, chunk->fdarray[i].segrnum));
479 				return (chunk->fdarray[i].segrnum);
480 			}
481 		}
482 		chunk = chunk->next;
483 	}
484 
485 	mutex_unlock(&pollfd_table.lock);
486 
487 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
488 	    "rsm_lookup_pollfd: not found(%d)\n", segfd));
489 
490 	return (0);
491 }
492 
493 /*
494  * Remove the entry corresponding to the given file descriptor from the
495  * pollfd table.
496  */
497 static void
498 _rsm_remove_pollfd_table(int segfd)
499 {
500 	int i;
501 	int hash;
502 	rsm_pollfd_chunk_t	*chunk;
503 	rsm_pollfd_chunk_t	*prev_chunk;
504 
505 	if (segfd < 0)
506 		return;
507 
508 	hash = RSM_POLLFD_HASH(segfd);
509 
510 	mutex_lock(&pollfd_table.lock);
511 
512 	prev_chunk = chunk = pollfd_table.buckets[hash];
513 	while (chunk) {
514 		assert(chunk->nfree < RSM_POLLFD_PER_CHUNK);
515 
516 		for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
517 			if (chunk->fdarray[i].fd == segfd) {
518 				DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
519 				    "rsm_remove_pollfd: %d:%d\n",
520 				    chunk->fdarray[i].fd,
521 				    chunk->fdarray[i].segrnum));
522 				chunk->fdarray[i].fd = -1;
523 				chunk->fdarray[i].segrnum = 0;
524 				chunk->nfree++;
525 				if (chunk->nfree == RSM_POLLFD_PER_CHUNK) {
526 					/* chunk is empty free it */
527 					if (prev_chunk == chunk) {
528 						pollfd_table.buckets[hash] =
529 						    chunk->next;
530 					} else {
531 						prev_chunk->next = chunk->next;
532 					}
533 					DBPRINTF((RSM_LIBRARY,
534 					    RSM_DEBUG_VERBOSE,
535 					    "rsm_remove_pollfd:free(%p)\n",
536 					    chunk));
537 					free(chunk);
538 					mutex_unlock(&pollfd_table.lock);
539 					return;
540 				}
541 			}
542 		}
543 		prev_chunk = chunk;
544 		chunk = chunk->next;
545 	}
546 
547 	mutex_unlock(&pollfd_table.lock);
548 }
549 
550 int
551 rsm_get_controller(char *name, rsmapi_controller_handle_t *chdl)
552 {
553 	rsm_controller_t *p;
554 	char	cntr_name[MAXNAMELEN];	/* cntr_name=<cntr_type><unit> */
555 	char	*cntr_type;
556 	int	unit = 0;
557 	int	i, e;
558 
559 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
560 	    "rsm_get_controller: enter\n"));
561 	/*
562 	 * Lookup controller name and return ops vector and controller
563 	 * structure
564 	 */
565 
566 	if (!chdl) {
567 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
568 		    "Invalid controller handle\n"));
569 		return (RSMERR_BAD_CTLR_HNDL);
570 	}
571 	if (!name) {
572 		/* use loopback if null */
573 		cntr_type = LOOPBACK;
574 	} else {
575 		(void) strcpy(cntr_name, name);
576 		/* scan from the end till a non-digit is found */
577 		for (i = strlen(cntr_name) - 1; i >= 0; i--) {
578 			if (! isdigit((int)cntr_name[i]))
579 				break;
580 		}
581 		i++;
582 		unit = atoi((char *)cntr_name+i);
583 		cntr_name[i] = '\0';	/* null terminate the cntr_type part */
584 		cntr_type = (char *)cntr_name;
585 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
586 		    "cntr_type=%s, instance=%d\n",
587 		    cntr_type, unit));
588 	}
589 
590 	/* protect the controller_list by locking the device/library */
591 	mutex_lock(&_rsm_lock);
592 
593 	for (p = controller_list; p; p = p->cntr_next) {
594 		if (!strcasecmp(p->cntr_name, cntr_type) &&
595 		    !strcasecmp(cntr_type, LOOPBACK)) {
596 			p->cntr_refcnt++;
597 			*chdl = (rsmapi_controller_handle_t)p;
598 			mutex_unlock(&_rsm_lock);
599 			DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
600 			    "rsm_get_controller: exit\n"));
601 			return (RSM_SUCCESS);
602 		} else if (!strcasecmp(p->cntr_name, cntr_type) &&
603 		    (p->cntr_unit == unit)) {
604 			p->cntr_refcnt++;
605 			*chdl = (rsmapi_controller_handle_t)p;
606 			mutex_unlock(&_rsm_lock);
607 			DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
608 			    "rsm_get_controller: exit\n"));
609 			return (RSM_SUCCESS);
610 		}
611 	}
612 
613 
614 	if (!strcasecmp(cntr_type, LOOPBACK)) {
615 		e = _rsm_loopbackload(cntr_type, unit,
616 		    (rsm_controller_t **)chdl);
617 	} else {
618 		e = _rsm_modload(cntr_type, unit, chdl);
619 	}
620 
621 	mutex_unlock(&_rsm_lock);
622 
623 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
624 	    " rsm_get_controller: exit\n"));
625 	return (e);
626 }
627 
628 int
629 rsm_release_controller(rsmapi_controller_handle_t cntr_handle)
630 {
631 	int			e = RSM_SUCCESS;
632 	rsm_controller_t	*chdl = (rsm_controller_t *)cntr_handle;
633 	rsm_controller_t	*curr, *prev;
634 
635 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
636 	    "rsm_release_controller: enter\n"));
637 
638 	mutex_lock(&_rsm_lock);
639 
640 	if (chdl->cntr_refcnt == 0) {
641 		mutex_unlock(&_rsm_lock);
642 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
643 		    "controller reference count is zero\n"));
644 		return (RSMERR_BAD_CTLR_HNDL);
645 	}
646 
647 	chdl->cntr_refcnt--;
648 
649 	if (chdl->cntr_refcnt > 0) {
650 		mutex_unlock(&_rsm_lock);
651 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
652 		    "rsm_release_controller: exit\n"));
653 		return (RSM_SUCCESS);
654 	}
655 
656 	e = chdl->cntr_segops->rsm_closedevice(cntr_handle);
657 
658 	/*
659 	 * remove the controller in any case from the controller list
660 	 */
661 
662 	prev = curr = controller_list;
663 	while (curr != NULL) {
664 		if (curr == chdl) {
665 			if (curr == prev) {
666 				controller_list = curr->cntr_next;
667 			} else {
668 				prev->cntr_next = curr->cntr_next;
669 			}
670 			free(curr);
671 			break;
672 		}
673 		prev = curr;
674 		curr = curr->cntr_next;
675 	}
676 	mutex_unlock(&_rsm_lock);
677 
678 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
679 	    "rsm_release_controller: exit\n"));
680 
681 	return (e);
682 }
683 
684 int
685 rsm_get_controller_attr(rsmapi_controller_handle_t chandle,
686     rsmapi_controller_attr_t *attr)
687 {
688 	rsm_controller_t *p;
689 
690 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
691 	    "rsm_get_controller_attr: enter\n"));
692 
693 	if (!chandle) {
694 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
695 		    "invalid controller handle\n"));
696 		return (RSMERR_BAD_CTLR_HNDL);
697 	}
698 
699 	if (!attr) {
700 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
701 		    "invalid attribute pointer\n"));
702 		return (RSMERR_BAD_ADDR);
703 	}
704 
705 	p = (rsm_controller_t *)chandle;
706 
707 	mutex_lock(&_rsm_lock);
708 	if (p->cntr_refcnt == 0) {
709 		mutex_unlock(&_rsm_lock);
710 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
711 		    "cntr refcnt is 0\n"));
712 		return (RSMERR_CTLR_NOT_PRESENT);
713 	}
714 
715 	/* copy only the user part of the attr structure */
716 	attr->attr_direct_access_sizes =
717 	    p->cntr_attr.attr_direct_access_sizes;
718 	attr->attr_atomic_sizes =
719 	    p->cntr_attr.attr_atomic_sizes;
720 	attr->attr_page_size =
721 	    p->cntr_attr.attr_page_size;
722 	attr->attr_max_export_segment_size =
723 	    p->cntr_attr.attr_max_export_segment_size;
724 	attr->attr_tot_export_segment_size =
725 	    p->cntr_attr.attr_tot_export_segment_size;
726 	attr->attr_max_export_segments =
727 	    p->cntr_attr.attr_max_export_segments;
728 	attr->attr_max_import_map_size =
729 	    p->cntr_attr.attr_max_import_map_size;
730 	attr->attr_tot_import_map_size =
731 	    p->cntr_attr.attr_tot_import_map_size;
732 	attr->attr_max_import_segments =
733 	    p->cntr_attr.attr_max_import_segments;
734 
735 	mutex_unlock(&_rsm_lock);
736 
737 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
738 	    "rsm_get_controller_attr: exit\n"));
739 
740 	return (RSM_SUCCESS);
741 }
742 
743 
744 
745 /*
746  * Create a segment handle for the virtual address range specified
747  * by vaddr and size
748  */
749 int
750 rsm_memseg_export_create(rsmapi_controller_handle_t controller,
751     rsm_memseg_export_handle_t *memseg,
752     void *vaddr,
753     size_t length,
754     uint_t flags)
755 {
756 
757 	rsm_controller_t *chdl = (rsm_controller_t *)controller;
758 	rsmseg_handle_t *p;
759 	rsm_ioctlmsg_t msg;
760 	int e;
761 #ifndef	_LP64
762 	int tmpfd;
763 #endif
764 
765 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
766 	    "rsm_memseg_export_create: enter\n"));
767 
768 	if (!controller) {
769 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
770 		    "invalid controller handle\n"));
771 		return (RSMERR_BAD_CTLR_HNDL);
772 	}
773 	if (!memseg) {
774 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
775 		    "invalid segment handle\n"));
776 		return (RSMERR_BAD_SEG_HNDL);
777 	}
778 
779 	*memseg = 0;
780 
781 	/*
782 	 * Check vaddr and size alignment, both must be mmu page size
783 	 * aligned
784 	 */
785 	if (!vaddr) {
786 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
787 		    "invalid arguments\n"));
788 		return (RSMERR_BAD_ADDR);
789 	}
790 
791 	if (!length) {
792 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
793 		    "invalid arguments\n"));
794 		return (RSMERR_BAD_LENGTH);
795 	}
796 
797 	if (((size_t)vaddr & (PAGESIZE - 1)) ||
798 	    (length & (PAGESIZE - 1))) {
799 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
800 		    "invalid mem alignment for vaddr or length\n"));
801 		return (RSMERR_BAD_MEM_ALIGNMENT);
802 	}
803 
804 	/*
805 	 * The following check does not apply for loopback controller
806 	 * since for the loopback adapter, the attr_max_export_segment_size
807 	 * is always 0.
808 	 */
809 	if (strcasecmp(chdl->cntr_name, LOOPBACK)) {
810 		if (length > chdl->cntr_attr.attr_max_export_segment_size) {
811 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
812 			    "length exceeds controller limits\n"));
813 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
814 			    "controller limits %d\n",
815 			    chdl->cntr_attr.attr_max_export_segment_size));
816 			return (RSMERR_BAD_LENGTH);
817 		}
818 	}
819 
820 	p = (rsmseg_handle_t *)malloc(sizeof (*p));
821 	if (p == NULL) {
822 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
823 		    "not enough memory\n"));
824 		return (RSMERR_INSUFFICIENT_MEM);
825 	}
826 
827 	p->rsmseg_fd = open(DEVRSM, O_RDWR);
828 	if (p->rsmseg_fd < 0) {
829 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
830 		    "unable to open device /dev/rsm\n"));
831 		free((void *)p);
832 		return (RSMERR_INSUFFICIENT_RESOURCES);
833 	}
834 
835 #ifndef	_LP64
836 	/*
837 	 * libc can't handle fd's greater than 255,  in order to
838 	 * insure that these values remain available make /dev/rsm
839 	 * fd > 255. Note: not needed for LP64
840 	 */
841 	tmpfd = fcntl(p->rsmseg_fd, F_DUPFD, 256);
842 	e = errno;
843 	if (tmpfd < 0) {
844 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
845 		    "F_DUPFD failed\n"));
846 	} else {
847 		(void) close(p->rsmseg_fd);
848 		p->rsmseg_fd = tmpfd;
849 	}
850 #endif	/*	_LP64	*/
851 
852 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE, ""
853 	    "rsmseg_fd is %d\n", p->rsmseg_fd));
854 
855 	if (fcntl(p->rsmseg_fd, F_SETFD, FD_CLOEXEC) < 0) {
856 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
857 		    "F_SETFD failed\n"));
858 	}
859 
860 	p->rsmseg_state = EXPORT_CREATE;
861 	p->rsmseg_size = length;
862 	/* increment controller handle */
863 	p->rsmseg_controller = chdl;
864 
865 	/* try to bind user address range */
866 	msg.cnum = chdl->cntr_unit;
867 	msg.cname = chdl->cntr_name;
868 	msg.cname_len = strlen(chdl->cntr_name) +1;
869 	msg.vaddr = vaddr;
870 	msg.len = length;
871 	msg.perm = flags;
872 	msg.off = 0;
873 	e = RSM_IOCTL_BIND;
874 
875 	/* Try to bind */
876 	if (ioctl(p->rsmseg_fd, e, &msg) < 0) {
877 		e = errno;
878 		(void) close(p->rsmseg_fd);
879 		free((void *)p);
880 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
881 		    "RSM_IOCTL_BIND failed\n"));
882 		return (e);
883 	}
884 	/* OK */
885 	p->rsmseg_type = RSM_EXPORT_SEG;
886 	p->rsmseg_vaddr = vaddr;
887 	p->rsmseg_size = length;
888 	p->rsmseg_state = EXPORT_BIND;
889 	p->rsmseg_pollfd_refcnt = 0;
890 	p->rsmseg_rnum = msg.rnum;
891 
892 	mutex_init(&p->rsmseg_lock, USYNC_THREAD, NULL);
893 
894 	*memseg = (rsm_memseg_export_handle_t)p;
895 
896 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
897 	    "rsm_memseg_export_create: exit\n"));
898 
899 	return (RSM_SUCCESS);
900 }
901 
902 int
903 rsm_memseg_export_destroy(rsm_memseg_export_handle_t memseg)
904 {
905 	rsmseg_handle_t *seg;
906 
907 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
908 	    "rsm_memseg_export_destroy: enter\n"));
909 
910 	if (!memseg) {
911 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
912 		    "invalid segment handle\n"));
913 		return (RSMERR_BAD_SEG_HNDL);
914 	}
915 
916 	seg = (rsmseg_handle_t *)memseg;
917 
918 	mutex_lock(&seg->rsmseg_lock);
919 	if (seg->rsmseg_pollfd_refcnt) {
920 		mutex_unlock(&seg->rsmseg_lock);
921 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
922 		    "segment reference count not zero\n"));
923 		return (RSMERR_POLLFD_IN_USE);
924 	}
925 	else
926 		seg->rsmseg_state = EXPORT_BIND;
927 
928 	mutex_unlock(&seg->rsmseg_lock);
929 
930 	(void) close(seg->rsmseg_fd);
931 	mutex_destroy(&seg->rsmseg_lock);
932 	free((void *)seg);
933 
934 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
935 	    "rsm_memseg_export_destroy: exit\n"));
936 
937 	return (RSM_SUCCESS);
938 }
939 
940 int
941 rsm_memseg_export_rebind(rsm_memseg_export_handle_t memseg, void *vaddr,
942     offset_t off, size_t length)
943 {
944 	rsm_ioctlmsg_t msg;
945 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
946 
947 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
948 	    "rsm_memseg_export_rebind: enter\n"));
949 
950 	off = off;
951 
952 	if (!seg) {
953 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
954 		    "invalid segment handle\n"));
955 		return (RSMERR_BAD_SEG_HNDL);
956 	}
957 	if (!vaddr) {
958 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
959 		    "invalid vaddr\n"));
960 		return (RSMERR_BAD_ADDR);
961 	}
962 
963 	/*
964 	 * Same as bind except it's ok to have elimint in list.
965 	 * Call into driver to remove any existing mappings.
966 	 */
967 	msg.vaddr = vaddr;
968 	msg.len = length;
969 	msg.off = 0;
970 
971 	mutex_lock(&seg->rsmseg_lock);
972 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_REBIND, &msg) < 0) {
973 		mutex_unlock(&seg->rsmseg_lock);
974 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
975 		    "RSM_IOCTL_REBIND failed\n"));
976 		return (errno);
977 	}
978 
979 	mutex_unlock(&seg->rsmseg_lock);
980 
981 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
982 	    "rsm_memseg_export_rebind: exit\n"));
983 
984 	return (RSM_SUCCESS);
985 }
986 
987 int
988 rsm_memseg_export_publish(rsm_memseg_export_handle_t memseg,
989     rsm_memseg_id_t *seg_id,
990     rsmapi_access_entry_t access_list[],
991     uint_t access_list_length)
992 
993 {
994 	rsm_ioctlmsg_t msg;
995 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
996 
997 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
998 	    "rsm_memseg_export_publish: enter\n"));
999 
1000 	if (seg_id == NULL) {
1001 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1002 		    "invalid segment id\n"));
1003 		return (RSMERR_BAD_SEGID);
1004 	}
1005 
1006 	if (!seg) {
1007 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1008 		    "invalid segment handle\n"));
1009 		return (RSMERR_BAD_SEG_HNDL);
1010 	}
1011 
1012 	if (access_list_length > 0 && !access_list) {
1013 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1014 		    "invalid access control list\n"));
1015 		return (RSMERR_BAD_ACL);
1016 	}
1017 
1018 	mutex_lock(&seg->rsmseg_lock);
1019 	if (seg->rsmseg_state != EXPORT_BIND) {
1020 		mutex_unlock(&seg->rsmseg_lock);
1021 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1022 		    "invalid segment state\n"));
1023 		return (RSMERR_SEG_ALREADY_PUBLISHED);
1024 	}
1025 
1026 	/*
1027 	 * seg id < RSM_DLPI_END and in the RSM_USER_APP_ID range
1028 	 * are reserved for internal use.
1029 	 */
1030 	if ((*seg_id > 0) &&
1031 	    ((*seg_id <= RSM_DLPI_ID_END) ||
1032 	    BETWEEN (*seg_id, RSM_USER_APP_ID_BASE, RSM_USER_APP_ID_END))) {
1033 		mutex_unlock(&seg->rsmseg_lock);
1034 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1035 		    "invalid segment id\n"));
1036 		return (RSMERR_RESERVED_SEGID);
1037 	}
1038 
1039 	msg.key = *seg_id;
1040 	msg.acl = access_list;
1041 	msg.acl_len = access_list_length;
1042 
1043 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_PUBLISH, &msg) < 0) {
1044 		mutex_unlock(&seg->rsmseg_lock);
1045 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1046 		    "RSM_IOCTL_PUBLISH failed\n"));
1047 		return (errno);
1048 	}
1049 
1050 	seg->rsmseg_keyid = msg.key;
1051 	seg->rsmseg_state = EXPORT_PUBLISH;
1052 	mutex_unlock(&seg->rsmseg_lock);
1053 
1054 	if (*seg_id == 0)
1055 		*seg_id = msg.key;
1056 
1057 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1058 	    "rsm_memseg_export_publish: exit\n"));
1059 
1060 	return (RSM_SUCCESS);
1061 
1062 }
1063 
1064 int
1065 rsm_memseg_export_unpublish(rsm_memseg_export_handle_t memseg)
1066 {
1067 	rsm_ioctlmsg_t msg;
1068 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1069 
1070 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1071 	    "rsm_memseg_export_unpublish: enter\n"));
1072 
1073 	if (!seg) {
1074 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1075 		    "invalid arguments\n"));
1076 		return (RSMERR_BAD_SEG_HNDL);
1077 	}
1078 
1079 	mutex_lock(&seg->rsmseg_lock);
1080 	if (seg->rsmseg_state != EXPORT_PUBLISH) {
1081 		mutex_unlock(&seg->rsmseg_lock);
1082 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1083 		    "segment not published %d\n",
1084 		    seg->rsmseg_keyid));
1085 		return (RSMERR_SEG_NOT_PUBLISHED);
1086 	}
1087 
1088 	msg.key = seg->rsmseg_keyid;
1089 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_UNPUBLISH, &msg) < 0) {
1090 		mutex_unlock(&seg->rsmseg_lock);
1091 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1092 		    "RSM_IOCTL_UNPUBLISH failed\n"));
1093 		return (errno);
1094 	}
1095 
1096 	seg->rsmseg_state = EXPORT_BIND;
1097 	mutex_unlock(&seg->rsmseg_lock);
1098 
1099 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1100 	    "rsm_memseg_export_unpublish: exit\n"));
1101 
1102 	return (RSM_SUCCESS);
1103 }
1104 
1105 
1106 int
1107 rsm_memseg_export_republish(rsm_memseg_export_handle_t memseg,
1108     rsmapi_access_entry_t access_list[],
1109     uint_t access_list_length)
1110 {
1111 	rsm_ioctlmsg_t msg;
1112 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1113 
1114 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1115 	    "rsm_memseg_export_republish: enter\n"));
1116 
1117 	if (!seg) {
1118 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1119 		    "invalid segment or segment state\n"));
1120 		return (RSMERR_BAD_SEG_HNDL);
1121 	}
1122 
1123 	mutex_lock(&seg->rsmseg_lock);
1124 	if (seg->rsmseg_state != EXPORT_PUBLISH) {
1125 		mutex_unlock(&seg->rsmseg_lock);
1126 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1127 		    "segment not published\n"));
1128 		return (RSMERR_SEG_NOT_PUBLISHED);
1129 	}
1130 
1131 	if (access_list_length > 0 && !access_list) {
1132 		mutex_unlock(&seg->rsmseg_lock);
1133 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1134 		    "invalid access control list\n"));
1135 		return (RSMERR_BAD_ACL);
1136 	}
1137 
1138 	msg.key = seg->rsmseg_keyid;
1139 	msg.acl = access_list;
1140 	msg.acl_len = access_list_length;
1141 
1142 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_REPUBLISH, &msg) < 0) {
1143 		mutex_unlock(&seg->rsmseg_lock);
1144 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1145 		    "RSM_IOCTL_REPUBLISH failed\n"));
1146 		return (errno);
1147 	}
1148 	mutex_unlock(&seg->rsmseg_lock);
1149 
1150 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1151 	    "rsm_memseg_export_republish: exit\n"));
1152 
1153 	return (RSM_SUCCESS);
1154 }
1155 
1156 
1157 	/*
1158 	 * import side memory segment operations:
1159 	 */
1160 int
1161 rsm_memseg_import_connect(rsmapi_controller_handle_t controller,
1162     rsm_node_id_t node_id,
1163     rsm_memseg_id_t segment_id,
1164     rsm_permission_t perm,
1165     rsm_memseg_import_handle_t *im_memseg)
1166 {
1167 	rsm_ioctlmsg_t msg;
1168 	rsmseg_handle_t *p;
1169 	rsm_controller_t *cntr = (rsm_controller_t *)controller;
1170 #ifndef	_LP64		/* added for fd > 255 fix */
1171 	int tmpfd;
1172 #endif
1173 	int e;
1174 
1175 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1176 	    "rsm_memseg_import_connect: enter\n"));
1177 
1178 	if (!cntr) {
1179 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1180 		    "invalid controller handle\n"));
1181 		return (RSMERR_BAD_CTLR_HNDL);
1182 	}
1183 
1184 	*im_memseg = 0;
1185 
1186 	p = (rsmseg_handle_t *)malloc(sizeof (*p));
1187 	if (!p) {
1188 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1189 		    "not enough memory\n"));
1190 		return (RSMERR_INSUFFICIENT_MEM);
1191 	}
1192 
1193 	if (perm & ~RSM_PERM_RDWR) {
1194 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1195 		    "invalid permissions\n"));
1196 		return (RSMERR_PERM_DENIED);
1197 	}
1198 
1199 	/*
1200 	 * Get size, va from driver
1201 	 */
1202 	msg.cnum = cntr->cntr_unit;
1203 	msg.cname = cntr->cntr_name;
1204 	msg.cname_len = strlen(cntr->cntr_name) +1;
1205 	msg.nodeid = node_id;
1206 	msg.key = segment_id;
1207 	msg.perm = perm;
1208 
1209 	p->rsmseg_fd = open(DEVRSM, O_RDWR);
1210 	if (p->rsmseg_fd < 0) {
1211 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1212 		    "unable to open /dev/rsm"));
1213 		free((void *)p);
1214 		return (RSMERR_INSUFFICIENT_RESOURCES);
1215 	}
1216 
1217 #ifndef	_LP64
1218 	/*
1219 	 * libc can't handle fd's greater than 255,  in order to
1220 	 * insure that these values remain available make /dev/rsm
1221 	 * fd > 255. Note: not needed for LP64
1222 	 */
1223 	tmpfd = fcntl(p->rsmseg_fd, F_DUPFD, 256); /* make fd > 255 */
1224 	e = errno;
1225 	if (tmpfd < 0) {
1226 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1227 		    "F_DUPFD failed\n"));
1228 	} else {
1229 		(void) close(p->rsmseg_fd);
1230 		p->rsmseg_fd = tmpfd;
1231 	}
1232 #endif	/* _LP64 */
1233 
1234 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
1235 	    "rsmseg_fd is %d\n", p->rsmseg_fd));
1236 
1237 	if (fcntl(p->rsmseg_fd, F_SETFD, FD_CLOEXEC) < 0) {
1238 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1239 		    "F_SETFD failed\n"));
1240 	}
1241 	if (ioctl(p->rsmseg_fd, RSM_IOCTL_CONNECT, &msg) < 0) {
1242 		e = errno;
1243 		(void) close(p->rsmseg_fd);
1244 		free((void *)p);
1245 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1246 		    "RSM_IOCTL_CONNECT failed\n"));
1247 		return (e);
1248 	}
1249 
1250 	/*
1251 	 * We connected ok.
1252 	 */
1253 	p->rsmseg_type = RSM_IMPORT_SEG;
1254 	p->rsmseg_state = IMPORT_CONNECT;
1255 	p->rsmseg_keyid = segment_id;
1256 	p->rsmseg_nodeid = node_id;
1257 	p->rsmseg_size = msg.len;
1258 	p->rsmseg_perm = perm;
1259 	p->rsmseg_controller = cntr;
1260 	p->rsmseg_barrier = NULL;
1261 	p->rsmseg_barmode = RSM_BARRIER_MODE_IMPLICIT;
1262 	p->rsmseg_bar = (bar_va ? bar_va + msg.off : &bar_fixed);
1263 	p->rsmseg_gnum = msg.gnum;
1264 	p->rsmseg_pollfd_refcnt = 0;
1265 	p->rsmseg_maplen = 0;    /* initialized, set in import_map */
1266 	p->rsmseg_mapoffset = 0;
1267 	p->rsmseg_flags = 0;
1268 	p->rsmseg_rnum = msg.rnum;
1269 	mutex_init(&p->rsmseg_lock, USYNC_THREAD, NULL);
1270 
1271 	p->rsmseg_ops = cntr->cntr_segops;
1272 
1273 	/*
1274 	 * XXX: Based on permission and controller direct_access attribute
1275 	 * we fix the segment ops vector
1276 	 */
1277 
1278 	p->rsmseg_vaddr = 0; /* defer mapping till using maps or trys to rw */
1279 
1280 	*im_memseg = (rsm_memseg_import_handle_t)p;
1281 
1282 	e =  p->rsmseg_ops->rsm_memseg_import_connect(controller,
1283 	    node_id, segment_id, perm, im_memseg);
1284 
1285 	if (e != RSM_SUCCESS) {
1286 		(void) close(p->rsmseg_fd);
1287 		mutex_destroy(&p->rsmseg_lock);
1288 		free((void *)p);
1289 	}
1290 
1291 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1292 	    "rsm_memseg_import_connect: exit\n"));
1293 
1294 	return (e);
1295 }
1296 
1297 
1298 int
1299 rsm_memseg_import_disconnect(rsm_memseg_import_handle_t im_memseg)
1300 {
1301 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1302 	int e;
1303 
1304 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1305 	    "rsm_memseg_import_disconnect: enter\n"));
1306 
1307 	if (!seg) {
1308 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1309 		    "invalid segment handle\n"));
1310 		return (RSMERR_BAD_SEG_HNDL);
1311 	}
1312 
1313 	if (seg->rsmseg_state != IMPORT_CONNECT) {
1314 		if (seg->rsmseg_flags & RSM_IMPLICIT_MAP) {
1315 			e = rsm_memseg_import_unmap(im_memseg);
1316 			if (e != RSM_SUCCESS) {
1317 				DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1318 				    "unmap failure\n"));
1319 				return (e);
1320 			}
1321 		} else {
1322 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1323 			    "segment busy\n"));
1324 			return (RSMERR_SEG_STILL_MAPPED);
1325 		}
1326 	}
1327 
1328 	mutex_lock(&seg->rsmseg_lock);
1329 	if (seg->rsmseg_pollfd_refcnt) {
1330 		mutex_unlock(&seg->rsmseg_lock);
1331 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1332 		    "segment reference count not zero\n"));
1333 		return (RSMERR_POLLFD_IN_USE);
1334 	}
1335 	mutex_unlock(&seg->rsmseg_lock);
1336 
1337 	e =  seg->rsmseg_ops->rsm_memseg_import_disconnect(im_memseg);
1338 
1339 	if (e == RSM_SUCCESS) {
1340 		(void) close(seg->rsmseg_fd);
1341 		mutex_destroy(&seg->rsmseg_lock);
1342 		free((void *)seg);
1343 	}
1344 
1345 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1346 	    "rsm_memseg_import_disconnect: exit\n"));
1347 
1348 	return (e);
1349 }
1350 
1351 /*
1352  * import side memory segment operations (read access functions):
1353  */
1354 
1355 static int
1356 __rsm_import_verify_access(rsmseg_handle_t *seg,
1357     off_t offset,
1358     caddr_t datap,
1359     size_t len,
1360     rsm_permission_t perm,
1361     rsm_access_size_t das)
1362 {
1363 	int	error;
1364 
1365 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1366 	    " __rsm_import_verify_access: enter\n"));
1367 
1368 	if (!seg) {
1369 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1370 		    "invalid segment handle\n"));
1371 		return (RSMERR_BAD_SEG_HNDL);
1372 	}
1373 	if (!datap) {
1374 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1375 		    "invalid data pointer\n"));
1376 		return (RSMERR_BAD_ADDR);
1377 	}
1378 
1379 	/*
1380 	 * Check alignment of pointer
1381 	 */
1382 	if ((uintptr_t)datap & (das - 1)) {
1383 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1384 		    "invalid alignment of data pointer\n"));
1385 		return (RSMERR_BAD_MEM_ALIGNMENT);
1386 	}
1387 
1388 	if (offset & (das - 1)) {
1389 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1390 		    "invalid offset\n"));
1391 		return (RSMERR_BAD_MEM_ALIGNMENT);
1392 	}
1393 
1394 	/* make sure that the import seg is connected */
1395 	if (seg->rsmseg_state != IMPORT_CONNECT &&
1396 	    seg->rsmseg_state != IMPORT_MAP) {
1397 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1398 		    "incorrect segment state\n"));
1399 		return (RSMERR_BAD_SEG_HNDL);
1400 	}
1401 
1402 	/* do an implicit map if required */
1403 	if (seg->rsmseg_state == IMPORT_CONNECT) {
1404 		error = __rsm_import_implicit_map(seg, RSM_IOTYPE_PUTGET);
1405 		if (error != RSM_SUCCESS) {
1406 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1407 			    "implicit map failure\n"));
1408 			return (error);
1409 		}
1410 	}
1411 
1412 	if ((seg->rsmseg_perm & perm) != perm) {
1413 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1414 		    "invalid permissions\n"));
1415 		return (RSMERR_PERM_DENIED);
1416 	}
1417 
1418 	if (seg->rsmseg_state == IMPORT_MAP) {
1419 		if ((offset < seg->rsmseg_mapoffset) ||
1420 		    (offset + len > seg->rsmseg_mapoffset +
1421 		    seg->rsmseg_maplen)) {
1422 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1423 			    "incorrect offset+length\n"));
1424 			return (RSMERR_BAD_OFFSET);
1425 		}
1426 	} else { /* IMPORT_CONNECT */
1427 		if ((len + offset) > seg->rsmseg_size) {
1428 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1429 			    "incorrect offset+length\n"));
1430 			return (RSMERR_BAD_LENGTH);
1431 		}
1432 	}
1433 
1434 	if ((seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) &&
1435 	    (seg->rsmseg_barrier == NULL)) {
1436 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1437 		    "invalid barrier\n"));
1438 		return (RSMERR_BARRIER_UNINITIALIZED);
1439 	}
1440 
1441 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1442 	    " __rsm_import_verify_access: exit\n"));
1443 
1444 	return (RSM_SUCCESS);
1445 }
1446 
1447 static int
1448 __rsm_import_implicit_map(rsmseg_handle_t *seg, int iotype)
1449 {
1450 	caddr_t va;
1451 	int flag = MAP_SHARED;
1452 	int prot = PROT_READ|PROT_WRITE;
1453 	int mapping_reqd = 0;
1454 
1455 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1456 	    " __rsm_import_implicit_map: enter\n"));
1457 
1458 	if (iotype == RSM_IOTYPE_PUTGET)
1459 		mapping_reqd = seg->rsmseg_controller->cntr_lib_attr->
1460 		    rsm_putget_map_reqd;
1461 	else if (iotype == RSM_IOTYPE_SCATGATH)
1462 		mapping_reqd = seg->rsmseg_controller->cntr_lib_attr->
1463 		    rsm_scatgath_map_reqd;
1464 
1465 
1466 	if (mapping_reqd) {
1467 		va = mmap(NULL, seg->rsmseg_size, prot,
1468 		    flag, seg->rsmseg_fd, 0);
1469 
1470 		if (va == MAP_FAILED) {
1471 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1472 			    "implicit map failed\n"));
1473 			if (errno == ENOMEM || errno == ENXIO ||
1474 			    errno == EOVERFLOW)
1475 				return (RSMERR_BAD_LENGTH);
1476 			else if (errno == ENODEV)
1477 				return (RSMERR_CONN_ABORTED);
1478 			else if (errno == EAGAIN)
1479 				return (RSMERR_INSUFFICIENT_RESOURCES);
1480 			else if (errno == ENOTSUP)
1481 				return (RSMERR_MAP_FAILED);
1482 			else if (errno == EACCES)
1483 				return (RSMERR_BAD_PERMS);
1484 			else
1485 				return (RSMERR_MAP_FAILED);
1486 		}
1487 		seg->rsmseg_vaddr = va;
1488 		seg->rsmseg_maplen = seg->rsmseg_size;
1489 		seg->rsmseg_mapoffset = 0;
1490 		seg->rsmseg_state = IMPORT_MAP;
1491 		seg->rsmseg_flags |= RSM_IMPLICIT_MAP;
1492 	}
1493 
1494 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1495 	    " __rsm_import_implicit_map: exit\n"));
1496 
1497 	return (RSM_SUCCESS);
1498 }
1499 
1500 int
1501 rsm_memseg_import_get8(rsm_memseg_import_handle_t im_memseg,
1502     off_t offset,
1503     uint8_t *datap,
1504     ulong_t rep_cnt)
1505 {
1506 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1507 	int e;
1508 
1509 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1510 	    "rsm_memseg_import_get8: enter\n"));
1511 
1512 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt,
1513 	    RSM_PERM_READ,
1514 	    RSM_DAS8);
1515 	if (e == RSM_SUCCESS) {
1516 		rsm_segops_t *ops = seg->rsmseg_ops;
1517 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1518 
1519 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1520 			/* generation number snapshot */
1521 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1522 		}
1523 
1524 		e = ops->rsm_memseg_import_get8(im_memseg, offset, datap,
1525 		    rep_cnt, 0);
1526 
1527 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1528 			/* check the generation number for force disconnects */
1529 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1530 				return (RSMERR_CONN_ABORTED);
1531 			}
1532 		}
1533 	}
1534 
1535 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1536 	    "rsm_memseg_import_get8: exit\n"));
1537 
1538 	return (e);
1539 }
1540 
1541 int
1542 rsm_memseg_import_get16(rsm_memseg_import_handle_t im_memseg,
1543     off_t offset,
1544     uint16_t *datap,
1545     ulong_t rep_cnt)
1546 {
1547 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1548 	int e;
1549 
1550 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1551 	    "rsm_memseg_import_get16: enter\n"));
1552 
1553 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*2,
1554 	    RSM_PERM_READ,
1555 	    RSM_DAS16);
1556 	if (e == RSM_SUCCESS) {
1557 		rsm_segops_t *ops = seg->rsmseg_ops;
1558 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1559 
1560 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1561 			/* generation number snapshot */
1562 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1563 		}
1564 
1565 		e = ops->rsm_memseg_import_get16(im_memseg, offset, datap,
1566 		    rep_cnt, 0);
1567 
1568 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1569 			/* check the generation number for force disconnects */
1570 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1571 				return (RSMERR_CONN_ABORTED);
1572 			}
1573 		}
1574 
1575 	}
1576 
1577 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1578 	    "rsm_memseg_import_get16: exit\n"));
1579 
1580 	return (e);
1581 }
1582 
1583 int
1584 rsm_memseg_import_get32(rsm_memseg_import_handle_t im_memseg,
1585     off_t offset,
1586     uint32_t *datap,
1587     ulong_t rep_cnt)
1588 {
1589 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1590 	int e;
1591 
1592 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1593 	    "rsm_memseg_import_get32: enter\n"));
1594 
1595 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*4,
1596 	    RSM_PERM_READ,
1597 	    RSM_DAS32);
1598 	if (e == RSM_SUCCESS) {
1599 		rsm_segops_t *ops = seg->rsmseg_ops;
1600 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1601 
1602 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1603 			/* generation number snapshot */
1604 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1605 		}
1606 
1607 		e = ops->rsm_memseg_import_get32(im_memseg, offset, datap,
1608 		    rep_cnt, 0);
1609 
1610 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1611 			/* check the generation number for force disconnects */
1612 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1613 				return (RSMERR_CONN_ABORTED);
1614 			}
1615 		}
1616 	}
1617 
1618 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1619 	    "rsm_memseg_import_get32: exit\n"));
1620 
1621 	return (e);
1622 }
1623 
1624 int
1625 rsm_memseg_import_get64(rsm_memseg_import_handle_t im_memseg,
1626     off_t offset,
1627     uint64_t *datap,
1628     ulong_t rep_cnt)
1629 {
1630 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1631 	int e;
1632 
1633 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1634 	    "rsm_memseg_import_get64: enter\n"));
1635 
1636 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*8,
1637 	    RSM_PERM_READ,
1638 	    RSM_DAS64);
1639 	if (e == RSM_SUCCESS) {
1640 		rsm_segops_t *ops = seg->rsmseg_ops;
1641 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1642 
1643 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1644 			/* generation number snapshot */
1645 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1646 		}
1647 
1648 		e = ops->rsm_memseg_import_get64(im_memseg, offset, datap,
1649 		    rep_cnt, 0);
1650 
1651 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1652 			/* check the generation number for force disconnects */
1653 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1654 				return (RSMERR_CONN_ABORTED);
1655 			}
1656 		}
1657 	}
1658 
1659 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1660 	    "rsm_memseg_import_get64: exit\n"));
1661 
1662 	return (e);
1663 }
1664 
1665 int
1666 rsm_memseg_import_get(rsm_memseg_import_handle_t im_memseg,
1667     off_t offset,
1668     void *dst_addr,
1669     size_t length)
1670 {
1671 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1672 	int e;
1673 
1674 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1675 	    "rsm_memseg_import_get: enter\n"));
1676 
1677 	e = __rsm_import_verify_access(seg, offset, (caddr_t)dst_addr, length,
1678 	    RSM_PERM_READ,
1679 	    RSM_DAS8);
1680 	if (e == RSM_SUCCESS) {
1681 		rsm_segops_t *ops = seg->rsmseg_ops;
1682 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1683 
1684 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1685 			/* generation number snapshot */
1686 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1687 		}
1688 
1689 		e = ops->rsm_memseg_import_get(im_memseg, offset, dst_addr,
1690 		    length);
1691 
1692 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1693 			/* check the generation number for force disconnects */
1694 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1695 				return (RSMERR_CONN_ABORTED);
1696 			}
1697 		}
1698 	}
1699 
1700 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1701 	    "rsm_memseg_import_get: exit\n"));
1702 
1703 	return (e);
1704 }
1705 
1706 
1707 int
1708 rsm_memseg_import_getv(rsm_scat_gath_t *sg_io)
1709 {
1710 	rsm_controller_t *cntrl;
1711 	rsmseg_handle_t *seg;
1712 	uint_t save_sg_io_flags;
1713 
1714 	int e;
1715 
1716 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1717 	    "rsm_memseg_import_getv: enter\n"));
1718 
1719 	if (sg_io == NULL) {
1720 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1721 		    "invalid sg_io structure\n"));
1722 		return (RSMERR_BAD_SGIO);
1723 	}
1724 
1725 	seg = (rsmseg_handle_t *)sg_io->remote_handle;
1726 	if (seg == NULL) {
1727 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1728 		    "invalid remote segment handle in sg_io\n"));
1729 		return (RSMERR_BAD_SEG_HNDL);
1730 	}
1731 
1732 	cntrl = (rsm_controller_t *)seg->rsmseg_controller;
1733 	if (cntrl == NULL) {
1734 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1735 		    "invalid controller handle\n"));
1736 		return (RSMERR_BAD_SEG_HNDL);
1737 	}
1738 
1739 	if ((sg_io->io_request_count > RSM_MAX_SGIOREQS) ||
1740 	    (sg_io->io_request_count == 0)) {
1741 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1742 		    "io_request_count value incorrect\n"));
1743 		return (RSMERR_BAD_SGIO);
1744 	}
1745 
1746 	if (seg->rsmseg_state == IMPORT_CONNECT) {
1747 		e = __rsm_import_implicit_map(seg, RSM_IOTYPE_SCATGATH);
1748 		if (e != RSM_SUCCESS) {
1749 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1750 			    "implicit map failure\n"));
1751 			return (e);
1752 		}
1753 	}
1754 
1755 	/*
1756 	 * Copy the flags field of the sg_io structure in a local
1757 	 * variable.
1758 	 * This is required since the flags field can be
1759 	 * changed by the plugin library routine to indicate that
1760 	 * the signal post was done.
1761 	 * This change in the flags field of the sg_io structure
1762 	 * should not be reflected to the user. Hence once the flags
1763 	 * field has been used for the purpose of determining whether
1764 	 * the plugin executed a signal post, it must be restored to
1765 	 * its original value which is stored in the local variable.
1766 	 */
1767 	save_sg_io_flags = sg_io->flags;
1768 
1769 	e = cntrl->cntr_segops->rsm_memseg_import_getv(sg_io);
1770 
1771 	/*
1772 	 * At this point, if an implicit signal post was requested by
1773 	 * the user, there could be two possibilities that arise:
1774 	 * 1. the plugin routine has already executed the implicit
1775 	 *    signal post either successfully or unsuccessfully
1776 	 * 2. the plugin does not have the capability of doing an
1777 	 *    implicit signal post and hence the signal post needs
1778 	 *    to be done here.
1779 	 * The above two cases can be idenfied by the flags
1780 	 * field within the sg_io structure as follows:
1781 	 * In case 1, the RSM_IMPLICIT_SIGPOST bit is reset to 0 by the
1782 	 * plugin, indicating that the signal post was done.
1783 	 * In case 2, the bit remains set to a 1 as originally given
1784 	 * by the user, and hence a signal post needs to be done here.
1785 	 */
1786 	if (sg_io->flags & RSM_IMPLICIT_SIGPOST &&
1787 	    e == RSM_SUCCESS) {
1788 		/* Do the implicit signal post */
1789 
1790 		/*
1791 		 * The value of the second argument to this call
1792 		 * depends on the value of the sg_io->flags field.
1793 		 * If the RSM_SIGPOST_NO_ACCUMULATE flag has been
1794 		 * ored into the sg_io->flags field, this indicates
1795 		 * that the rsm_intr_signal_post is to be done with
1796 		 * the flags argument set to RSM_SIGPOST_NO_ACCUMULATE
1797 		 * Else, the flags argument is set to 0. These
1798 		 * semantics can be achieved simply by masking off
1799 		 * all other bits in the sg_io->flags field except the
1800 		 * RSM_SIGPOST_NO_ACCUMULATE bit and using the result
1801 		 * as the flags argument for the rsm_intr_signal_post.
1802 		 */
1803 
1804 		int sigpost_flags = sg_io->flags & RSM_SIGPOST_NO_ACCUMULATE;
1805 		e = rsm_intr_signal_post(seg, sigpost_flags);
1806 	}
1807 
1808 	/* Restore the flags field within the users scatter gather structure */
1809 	sg_io->flags = save_sg_io_flags;
1810 
1811 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1812 	    "rsm_memseg_import_getv: exit\n"));
1813 
1814 	return (e);
1815 
1816 }
1817 
1818 	/*
1819 	 * import side memory segment operations (write access functions):
1820 	 */
1821 
1822 int
1823 rsm_memseg_import_put8(rsm_memseg_import_handle_t im_memseg,
1824     off_t offset,
1825     uint8_t *datap,
1826     ulong_t rep_cnt)
1827 {
1828 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1829 	int e;
1830 
1831 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1832 	    "rsm_memseg_import_put8: enter\n"));
1833 
1834 	/* addr of data will always pass the alignment check, avoids	*/
1835 	/* need for a special case in verify_access for PUTs		*/
1836 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt,
1837 	    RSM_PERM_WRITE,
1838 	    RSM_DAS8);
1839 	if (e == RSM_SUCCESS) {
1840 		rsm_segops_t *ops = seg->rsmseg_ops;
1841 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1842 
1843 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1844 			/* generation number snapshot */
1845 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1846 		}
1847 
1848 		e = ops->rsm_memseg_import_put8(im_memseg, offset, datap,
1849 		    rep_cnt, 0);
1850 
1851 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1852 			/* check the generation number for force disconnects */
1853 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1854 				return (RSMERR_CONN_ABORTED);
1855 			}
1856 		}
1857 	}
1858 
1859 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1860 	    "rsm_memseg_import_put8: exit\n"));
1861 
1862 	return (e);
1863 }
1864 
1865 int
1866 rsm_memseg_import_put16(rsm_memseg_import_handle_t im_memseg,
1867     off_t offset,
1868     uint16_t *datap,
1869     ulong_t rep_cnt)
1870 {
1871 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1872 	int e;
1873 
1874 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1875 	    "rsm_memseg_import_put16: enter\n"));
1876 
1877 	/* addr of data will always pass the alignment check, avoids	*/
1878 	/* need for a special case in verify_access for PUTs		*/
1879 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*2,
1880 	    RSM_PERM_WRITE,
1881 	    RSM_DAS16);
1882 	if (e == RSM_SUCCESS) {
1883 		rsm_segops_t *ops = seg->rsmseg_ops;
1884 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1885 
1886 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1887 			/* generation number snapshot */
1888 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1889 		}
1890 
1891 		e = ops->rsm_memseg_import_put16(im_memseg, offset, datap,
1892 		    rep_cnt, 0);
1893 
1894 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1895 			/* check the generation number for force disconnects */
1896 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1897 				return (RSMERR_CONN_ABORTED);
1898 			}
1899 		}
1900 
1901 	}
1902 
1903 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1904 	    "rsm_memseg_import_put16: exit\n"));
1905 
1906 	return (e);
1907 }
1908 
1909 int
1910 rsm_memseg_import_put32(rsm_memseg_import_handle_t im_memseg,
1911     off_t offset,
1912     uint32_t *datap,
1913     ulong_t rep_cnt)
1914 {
1915 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1916 	int e;
1917 
1918 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1919 	    "rsm_memseg_import_put32: enter\n"));
1920 
1921 	/* addr of data will always pass the alignment check, avoids	*/
1922 	/* need for a special case in verify_access for PUTs		*/
1923 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*4,
1924 	    RSM_PERM_WRITE,
1925 	    RSM_DAS32);
1926 	if (e == RSM_SUCCESS) {
1927 		rsm_segops_t *ops = seg->rsmseg_ops;
1928 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1929 
1930 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1931 			/* generation number snapshot */
1932 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1933 		}
1934 
1935 		e = ops->rsm_memseg_import_put32(im_memseg, offset, datap,
1936 		    rep_cnt, 0);
1937 
1938 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1939 			/* check the generation number for force disconnects */
1940 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1941 				return (RSMERR_CONN_ABORTED);
1942 			}
1943 		}
1944 	}
1945 
1946 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1947 	    "rsm_memseg_import_put32: exit\n"));
1948 
1949 	return (e);
1950 }
1951 
1952 int
1953 rsm_memseg_import_put64(rsm_memseg_import_handle_t im_memseg,
1954     off_t offset,
1955     uint64_t *datap,
1956     ulong_t rep_cnt)
1957 {
1958 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1959 	int		e;
1960 
1961 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1962 	    "rsm_memseg_import_put64: enter\n"));
1963 
1964 	/* addr of data will always pass the alignment check, avoids	*/
1965 	/* need for a special case in verify_access for PUTs		*/
1966 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*8,
1967 	    RSM_PERM_WRITE,
1968 	    RSM_DAS64);
1969 	if (e == RSM_SUCCESS) {
1970 		rsm_segops_t *ops = seg->rsmseg_ops;
1971 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1972 
1973 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1974 			/* generation number snapshot */
1975 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1976 		}
1977 
1978 		e = ops->rsm_memseg_import_put64(im_memseg, offset, datap,
1979 		    rep_cnt, 0);
1980 
1981 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1982 			/* check the generation number for force disconnects */
1983 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1984 				return (RSMERR_CONN_ABORTED);
1985 			}
1986 		}
1987 	}
1988 
1989 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1990 	    "rsm_memseg_import_put64: exit\n"));
1991 
1992 	return (e);
1993 }
1994 
1995 int
1996 rsm_memseg_import_put(rsm_memseg_import_handle_t im_memseg,
1997     off_t offset,
1998     void *src_addr,
1999     size_t length)
2000 {
2001 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2002 	int e;
2003 
2004 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2005 	    "rsm_memseg_import_put: enter\n"));
2006 
2007 	e = __rsm_import_verify_access(seg, offset, (caddr_t)src_addr, length,
2008 	    RSM_PERM_WRITE,
2009 	    RSM_DAS8);
2010 	if (e == RSM_SUCCESS) {
2011 		rsm_segops_t *ops = seg->rsmseg_ops;
2012 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
2013 
2014 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2015 			/* generation number snapshot */
2016 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
2017 		}
2018 
2019 		e = ops->rsm_memseg_import_put(im_memseg, offset, src_addr,
2020 		    length);
2021 
2022 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2023 			/* check the generation number for force disconnects */
2024 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
2025 				return (RSMERR_CONN_ABORTED);
2026 			}
2027 		}
2028 
2029 	}
2030 
2031 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2032 	    "rsm_memseg_import_put: exit\n"));
2033 	return (e);
2034 }
2035 
2036 
2037 int
2038 rsm_memseg_import_putv(rsm_scat_gath_t *sg_io)
2039 {
2040 	rsm_controller_t *cntrl;
2041 	rsmseg_handle_t *seg;
2042 	uint_t save_sg_io_flags;
2043 
2044 	int e;
2045 
2046 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2047 	    "rsm_memseg_import_putv: enter\n"));
2048 
2049 
2050 	if (sg_io == NULL) {
2051 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2052 		    "invalid sg_io structure\n"));
2053 		return (RSMERR_BAD_SGIO);
2054 	}
2055 
2056 	seg = (rsmseg_handle_t *)sg_io->remote_handle;
2057 	if (seg == NULL) {
2058 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2059 		    "invalid remote segment handle in sg_io\n"));
2060 		return (RSMERR_BAD_SEG_HNDL);
2061 	}
2062 
2063 	cntrl = (rsm_controller_t *)seg->rsmseg_controller;
2064 	if (cntrl == NULL) {
2065 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2066 		    "invalid controller handle\n"));
2067 		return (RSMERR_BAD_SEG_HNDL);
2068 	}
2069 
2070 	if ((sg_io->io_request_count > RSM_MAX_SGIOREQS) ||
2071 	    (sg_io->io_request_count == 0)) {
2072 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2073 		    "io_request_count value incorrect\n"));
2074 		return (RSMERR_BAD_SGIO);
2075 	}
2076 
2077 	/* do an implicit map if required */
2078 	if (seg->rsmseg_state == IMPORT_CONNECT) {
2079 		e = __rsm_import_implicit_map(seg, RSM_IOTYPE_SCATGATH);
2080 		if (e != RSM_SUCCESS) {
2081 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2082 			    "implicit map failed\n"));
2083 			return (e);
2084 		}
2085 	}
2086 
2087 	/*
2088 	 * Copy the flags field of the sg_io structure in a local
2089 	 * variable.
2090 	 * This is required since the flags field can be
2091 	 * changed by the plugin library routine to indicate that
2092 	 * the signal post was done.
2093 	 * This change in the flags field of the sg_io structure
2094 	 * should not be reflected to the user. Hence once the flags
2095 	 * field has been used for the purpose of determining whether
2096 	 * the plugin executed a signal post, it must be restored to
2097 	 * its original value which is stored in the local variable.
2098 	 */
2099 	save_sg_io_flags = sg_io->flags;
2100 
2101 	e = cntrl->cntr_segops->rsm_memseg_import_putv(sg_io);
2102 
2103 	/*
2104 	 * At this point, if an implicit signal post was requested by
2105 	 * the user, there could be two possibilities that arise:
2106 	 * 1. the plugin routine has already executed the implicit
2107 	 *    signal post either successfully or unsuccessfully
2108 	 * 2. the plugin does not have the capability of doing an
2109 	 *    implicit signal post and hence the signal post needs
2110 	 *    to be done here.
2111 	 * The above two cases can be idenfied by the flags
2112 	 * field within the sg_io structure as follows:
2113 	 * In case 1, the RSM_IMPLICIT_SIGPOST bit is reset to 0 by the
2114 	 * plugin, indicating that the signal post was done.
2115 	 * In case 2, the bit remains set to a 1 as originally given
2116 	 * by the user, and hence a signal post needs to be done here.
2117 	 */
2118 	if (sg_io->flags & RSM_IMPLICIT_SIGPOST &&
2119 	    e == RSM_SUCCESS) {
2120 		/* Do the implicit signal post */
2121 
2122 		/*
2123 		 * The value of the second argument to this call
2124 		 * depends on the value of the sg_io->flags field.
2125 		 * If the RSM_SIGPOST_NO_ACCUMULATE flag has been
2126 		 * ored into the sg_io->flags field, this indicates
2127 		 * that the rsm_intr_signal_post is to be done with
2128 		 * the flags argument set to RSM_SIGPOST_NO_ACCUMULATE
2129 		 * Else, the flags argument is set to 0. These
2130 		 * semantics can be achieved simply by masking off
2131 		 * all other bits in the sg_io->flags field except the
2132 		 * RSM_SIGPOST_NO_ACCUMULATE bit and using the result
2133 		 * as the flags argument for the rsm_intr_signal_post.
2134 		 */
2135 
2136 		int sigpost_flags = sg_io->flags & RSM_SIGPOST_NO_ACCUMULATE;
2137 		e = rsm_intr_signal_post(seg, sigpost_flags);
2138 
2139 	}
2140 
2141 	/* Restore the flags field within the users scatter gather structure */
2142 	sg_io->flags = save_sg_io_flags;
2143 
2144 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2145 	    "rsm_memseg_import_putv: exit\n"));
2146 
2147 	return (e);
2148 }
2149 
2150 
2151 	/*
2152 	 * import side memory segment operations (mapping):
2153 	 */
2154 int
2155 rsm_memseg_import_map(rsm_memseg_import_handle_t im_memseg,
2156     void **address,
2157     rsm_attribute_t attr,
2158     rsm_permission_t perm,
2159     off_t offset,
2160     size_t length)
2161 {
2162 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2163 	int flag = MAP_SHARED;
2164 	int prot;
2165 	caddr_t va;
2166 
2167 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2168 	    "rsm_memseg_import_map: enter\n"));
2169 
2170 	if (!seg) {
2171 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2172 		    "invalid segment\n"));
2173 		return (RSMERR_BAD_SEG_HNDL);
2174 	}
2175 	if (!address) {
2176 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2177 		    "invalid address\n"));
2178 		return (RSMERR_BAD_ADDR);
2179 	}
2180 
2181 	/*
2182 	 * Only one map per segment handle!
2183 	 * XXX need to take a lock here
2184 	 */
2185 	mutex_lock(&seg->rsmseg_lock);
2186 
2187 	if (seg->rsmseg_state == IMPORT_MAP) {
2188 		mutex_unlock(&seg->rsmseg_lock);
2189 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2190 		    "segment already mapped\n"));
2191 		return (RSMERR_SEG_ALREADY_MAPPED);
2192 	}
2193 
2194 	/* Only import segments allowed to map */
2195 	if (seg->rsmseg_state != IMPORT_CONNECT) {
2196 		mutex_unlock(&seg->rsmseg_lock);
2197 		return (RSMERR_BAD_SEG_HNDL);
2198 	}
2199 
2200 	/* check for permissions */
2201 	if (perm > RSM_PERM_RDWR) {
2202 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2203 		    "bad permissions when mapping\n"));
2204 		mutex_unlock(&seg->rsmseg_lock);
2205 		return (RSMERR_BAD_PERMS);
2206 	}
2207 
2208 	if (length == 0) {
2209 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2210 		    "mapping with length 0\n"));
2211 		mutex_unlock(&seg->rsmseg_lock);
2212 		return (RSMERR_BAD_LENGTH);
2213 	}
2214 
2215 	if (offset + length > seg->rsmseg_size) {
2216 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2217 		    "map length + offset exceed segment size\n"));
2218 		mutex_unlock(&seg->rsmseg_lock);
2219 		return (RSMERR_BAD_LENGTH);
2220 	}
2221 
2222 	if ((size_t)offset & (PAGESIZE - 1)) {
2223 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2224 		    "bad mem alignment\n"));
2225 		return (RSMERR_BAD_MEM_ALIGNMENT);
2226 	}
2227 
2228 	if (attr & RSM_MAP_FIXED) {
2229 		if ((uintptr_t)(*address) & (PAGESIZE - 1)) {
2230 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
2231 			    "bad mem alignment\n"));
2232 			return (RSMERR_BAD_MEM_ALIGNMENT);
2233 		}
2234 		flag |= MAP_FIXED;
2235 	}
2236 
2237 	prot = PROT_NONE;
2238 	if (perm & RSM_PERM_READ)
2239 		prot |= PROT_READ;
2240 	if (perm & RSM_PERM_WRITE)
2241 		prot |= PROT_WRITE;
2242 
2243 	va = mmap(*address, length, prot, flag, seg->rsmseg_fd, offset);
2244 	if (va == MAP_FAILED) {
2245 		int e = errno;
2246 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2247 		    "error %d during map\n", e));
2248 
2249 		mutex_unlock(&seg->rsmseg_lock);
2250 		if (e == ENXIO || e == EOVERFLOW ||
2251 		    e == ENOMEM)
2252 			return (RSMERR_BAD_LENGTH);
2253 		else if (e == ENODEV)
2254 			return (RSMERR_CONN_ABORTED);
2255 		else if (e == EAGAIN)
2256 			return (RSMERR_INSUFFICIENT_RESOURCES);
2257 		else if (e == ENOTSUP)
2258 			return (RSMERR_MAP_FAILED);
2259 		else if (e == EACCES)
2260 			return (RSMERR_BAD_PERMS);
2261 		else
2262 			return (RSMERR_MAP_FAILED);
2263 	}
2264 	*address = va;
2265 
2266 	/*
2267 	 * Fix segment ops vector to handle direct access.
2268 	 */
2269 	/*
2270 	 * XXX: Set this only for full segment mapping. Keep a list
2271 	 * of mappings to use for access functions
2272 	 */
2273 	seg->rsmseg_vaddr = va;
2274 	seg->rsmseg_maplen = length;
2275 	seg->rsmseg_mapoffset = offset;
2276 	seg->rsmseg_state = IMPORT_MAP;
2277 
2278 	mutex_unlock(&seg->rsmseg_lock);
2279 
2280 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2281 	    "rsm_memseg_import_map: exit\n"));
2282 
2283 	return (RSM_SUCCESS);
2284 }
2285 
2286 int
2287 rsm_memseg_import_unmap(rsm_memseg_import_handle_t im_memseg)
2288 {
2289 	/*
2290 	 * Until we fix the rsm driver to catch unload, we unload
2291 	 * the whole segment.
2292 	 */
2293 
2294 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2295 
2296 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2297 	    "rsm_memseg_import_unmap: enter\n"));
2298 
2299 	if (!seg) {
2300 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2301 		    "invalid segment or segment state\n"));
2302 		return (RSMERR_BAD_SEG_HNDL);
2303 	}
2304 
2305 	mutex_lock(&seg->rsmseg_lock);
2306 	if (seg->rsmseg_state != IMPORT_MAP) {
2307 		mutex_unlock(&seg->rsmseg_lock);
2308 		return (RSMERR_SEG_NOT_MAPPED);
2309 	}
2310 
2311 	seg->rsmseg_mapoffset = 0;   /* reset the offset */
2312 	seg->rsmseg_state = IMPORT_CONNECT;
2313 	seg->rsmseg_flags &= ~RSM_IMPLICIT_MAP;
2314 	(void) munmap(seg->rsmseg_vaddr, seg->rsmseg_maplen);
2315 
2316 	mutex_unlock(&seg->rsmseg_lock);
2317 
2318 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2319 	    "rsm_memseg_import_unmap: exit\n"));
2320 
2321 	return (RSM_SUCCESS);
2322 }
2323 
2324 
2325 	/*
2326 	 * import side memory segment operations (barriers):
2327 	 */
2328 int
2329 rsm_memseg_import_init_barrier(rsm_memseg_import_handle_t im_memseg,
2330     rsm_barrier_type_t type,
2331     rsmapi_barrier_t *barrier)
2332 {
2333 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2334 	rsmbar_handle_t *bar;
2335 
2336 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2337 	    "rsm_memseg_import_init_barrier: enter\n"));
2338 
2339 	if (!seg) {
2340 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2341 		    "invalid segment or barrier\n"));
2342 		return (RSMERR_BAD_SEG_HNDL);
2343 	}
2344 	if (!barrier) {
2345 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2346 		    "invalid barrier pointer\n"));
2347 		return (RSMERR_BAD_BARRIER_PTR);
2348 	}
2349 
2350 	bar = (rsmbar_handle_t *)barrier;
2351 	bar->rsmbar_seg = seg;
2352 
2353 	seg->rsmseg_barrier = barrier;  /* used in put/get fns */
2354 
2355 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2356 	    "rsm_memseg_import_init_barrier: exit\n"));
2357 
2358 	return (seg->rsmseg_ops->rsm_memseg_import_init_barrier(im_memseg,
2359 	    type, (rsm_barrier_handle_t)barrier));
2360 }
2361 
2362 int
2363 rsm_memseg_import_open_barrier(rsmapi_barrier_t *barrier)
2364 {
2365 	rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2366 	rsm_segops_t *ops;
2367 
2368 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2369 	    "rsm_memseg_import_open_barrier: enter\n"));
2370 
2371 	if (!bar) {
2372 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2373 		    "invalid barrier\n"));
2374 		return (RSMERR_BAD_BARRIER_PTR);
2375 	}
2376 	if (!bar->rsmbar_seg) {
2377 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2378 		    "uninitialized barrier\n"));
2379 		return (RSMERR_BARRIER_UNINITIALIZED);
2380 	}
2381 
2382 	/* generation number snapshot */
2383 	bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum; /* bar[0] */
2384 
2385 	ops = bar->rsmbar_seg->rsmseg_ops;
2386 
2387 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2388 	    "rsm_memseg_import_open_barrier: exit\n"));
2389 
2390 	return (ops->rsm_memseg_import_open_barrier(
2391 	    (rsm_barrier_handle_t)barrier));
2392 }
2393 
2394 int
2395 rsm_memseg_import_order_barrier(rsmapi_barrier_t *barrier)
2396 {
2397 	rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2398 	rsm_segops_t *ops;
2399 
2400 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2401 	    "rsm_memseg_import_order_barrier: enter\n"));
2402 
2403 	if (!bar) {
2404 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2405 		    "invalid barrier\n"));
2406 		return (RSMERR_BAD_BARRIER_PTR);
2407 	}
2408 	if (!bar->rsmbar_seg) {
2409 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2410 		    "uninitialized barrier\n"));
2411 		return (RSMERR_BARRIER_UNINITIALIZED);
2412 	}
2413 
2414 	ops = bar->rsmbar_seg->rsmseg_ops;
2415 
2416 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2417 	    "rsm_memseg_import_order_barrier: exit\n"));
2418 
2419 	return (ops->rsm_memseg_import_order_barrier(
2420 	    (rsm_barrier_handle_t)barrier));
2421 }
2422 
2423 int
2424 rsm_memseg_import_close_barrier(rsmapi_barrier_t *barrier)
2425 {
2426 	rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2427 	rsm_segops_t *ops;
2428 
2429 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2430 	    "rsm_memseg_import_close_barrier: enter\n"));
2431 
2432 	if (!bar) {
2433 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2434 		    "invalid barrier\n"));
2435 		return (RSMERR_BAD_BARRIER_PTR);
2436 	}
2437 	if (!bar->rsmbar_seg) {
2438 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2439 		    "uninitialized barrier\n"));
2440 		return (RSMERR_BARRIER_UNINITIALIZED);
2441 	}
2442 
2443 	/* generation number snapshot */
2444 	if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
2445 		return (RSMERR_CONN_ABORTED);
2446 	}
2447 
2448 	ops = bar->rsmbar_seg->rsmseg_ops;
2449 
2450 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2451 	    "rsm_memseg_import_close_barrier: exit\n"));
2452 
2453 	return (ops->rsm_memseg_import_close_barrier(
2454 	    (rsm_barrier_handle_t)barrier));
2455 }
2456 
2457 int
2458 rsm_memseg_import_destroy_barrier(rsmapi_barrier_t *barrier)
2459 {
2460 	rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2461 	rsm_segops_t *ops;
2462 
2463 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2464 	    "rsm_memseg_import_destroy_barrier: enter\n"));
2465 
2466 	if (!bar) {
2467 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2468 		    "invalid barrier\n"));
2469 		return (RSMERR_BAD_BARRIER_PTR);
2470 	}
2471 	if (!bar->rsmbar_seg) {
2472 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2473 		    "uninitialized barrier\n"));
2474 		return (RSMERR_BARRIER_UNINITIALIZED);
2475 	}
2476 
2477 	bar->rsmbar_seg->rsmseg_barrier = NULL;
2478 
2479 	ops = bar->rsmbar_seg->rsmseg_ops;
2480 
2481 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2482 	    "rsm_memseg_import_destroy_barrier: exit\n"));
2483 
2484 	return (ops->rsm_memseg_import_destroy_barrier
2485 	    ((rsm_barrier_handle_t)barrier));
2486 }
2487 
2488 int
2489 rsm_memseg_import_get_mode(rsm_memseg_import_handle_t im_memseg,
2490     rsm_barrier_mode_t *mode)
2491 {
2492 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2493 
2494 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2495 	    "rsm_memseg_import_get_mode: enter\n"));
2496 
2497 	if (seg) {
2498 		*mode = seg->rsmseg_barmode;
2499 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2500 		    "rsm_memseg_import_get_mode: exit\n"));
2501 
2502 		return (seg->rsmseg_ops->rsm_memseg_import_get_mode(im_memseg,
2503 		    mode));
2504 	}
2505 
2506 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2507 	    "invalid arguments \n"));
2508 
2509 	return (RSMERR_BAD_SEG_HNDL);
2510 
2511 }
2512 
2513 int
2514 rsm_memseg_import_set_mode(rsm_memseg_import_handle_t im_memseg,
2515     rsm_barrier_mode_t mode)
2516 {
2517 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2518 
2519 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2520 	    "rsm_memseg_import_set_mode: enter\n"));
2521 	if (seg) {
2522 		if ((mode == RSM_BARRIER_MODE_IMPLICIT ||
2523 		    mode == RSM_BARRIER_MODE_EXPLICIT)) {
2524 			seg->rsmseg_barmode = mode;
2525 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2526 			    "rsm_memseg_import_set_mode: exit\n"));
2527 
2528 			return (seg->rsmseg_ops->rsm_memseg_import_set_mode(
2529 			    im_memseg,
2530 			    mode));
2531 		} else {
2532 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2533 			    "bad barrier mode\n"));
2534 			return (RSMERR_BAD_MODE);
2535 		}
2536 	}
2537 
2538 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2539 	    "invalid arguments\n"));
2540 
2541 	return (RSMERR_BAD_SEG_HNDL);
2542 }
2543 
2544 int
2545 rsm_intr_signal_post(void *memseg, uint_t flags)
2546 {
2547 	rsm_ioctlmsg_t msg;
2548 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2549 
2550 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2551 	    "rsm_intr_signal_post: enter\n"));
2552 
2553 	flags = flags;
2554 
2555 	if (!seg) {
2556 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2557 		    "invalid segment handle\n"));
2558 		return (RSMERR_BAD_SEG_HNDL);
2559 	}
2560 
2561 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_RING_BELL, &msg) < 0) {
2562 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2563 		    "RSM_IOCTL_RING_BELL failed\n"));
2564 		return (errno);
2565 	}
2566 
2567 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2568 	    "rsm_intr_signal_post: exit\n"));
2569 
2570 	return (RSM_SUCCESS);
2571 }
2572 
2573 int
2574 rsm_intr_signal_wait(void *memseg, int timeout)
2575 {
2576 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2577 	struct pollfd fds;
2578 	minor_t	rnum;
2579 
2580 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2581 	    "rsm_intr_signal_wait: enter\n"));
2582 
2583 	if (!seg) {
2584 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2585 		    "invalid segment\n"));
2586 		return (RSMERR_BAD_SEG_HNDL);
2587 	}
2588 
2589 	fds.fd = seg->rsmseg_fd;
2590 	fds.events = POLLRDNORM;
2591 
2592 	rnum = seg->rsmseg_rnum;
2593 
2594 	return (__rsm_intr_signal_wait_common(&fds, &rnum, 1, timeout, NULL));
2595 }
2596 
2597 int
2598 rsm_intr_signal_wait_pollfd(struct pollfd fds[], nfds_t nfds, int timeout,
2599 	int *numfdsp)
2600 {
2601 	return (__rsm_intr_signal_wait_common(fds, NULL, nfds, timeout,
2602 	    numfdsp));
2603 }
2604 
2605 /*
2606  * This is the generic wait routine, it takes the following arguments
2607  *	- pollfd array
2608  *	- rnums array corresponding to the pollfd if known, if this is
2609  *	NULL then the fds are looked up from the pollfd_table.
2610  *	- number of fds in pollfd array,
2611  *	- timeout
2612  *	- pointer to a location where the number of fds with successful
2613  *	events is returned.
2614  */
2615 static int
2616 __rsm_intr_signal_wait_common(struct pollfd fds[], minor_t rnums[],
2617     nfds_t nfds, int timeout, int *numfdsp)
2618 {
2619 	int	i;
2620 	int	numsegs = 0;
2621 	int	numfd;
2622 	int	fds_processed = 0;
2623 	minor_t	segrnum;
2624 	rsm_poll_event_t	event_arr[RSM_MAX_POLLFDS];
2625 	rsm_poll_event_t	*event_list = NULL;
2626 	rsm_poll_event_t	*events;
2627 	rsm_consume_event_msg_t msg;
2628 
2629 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE, "wait_common enter\n"));
2630 
2631 	if (numfdsp) {
2632 		*numfdsp = 0;
2633 	}
2634 
2635 	numfd = poll(fds, nfds, timeout);
2636 
2637 	switch (numfd) {
2638 	case -1: /* poll returned error - map to RSMERR_... */
2639 		DBPRINTF((RSM_LIBRARY, RSM_ERR, "signal wait pollfd err\n"));
2640 		switch (errno) {
2641 		case EAGAIN:
2642 			return (RSMERR_INSUFFICIENT_RESOURCES);
2643 		case EFAULT:
2644 			return (RSMERR_BAD_ADDR);
2645 		case EINTR:
2646 			return (RSMERR_INTERRUPTED);
2647 		case EINVAL:
2648 		default:
2649 			return (RSMERR_BAD_ARGS_ERRORS);
2650 		}
2651 	case 0: /* timedout - return from here */
2652 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2653 		    "signal wait timed out\n"));
2654 		return (RSMERR_TIMEOUT);
2655 	default:
2656 		break;
2657 	}
2658 
2659 	if (numfd <= RSM_MAX_POLLFDS) {
2660 		/* use the event array on the stack */
2661 		events = (rsm_poll_event_t *)event_arr;
2662 	} else {
2663 		/*
2664 		 * actual number of fds corresponding to rsmapi segments might
2665 		 * be < numfd, don't want to scan the list to figure that out
2666 		 * lets just allocate on the heap
2667 		 */
2668 		event_list = (rsm_poll_event_t *)malloc(
2669 		    sizeof (rsm_poll_event_t)*numfd);
2670 		if (!event_list) {
2671 			/*
2672 			 * return with error even if poll might have succeeded
2673 			 * since the application can retry and the events will
2674 			 * still be available.
2675 			 */
2676 			return (RSMERR_INSUFFICIENT_MEM);
2677 		}
2678 		events = event_list;
2679 	}
2680 
2681 	/*
2682 	 * process the fds for events and if it corresponds to an rsmapi
2683 	 * segment consume the event
2684 	 */
2685 	for (i = 0; i < nfds; i++) {
2686 		if (fds[i].revents == POLLRDNORM) {
2687 			/*
2688 			 * poll returned an event and if its POLLRDNORM, it
2689 			 * might correspond to an rsmapi segment
2690 			 */
2691 			if (rnums) { /* resource num is passed in */
2692 				segrnum = rnums[i];
2693 			} else { /* lookup pollfd table to get resource num */
2694 				segrnum = _rsm_lookup_pollfd_table(fds[i].fd);
2695 			}
2696 			if (segrnum) {
2697 				events[numsegs].rnum = segrnum;
2698 				events[numsegs].revent = 0;
2699 				events[numsegs].fdsidx = i; /* fdlist index */
2700 				numsegs++;
2701 			}
2702 		}
2703 
2704 		if ((fds[i].revents) && (++fds_processed == numfd)) {
2705 			/*
2706 			 * only "numfd" events have revents field set, once we
2707 			 * process that many break out of the loop
2708 			 */
2709 			break;
2710 		}
2711 	}
2712 
2713 	if (numsegs == 0) { /* No events for rsmapi segs in the fdlist */
2714 		if (event_list) {
2715 			free(event_list);
2716 		}
2717 		if (numfdsp) {
2718 			*numfdsp = numfd;
2719 		}
2720 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2721 		    "wait_common exit: no rsmapi segs\n"));
2722 		return (RSM_SUCCESS);
2723 	}
2724 
2725 	msg.seglist = (caddr_t)events;
2726 	msg.numents = numsegs;
2727 
2728 	if (ioctl(_rsm_fd, RSM_IOCTL_CONSUMEEVENT, &msg) < 0) {
2729 		int error = errno;
2730 		if (event_list) {
2731 			free(event_list);
2732 		}
2733 		DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
2734 		    "RSM_IOCTL_CONSUMEEVENT failed(%d)\n", error));
2735 		return (error);
2736 	}
2737 
2738 	/* count the number of segs for which consumeevent was successful */
2739 	numfd -= numsegs;
2740 
2741 	for (i = 0; i < numsegs; i++) {
2742 		if (events[i].revent != 0) {
2743 			fds[events[i].fdsidx].revents = POLLRDNORM;
2744 			numfd++;
2745 		} else { /* failed to consume event so set revents to 0 */
2746 			fds[events[i].fdsidx].revents = 0;
2747 		}
2748 	}
2749 
2750 	if (event_list) {
2751 		free(event_list);
2752 	}
2753 
2754 	if (numfd > 0) {
2755 		if (numfdsp) {
2756 			*numfdsp = numfd;
2757 		}
2758 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2759 		    "wait_common exit\n"));
2760 		return (RSM_SUCCESS);
2761 	} else {
2762 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2763 		    "wait_common exit\n"));
2764 		return (RSMERR_TIMEOUT);
2765 	}
2766 }
2767 
2768 /*
2769  * This function provides the data (file descriptor and event) for
2770  * the specified pollfd struct.  The pollfd struct may then be
2771  * subsequently used with the poll system call to wait for an event
2772  * signalled by rsm_intr_signal_post.  The memory segment must be
2773  * currently published for a successful return with a valid pollfd.
2774  * A reference count for the descriptor is incremented.
2775  */
2776 int
2777 rsm_memseg_get_pollfd(void *memseg,
2778 			struct pollfd *poll_fd)
2779 {
2780 	int	i;
2781 	int	err = RSM_SUCCESS;
2782 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2783 
2784 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2785 	    "rsm_memseg_get_pollfd: enter\n"));
2786 
2787 	if (!seg) {
2788 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2789 		    "invalid segment\n"));
2790 		return (RSMERR_BAD_SEG_HNDL);
2791 	}
2792 
2793 	mutex_lock(&seg->rsmseg_lock);
2794 
2795 	poll_fd->fd = seg->rsmseg_fd;
2796 	poll_fd->events = POLLRDNORM;
2797 	seg->rsmseg_pollfd_refcnt++;
2798 	if (seg->rsmseg_pollfd_refcnt == 1) {
2799 		/* insert the segment into the pollfd table */
2800 		err = _rsm_insert_pollfd_table(seg->rsmseg_fd,
2801 		    seg->rsmseg_rnum);
2802 	}
2803 
2804 	mutex_unlock(&seg->rsmseg_lock);
2805 
2806 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2807 	    "rsm_memseg_get_pollfd: exit(%d)\n", err));
2808 
2809 	return (err);
2810 }
2811 
2812 /*
2813  * This function decrements the segment pollfd reference count.
2814  * A segment unpublish or destroy operation will fail if the reference count is
2815  * non zero.
2816  */
2817 int
2818 rsm_memseg_release_pollfd(void * memseg)
2819 {
2820 	int	i;
2821 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2822 
2823 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2824 	    "rsm_memseg_release_pollfd: enter\n"));
2825 
2826 	if (!seg) {
2827 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2828 		    "invalid segment handle\n"));
2829 		return (RSMERR_BAD_SEG_HNDL);
2830 	}
2831 
2832 	mutex_lock(&seg->rsmseg_lock);
2833 
2834 	if (seg->rsmseg_pollfd_refcnt) {
2835 		seg->rsmseg_pollfd_refcnt--;
2836 		if (seg->rsmseg_pollfd_refcnt == 0) {
2837 			/* last reference removed - update the pollfd_table */
2838 			_rsm_remove_pollfd_table(seg->rsmseg_fd);
2839 		}
2840 	}
2841 
2842 	mutex_unlock(&seg->rsmseg_lock);
2843 
2844 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2845 	    "rsm_memseg_release_pollfd: exit\n"));
2846 
2847 	return (RSM_SUCCESS);
2848 }
2849 
2850 /*
2851  * The interconnect topology data is obtained from the Kernel Agent
2852  * and stored in a memory buffer allocated by this function.  A pointer
2853  * to the buffer is stored in the location specified by the caller in
2854  * the function argument.  It is the callers responsibility to
2855  * call rsm_free_interconnect_topolgy() to free the allocated memory.
2856  */
2857 int
2858 rsm_get_interconnect_topology(rsm_topology_t **topology_data)
2859 {
2860 	uint32_t		topology_data_size;
2861 	rsm_topology_t		*topology_ptr;
2862 	int			error;
2863 
2864 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2865 	    "rsm_get_interconnect_topology: enter\n"));
2866 
2867 	if (topology_data == NULL)
2868 		return (RSMERR_BAD_TOPOLOGY_PTR);
2869 
2870 	*topology_data = NULL;
2871 
2872 again:
2873 	/* obtain the size of the topology data */
2874 	if (ioctl(_rsm_fd, RSM_IOCTL_TOPOLOGY_SIZE, &topology_data_size) < 0) {
2875 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2876 		    "RSM_IOCTL_TOPOLOGY_SIZE failed\n"));
2877 		return (errno);
2878 	}
2879 
2880 	/* allocate double-word aligned memory to hold the topology data */
2881 	topology_ptr = (rsm_topology_t *)memalign(8, topology_data_size);
2882 	if (topology_ptr == NULL) {
2883 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2884 		    "not enough memory\n"));
2885 		return (RSMERR_INSUFFICIENT_MEM);
2886 	}
2887 
2888 	/*
2889 	 * Request the topology data.
2890 	 * Pass in the size to be used as a check in case
2891 	 * the data has grown since the size was obtained - if
2892 	 * it has, the errno value will be E2BIG.
2893 	 */
2894 	topology_ptr->topology_hdr.local_nodeid =
2895 	    (rsm_node_id_t)topology_data_size;
2896 	if (ioctl(_rsm_fd, RSM_IOCTL_TOPOLOGY_DATA, topology_ptr) < 0) {
2897 		error = errno;
2898 		free((void *)topology_ptr);
2899 		if (error == E2BIG)
2900 			goto again;
2901 		else {
2902 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
2903 			    "RSM_IOCTL_TOPOLOGY_DATA failed\n"));
2904 			return (error);
2905 		}
2906 	} else
2907 		*topology_data = topology_ptr;
2908 
2909 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2910 	    " rsm_get_interconnect_topology: exit\n"));
2911 
2912 	return (RSM_SUCCESS);
2913 }
2914 
2915 
2916 void
2917 rsm_free_interconnect_topology(rsm_topology_t *topology_ptr)
2918 {
2919 
2920 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2921 	    "rsm_free_interconnect_topology: enter\n"));
2922 
2923 	if (topology_ptr) {
2924 		free((void *)topology_ptr);
2925 	}
2926 
2927 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2928 	    "rsm_free_interconnect_topology: exit\n"));
2929 }
2930 
2931 int
2932 rsm_create_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,
2933 				rsm_localmemory_handle_t *local_hndl_p,
2934 				caddr_t local_vaddr, size_t len)
2935 {
2936 	int e;
2937 	rsm_controller_t *cntrl = (rsm_controller_t *)cntrl_handle;
2938 
2939 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2940 	    "rsm_create_localmemory_handle: enter\n"));
2941 
2942 	if ((size_t)local_vaddr & (PAGESIZE - 1)) {
2943 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2944 		    "invalid arguments\n"));
2945 		return (RSMERR_BAD_ADDR);
2946 	}
2947 
2948 	if (!cntrl_handle) {
2949 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2950 		    "invalid controller handle\n"));
2951 		return (RSMERR_BAD_CTLR_HNDL);
2952 	}
2953 	if (!local_hndl_p) {
2954 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2955 		    "invalid local memory handle pointer\n"));
2956 		return (RSMERR_BAD_LOCALMEM_HNDL);
2957 	}
2958 	if (len == 0) {
2959 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2960 		    "invalid length\n"));
2961 		return (RSMERR_BAD_LENGTH);
2962 	}
2963 
2964 	e = cntrl->cntr_segops->rsm_create_localmemory_handle(
2965 	    cntrl_handle,
2966 	    local_hndl_p,
2967 	    local_vaddr,
2968 	    len);
2969 
2970 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2971 	    "rsm_create_localmemory_handle: exit\n"));
2972 
2973 	return (e);
2974 }
2975 
2976 int
2977 rsm_free_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,
2978     rsm_localmemory_handle_t local_handle)
2979 {
2980 	int e;
2981 
2982 	rsm_controller_t *cntrl = (rsm_controller_t *)cntrl_handle;
2983 
2984 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2985 	    "rsm_free_localmemory_handle: enter\n"));
2986 
2987 
2988 	if (!cntrl_handle) {
2989 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2990 		    "invalid controller handle\n"));
2991 		return (RSMERR_BAD_CTLR_HNDL);
2992 	}
2993 
2994 	if (!local_handle) {
2995 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2996 		    "invalid localmemory handle\n"));
2997 		return (RSMERR_BAD_LOCALMEM_HNDL);
2998 	}
2999 
3000 	e = cntrl->cntr_segops->rsm_free_localmemory_handle(local_handle);
3001 
3002 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3003 	    "rsm_free_localmemory_handle: exit\n"));
3004 
3005 	return (e);
3006 }
3007 
3008 int
3009 rsm_get_segmentid_range(const char *appid, rsm_memseg_id_t *baseid,
3010 	uint32_t *length)
3011 {
3012 	char    buf[RSMFILE_BUFSIZE];
3013 	char	*s;
3014 	char	*fieldv[4];
3015 	int	fieldc = 0;
3016 	int	found = 0;
3017 	int	err = RSMERR_BAD_APPID;
3018 	FILE    *fp;
3019 
3020 	if (appid == NULL || baseid == NULL || length == NULL)
3021 		return (RSMERR_BAD_ADDR);
3022 
3023 	if ((fp = fopen(RSMSEGIDFILE, "rF")) == NULL) {
3024 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3025 		    "cannot open <%s>\n", RSMSEGIDFILE));
3026 		return (RSMERR_BAD_CONF);
3027 	}
3028 
3029 	while (s = fgets(buf, RSMFILE_BUFSIZE, fp)) {
3030 		fieldc = 0;
3031 		while (isspace(*s))	/* skip the leading spaces */
3032 			s++;
3033 
3034 		if (*s == '#') {	/* comment line - skip it */
3035 			continue;
3036 		}
3037 
3038 		/*
3039 		 * parse the reserved segid file and
3040 		 * set the pointers appropriately.
3041 		 * fieldv[0] :  keyword
3042 		 * fieldv[1] :  application identifier
3043 		 * fieldv[2] :  baseid
3044 		 * fieldv[3] :  length
3045 		 */
3046 		while ((*s != '\n') && (*s != '\0') && (fieldc < 4)) {
3047 
3048 			while (isspace(*s)) /* skip the leading spaces */
3049 				s++;
3050 
3051 			fieldv[fieldc++] = s;
3052 
3053 			if (fieldc == 4) {
3054 				if (fieldv[3][strlen(fieldv[3])-1] == '\n')
3055 					fieldv[3][strlen(fieldv[3])-1] = '\0';
3056 				break;
3057 			}
3058 
3059 			while (*s && !isspace(*s))
3060 				++s;	/* move to the next white space */
3061 
3062 			if (*s)
3063 				*s++ = '\0';
3064 		}
3065 
3066 		if (fieldc < 4) {	/* some fields are missing */
3067 			err = RSMERR_BAD_CONF;
3068 			break;
3069 		}
3070 
3071 		if (strcasecmp(fieldv[1], appid) == 0) { /* found a match */
3072 			if (strcasecmp(fieldv[0], RSMSEG_RESERVED) == 0) {
3073 				errno = 0;
3074 				*baseid = strtol(fieldv[2], (char **)NULL, 16);
3075 				if (errno != 0) {
3076 					err = RSMERR_BAD_CONF;
3077 					break;
3078 				}
3079 
3080 				errno = 0;
3081 				*length = (int)strtol(fieldv[3],
3082 				    (char **)NULL, 10);
3083 				if (errno != 0) {
3084 					err = RSMERR_BAD_CONF;
3085 					break;
3086 				}
3087 
3088 				found = 1;
3089 			} else {	/* error in format */
3090 				err = RSMERR_BAD_CONF;
3091 			}
3092 			break;
3093 		}
3094 	}
3095 
3096 	(void) fclose(fp);
3097 
3098 	if (found)
3099 		return (RSM_SUCCESS);
3100 
3101 	return (err);
3102 }
3103 
3104 static 	int
3105 _rsm_get_hwaddr(rsmapi_controller_handle_t handle, rsm_node_id_t nodeid,
3106     rsm_addr_t *hwaddrp)
3107 {
3108 	rsm_ioctlmsg_t	msg = {0};
3109 	rsm_controller_t *ctrlp;
3110 
3111 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3112 	    "_rsm_get_hwaddr: enter\n"));
3113 
3114 	ctrlp = (rsm_controller_t *)handle;
3115 
3116 	if (ctrlp == NULL) {
3117 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3118 		    "invalid controller handle\n"));
3119 		return (RSMERR_BAD_CTLR_HNDL);
3120 	}
3121 
3122 	msg.cname = ctrlp->cntr_name;
3123 	msg.cname_len = strlen(ctrlp->cntr_name) +1;
3124 	msg.cnum = ctrlp->cntr_unit;
3125 	msg.nodeid = nodeid;
3126 
3127 	if (ioctl(_rsm_fd, RSM_IOCTL_MAP_TO_ADDR, &msg) < 0) {
3128 		int error = errno;
3129 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3130 		    "RSM_IOCTL_MAP_TO_ADDR failed\n"));
3131 		return (error);
3132 	}
3133 
3134 	*hwaddrp = msg.hwaddr;
3135 
3136 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3137 	    "_rsm_get_hwaddr: exit\n"));
3138 
3139 	return (RSM_SUCCESS);
3140 
3141 }
3142 
3143 static	int
3144 _rsm_get_nodeid(rsmapi_controller_handle_t handle, rsm_addr_t hwaddr,
3145     rsm_node_id_t *nodeidp)
3146 {
3147 
3148 	rsm_ioctlmsg_t	msg = {0};
3149 	rsm_controller_t *ctrlp;
3150 
3151 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3152 	    "_rsm_get_nodeid: enter\n"));
3153 
3154 	ctrlp = (rsm_controller_t *)handle;
3155 
3156 	if (ctrlp == NULL) {
3157 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3158 		    "invalid arguments\n"));
3159 		return (RSMERR_BAD_CTLR_HNDL);
3160 	}
3161 
3162 	msg.cname = ctrlp->cntr_name;
3163 	msg.cname_len = strlen(ctrlp->cntr_name) +1;
3164 	msg.cnum = ctrlp->cntr_unit;
3165 	msg.hwaddr = hwaddr;
3166 
3167 	if (ioctl(_rsm_fd, RSM_IOCTL_MAP_TO_NODEID, &msg) < 0) {
3168 		int error = errno;
3169 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3170 		    "RSM_IOCTL_MAP_TO_NODEID failed\n"));
3171 		return (error);
3172 	}
3173 
3174 	*nodeidp = msg.nodeid;
3175 
3176 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3177 	    "_rsm_get_nodeid: exit\n"));
3178 
3179 	return (RSM_SUCCESS);
3180 
3181 }
3182 
3183 #ifdef DEBUG
3184 void
3185 dbg_printf(int msg_category, int msg_level, char *fmt, ...)
3186 {
3187 	if ((msg_category & rsmlibdbg_category) &&
3188 	    (msg_level <= rsmlibdbg_level)) {
3189 		va_list arg_list;
3190 		va_start(arg_list, fmt);
3191 		mutex_lock(&rsmlog_lock);
3192 		fprintf(rsmlog_fd, "Thread %d ", thr_self());
3193 		vfprintf(rsmlog_fd, fmt, arg_list);
3194 		fflush(rsmlog_fd);
3195 		mutex_unlock(&rsmlog_lock);
3196 		va_end(arg_list);
3197 	}
3198 }
3199 #endif /* DEBUG */
3200