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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/errno.h> 29 #include <sys/kmem.h> 30 #include <sys/vnode.h> 31 #include <sys/pathname.h> 32 #include <sys/door.h> 33 #include <sys/cmn_err.h> 34 #include <sys/sunddi.h> /* for string functions */ 35 #include <sys/vscan.h> 36 37 #define VS_DOOR_RETRIES 3 38 39 /* max time (secs) to wait for door calls to complete during door_close */ 40 #define VS_DOOR_CLOSE_TIMEOUT_DEFAULT 30 41 uint32_t vs_door_close_timeout = VS_DOOR_CLOSE_TIMEOUT_DEFAULT; 42 43 static door_handle_t vscan_door_handle = NULL; 44 static kmutex_t vscan_door_mutex; 45 static kcondvar_t vscan_door_cv; 46 static int vscan_door_call_count = 0; 47 48 49 /* 50 * vscan_door_init 51 */ 52 int 53 vscan_door_init(void) 54 { 55 mutex_init(&vscan_door_mutex, NULL, MUTEX_DEFAULT, NULL); 56 cv_init(&vscan_door_cv, NULL, CV_DEFAULT, NULL); 57 return (0); 58 } 59 60 61 /* 62 * vscan_door_fini 63 */ 64 void 65 vscan_door_fini(void) 66 { 67 mutex_destroy(&vscan_door_mutex); 68 cv_destroy(&vscan_door_cv); 69 } 70 71 72 /* 73 * vscan_door_open 74 */ 75 int 76 vscan_door_open(int door_id) 77 { 78 mutex_enter(&vscan_door_mutex); 79 80 if (vscan_door_handle == NULL) 81 vscan_door_handle = door_ki_lookup(door_id); 82 83 if (vscan_door_handle == NULL) { 84 cmn_err(CE_WARN, "Internal communication error " 85 "- failed to access vscan service daemon."); 86 mutex_exit(&vscan_door_mutex); 87 return (-1); 88 } 89 90 mutex_exit(&vscan_door_mutex); 91 return (0); 92 } 93 94 95 /* 96 * vscan_door_close 97 */ 98 void 99 vscan_door_close(void) 100 { 101 clock_t timeout, time_left; 102 103 mutex_enter(&vscan_door_mutex); 104 105 /* wait for any in-progress requests to complete */ 106 time_left = SEC_TO_TICK(vs_door_close_timeout); 107 while ((vscan_door_call_count > 0) && (time_left > 0)) { 108 timeout = time_left; 109 time_left = cv_reltimedwait(&vscan_door_cv, &vscan_door_mutex, 110 timeout, TR_CLOCK_TICK); 111 } 112 113 if (time_left == -1) 114 cmn_err(CE_WARN, "Timeout waiting for door calls to complete"); 115 116 if (vscan_door_handle) { 117 door_ki_rele(vscan_door_handle); 118 vscan_door_handle = NULL; 119 } 120 121 mutex_exit(&vscan_door_mutex); 122 } 123 124 125 /* 126 * vscan_door_scan_file 127 * 128 * Returns: result returned in door response or VS_STATUS_ERROR 129 */ 130 int 131 vscan_door_scan_file(vs_scan_req_t *scan_req) 132 { 133 int err; 134 int i; 135 door_arg_t arg; 136 uint32_t result = 0; 137 138 if (!vscan_door_handle) 139 return (VS_STATUS_ERROR); 140 141 mutex_enter(&vscan_door_mutex); 142 vscan_door_call_count++; 143 mutex_exit(&vscan_door_mutex); 144 145 arg.data_ptr = (char *)scan_req; 146 arg.data_size = sizeof (vs_scan_req_t); 147 arg.desc_ptr = NULL; 148 arg.desc_num = 0; 149 arg.rbuf = (char *)&result; 150 arg.rsize = sizeof (uint32_t); 151 152 for (i = 0; i < VS_DOOR_RETRIES; ++i) { 153 if ((err = door_ki_upcall_limited(vscan_door_handle, &arg, 154 NULL, SIZE_MAX, 0)) == 0) 155 break; 156 157 if (err != EAGAIN && err != EINTR) 158 break; 159 } 160 161 if (err != 0) { 162 cmn_err(CE_WARN, "Internal communication error (%d)" 163 "- failed to send scan request to vscand", err); 164 result = VS_STATUS_ERROR; 165 } 166 167 mutex_enter(&vscan_door_mutex); 168 vscan_door_call_count--; 169 cv_signal(&vscan_door_cv); 170 mutex_exit(&vscan_door_mutex); 171 172 return (result); 173 } 174