nfs-ganesha 1.4
|
00001 /* 00002 * Copyright IBM Corporation, 2010 00003 * Contributor: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 00004 * 00005 * -------------------------- 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 3 of the License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 * 00021 * 00022 */ 00023 00024 #ifdef HAVE_CONFIG_H 00025 #include "config.h" 00026 #endif 00027 00028 #ifdef _SOLARIS 00029 #include "solaris_port.h" 00030 #endif 00031 00032 #include <stdio.h> 00033 #include <pthread.h> 00034 00035 #include "sal_functions.h" 00036 #include "nlm4.h" 00037 #include "nlm_util.h" 00038 #include "nlm_async.h" 00039 #include "nfs_tcb.h" 00040 00041 pthread_mutex_t nlm_async_resp_mutex = PTHREAD_MUTEX_INITIALIZER; 00042 pthread_cond_t nlm_async_resp_cond = PTHREAD_COND_INITIALIZER; 00043 00044 int nlm_send_async_res_nlm4(state_nlm_client_t * host, 00045 state_async_func_t func, 00046 nfs_res_t * pres) 00047 { 00048 state_async_queue_t * arg = gsh_malloc(sizeof(*arg)); 00049 state_nlm_async_data_t * nlm_arg; 00050 state_status_t status; 00051 00052 if(arg != NULL) 00053 { 00054 nlm_arg = &arg->state_async_data.state_nlm_async_data; 00055 memset(arg, 0, sizeof(*arg)); 00056 arg->state_async_func = func; 00057 nlm_arg->nlm_async_host = host; 00058 nlm_arg->nlm_async_args.nlm_async_res = *pres; 00059 if(!copy_netobj(&nlm_arg->nlm_async_args.nlm_async_res.res_nlm4.cookie, 00060 &pres->res_nlm4.cookie)) 00061 { 00062 LogFullDebug(COMPONENT_NLM, 00063 "Unable to copy async response file handle"); 00064 gsh_free(arg); 00065 return NFS_REQ_DROP; 00066 } 00067 } 00068 else 00069 { 00070 LogFullDebug(COMPONENT_NLM, 00071 "Unable to allocate async response"); 00072 return NFS_REQ_DROP; 00073 } 00074 00075 status = state_async_schedule(arg); 00076 00077 if(status != STATE_SUCCESS) 00078 { 00079 gsh_free(arg); 00080 return NFS_REQ_DROP; 00081 } 00082 00083 return NFS_REQ_OK; 00084 } 00085 00086 int nlm_send_async_res_nlm4test(state_nlm_client_t * host, 00087 state_async_func_t func, 00088 nfs_res_t * pres) 00089 { 00090 state_async_queue_t * arg = gsh_malloc(sizeof(*arg)); 00091 state_nlm_async_data_t * nlm_arg; 00092 state_status_t status; 00093 00094 if(arg != NULL) 00095 { 00096 nlm_arg = &arg->state_async_data.state_nlm_async_data; 00097 memset(arg, 0, sizeof(*arg)); 00098 arg->state_async_func = func; 00099 nlm_arg->nlm_async_host = host; 00100 nlm_arg->nlm_async_args.nlm_async_res = *pres; 00101 if(!copy_netobj(&nlm_arg->nlm_async_args.nlm_async_res.res_nlm4test.cookie, 00102 &pres->res_nlm4test.cookie)) 00103 { 00104 LogFullDebug(COMPONENT_NLM, 00105 "Unable to copy async response file handle"); 00106 gsh_free(arg); 00107 return NFS_REQ_DROP; 00108 } 00109 else if(pres->res_nlm4test.test_stat.stat == NLM4_DENIED) 00110 { 00111 if(!copy_netobj(&nlm_arg->nlm_async_args.nlm_async_res.res_nlm4test.test_stat.nlm4_testrply_u.holder.oh, 00112 &pres->res_nlm4test.test_stat.nlm4_testrply_u.holder.oh)) 00113 { 00114 LogFullDebug(COMPONENT_NLM, 00115 "Unable to copy async response oh"); 00116 netobj_free(&nlm_arg->nlm_async_args.nlm_async_res.res_nlm4test.cookie); 00117 gsh_free(arg); 00118 return NFS_REQ_DROP; 00119 } 00120 } 00121 } 00122 else 00123 { 00124 LogFullDebug(COMPONENT_NLM, 00125 "Unable to allocate async response"); 00126 return NFS_REQ_DROP; 00127 } 00128 00129 00130 status = state_async_schedule(arg); 00131 00132 if(status != STATE_SUCCESS) 00133 { 00134 netobj_free(&nlm_arg->nlm_async_args.nlm_async_res.res_nlm4test.cookie); 00135 if(pres->res_nlm4test.test_stat.stat == NLM4_DENIED) 00136 netobj_free(&nlm_arg->nlm_async_args.nlm_async_res.res_nlm4test.test_stat.nlm4_testrply_u.holder.oh); 00137 gsh_free(arg); 00138 return NFS_REQ_DROP; 00139 } 00140 00141 return NFS_REQ_OK; 00142 } 00143 00144 xdrproc_t nlm_reply_proc[] = 00145 { 00146 [NLMPROC4_GRANTED_MSG] = (xdrproc_t) xdr_nlm4_testargs, 00147 [NLMPROC4_TEST_RES] = (xdrproc_t) xdr_nlm4_testres, 00148 [NLMPROC4_LOCK_RES] = (xdrproc_t) xdr_nlm4_res, 00149 [NLMPROC4_CANCEL_RES] = (xdrproc_t) xdr_nlm4_res, 00150 [NLMPROC4_UNLOCK_RES] = (xdrproc_t) xdr_nlm4_res, 00151 }; 00152 00153 static void *resp_key; 00154 00155 #define MAX_ASYNC_RETRY 2 00156 00157 /* Client routine to send the asynchrnous response, key is used to wait for a response */ 00158 int nlm_send_async(int proc, 00159 state_nlm_client_t * host, 00160 void * inarg, 00161 void * key) 00162 { 00163 struct timeval tout = { 0, 10 }; 00164 int retval, retry; 00165 struct timeval start, now; 00166 struct timespec timeout; 00167 00168 for(retry = 1; retry <= MAX_ASYNC_RETRY; retry++) 00169 { 00170 if(host->slc_callback_clnt == NULL) 00171 { 00172 LogFullDebug(COMPONENT_NLM, 00173 "Clnt_create %s", 00174 host->slc_nsm_client->ssc_nlm_caller_name); 00175 00176 host->slc_callback_clnt = Clnt_create(host->slc_nsm_client->ssc_nlm_caller_name, 00177 NLMPROG, 00178 NLM4_VERS, 00179 (char *)xprt_type_to_str(host->slc_client_type)); 00180 00181 if(host->slc_callback_clnt == NULL) 00182 { 00183 LogMajor(COMPONENT_NLM, 00184 "Cannot create NLM async %s connection to client %s", 00185 xprt_type_to_str(host->slc_client_type), 00186 host->slc_nsm_client->ssc_nlm_caller_name); 00187 return -1; 00188 } 00189 } 00190 00191 pthread_mutex_lock(&nlm_async_resp_mutex); 00192 resp_key = key; 00193 pthread_mutex_unlock(&nlm_async_resp_mutex); 00194 00195 LogFullDebug(COMPONENT_NLM, "About to make clnt_call"); 00196 retval = clnt_call(host->slc_callback_clnt, 00197 proc, 00198 nlm_reply_proc[proc], 00199 inarg, 00200 (xdrproc_t) xdr_void, 00201 NULL, 00202 tout); 00203 LogFullDebug(COMPONENT_NLM, "Done with clnt_call"); 00204 00205 if(retval == RPC_TIMEDOUT || retval == RPC_SUCCESS) 00206 { 00207 retval = RPC_SUCCESS; 00208 break; 00209 } 00210 00211 LogDebug(COMPONENT_NLM, 00212 "NLM async Client procedure call %d failed with return code %d %s", 00213 proc, retval, clnt_sperror(host->slc_callback_clnt, "")); 00214 00215 Clnt_destroy(host->slc_callback_clnt); 00216 host->slc_callback_clnt = NULL; 00217 00218 if(retry == MAX_ASYNC_RETRY) 00219 { 00220 LogMajor(COMPONENT_NLM, 00221 "NLM async Client exceeded retry count %d", 00222 MAX_ASYNC_RETRY); 00223 pthread_mutex_lock(&nlm_async_resp_mutex); 00224 resp_key = NULL; 00225 pthread_mutex_unlock(&nlm_async_resp_mutex); 00226 return retval; 00227 } 00228 } 00229 00230 pthread_mutex_lock(&nlm_async_resp_mutex); 00231 if(resp_key != NULL) 00232 { 00233 /* Wait for 5 seconds or a signal */ 00234 gettimeofday(&start, NULL); 00235 gettimeofday(&now, NULL); 00236 timeout.tv_sec = 5 + start.tv_sec; 00237 timeout.tv_nsec = 0; 00238 LogFullDebug(COMPONENT_NLM, 00239 "About to wait for signal for key %p", 00240 resp_key); 00241 while(resp_key != NULL && now.tv_sec < (start.tv_sec + 5)) 00242 { 00243 int rc = pthread_cond_timedwait(&nlm_async_resp_cond, &nlm_async_resp_mutex, &timeout); 00244 LogFullDebug(COMPONENT_NLM, 00245 "pthread_cond_timedwait returned %d", rc); 00246 gettimeofday(&now, NULL); 00247 } 00248 LogFullDebug(COMPONENT_NLM, "Done waiting"); 00249 } 00250 pthread_mutex_unlock(&nlm_async_resp_mutex); 00251 00252 return retval; 00253 } 00254 00255 void nlm_signal_async_resp(void *key) 00256 { 00257 pthread_mutex_lock(&nlm_async_resp_mutex); 00258 if(resp_key == key) 00259 { 00260 resp_key = NULL; 00261 pthread_cond_signal(&nlm_async_resp_cond); 00262 LogFullDebug(COMPONENT_NLM, 00263 "Signaled condition variable"); 00264 } 00265 else 00266 { 00267 LogFullDebug(COMPONENT_NLM, 00268 "Didn't signal condition variable"); 00269 } 00270 pthread_mutex_unlock(&nlm_async_resp_mutex); 00271 }