nfs-ganesha 1.4

nlm_async.c

Go to the documentation of this file.
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 }