xref: /illumos-gate/usr/src/uts/common/io/vscan/vscan_door.c (revision fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bb)
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 2007 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 <sys/types.h>
30 #include <sys/kmem.h>
31 #include <sys/vnode.h>
32 #include <sys/pathname.h>
33 #include <sys/door.h>
34 #include <sys/cmn_err.h>
35 #include <sys/sunddi.h> /* for string functions */
36 #include <sys/vscan.h>
37 
38 
39 static int vscan_door_id = -1;
40 static door_handle_t vscan_door_handle = NULL;
41 static kmutex_t vscan_door_mutex;
42 static kcondvar_t vscan_door_cv;
43 static int vscan_door_call_count = 0;
44 
45 
46 /*
47  * vscan_door_init
48  */
49 int
50 vscan_door_init(void)
51 {
52 	mutex_init(&vscan_door_mutex, NULL, MUTEX_DEFAULT, NULL);
53 	cv_init(&vscan_door_cv, NULL, CV_DEFAULT, NULL);
54 	return (0);
55 }
56 
57 
58 /*
59  * vscan_door_fini
60  */
61 void
62 vscan_door_fini(void)
63 {
64 	mutex_destroy(&vscan_door_mutex);
65 	cv_destroy(&vscan_door_cv);
66 }
67 
68 
69 /*
70  * vscan_door_open
71  */
72 int
73 vscan_door_open(int door_id)
74 {
75 	mutex_enter(&vscan_door_mutex);
76 
77 	if (vscan_door_handle == NULL) {
78 		vscan_door_id = door_id;
79 		vscan_door_handle = door_ki_lookup(door_id);
80 	}
81 
82 	mutex_exit(&vscan_door_mutex);
83 
84 	if (vscan_door_handle == NULL) {
85 		cmn_err(CE_WARN, "Internal communication error "
86 		    "- failed to access vscan service daemon.");
87 		return (-1);
88 	}
89 
90 	return (0);
91 }
92 
93 
94 /*
95  * vscan_door_close
96  */
97 void
98 vscan_door_close(void)
99 {
100 	mutex_enter(&vscan_door_mutex);
101 
102 	/* wait for any in-progress requests to complete */
103 	while (vscan_door_call_count > 0) {
104 		cv_wait(&vscan_door_cv, &vscan_door_mutex);
105 	}
106 
107 	if (vscan_door_handle) {
108 		door_ki_rele(vscan_door_handle);
109 		vscan_door_handle = NULL;
110 	}
111 
112 	mutex_exit(&vscan_door_mutex);
113 }
114 
115 
116 /*
117  * vscan_door_scan_file
118  */
119 int
120 vscan_door_scan_file(vs_scan_req_t *scan_req)
121 {
122 	int err, rc = 0;
123 	door_arg_t arg;
124 
125 	if (!vscan_door_handle &&
126 	    vscan_door_open(vscan_door_id) != 0)
127 		return (-1);
128 
129 	mutex_enter(&vscan_door_mutex);
130 	vscan_door_call_count++;
131 	mutex_exit(&vscan_door_mutex);
132 
133 	arg.data_ptr = (char *)scan_req;
134 	arg.data_size = sizeof (vs_scan_req_t);
135 	arg.desc_ptr = NULL;
136 	arg.desc_num = 0;
137 	arg.rbuf = (char *)scan_req;
138 	arg.rsize = sizeof (vs_scan_req_t);
139 
140 	if ((err = door_ki_upcall(vscan_door_handle, &arg)) != 0) {
141 		cmn_err(CE_WARN, "Internal communication error (%d)"
142 		    "- failed to send scan request to vscand", err);
143 		vscan_door_close();
144 		rc = -1;
145 	}
146 
147 	mutex_enter(&vscan_door_mutex);
148 	vscan_door_call_count--;
149 	cv_signal(&vscan_door_cv);
150 	mutex_exit(&vscan_door_mutex);
151 
152 	return (rc);
153 }
154