nfs-ganesha 1.4

nlm_Lock.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 License
00009  * as published by the Free Software Foundation; either version 3 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful, but
00013  * 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
00020  * 02110-1301 USA
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 <string.h>
00034 #include <pthread.h>
00035 #include "log.h"
00036 #include "ganesha_rpc.h"
00037 #include "nlm4.h"
00038 #include "sal_functions.h"
00039 #include "nlm_util.h"
00040 #include "nlm_async.h"
00041 
00054 int nlm4_Lock(nfs_arg_t            * parg,
00055               exportlist_t         * pexport,
00056               fsal_op_context_t    * pcontext,
00057               nfs_worker_data_t    * pworker,
00058               struct svc_req       * preq,
00059               nfs_res_t            * pres)
00060 {
00061   nlm4_lockargs      * arg = &parg->arg_nlm4_lock;
00062   cache_entry_t      * pentry;
00063   state_status_t       state_status = STATE_SUCCESS;
00064   char                 buffer[MAXNETOBJ_SZ * 2];
00065   state_nsm_client_t * nsm_client;
00066   state_nlm_client_t * nlm_client;
00067   state_owner_t      * nlm_owner, * holder;
00068   fsal_lock_param_t    lock, conflict;
00069   int                  rc;
00070   int                  grace = nfs_in_grace();
00071   state_block_data_t * pblock_data;
00072   const char         * proc_name = "nlm4_Lock";
00073   care_t               care = CARE_MONITOR;
00074 
00075   if(preq->rq_proc == NLMPROC4_NM_LOCK)
00076     {
00077       /* If call is a NM lock, indicate that we care about NLM client but
00078        * will not monitor.
00079        */
00080       proc_name = "nlm4_NM_Lock";
00081       care = CARE_NO_MONITOR;
00082     }
00083 
00084   netobj_to_string(&arg->cookie, buffer, 1024);
00085   LogDebug(COMPONENT_NLM,
00086            "REQUEST PROCESSING: Calling %s svid=%d off=%llx len=%llx cookie=%s reclaim=%s",
00087            proc_name,
00088            (int) arg->alock.svid,
00089            (unsigned long long) arg->alock.l_offset,
00090            (unsigned long long) arg->alock.l_len, buffer,
00091            arg->reclaim ? "yes" : "no");
00092 
00093   if(!copy_netobj(&pres->res_nlm4test.cookie, &arg->cookie))
00094     {
00095       pres->res_nlm4.stat.stat = NLM4_FAILED;
00096       LogDebug(COMPONENT_NLM, "REQUEST RESULT: %s %s",
00097                proc_name, lock_result_str(pres->res_nlm4.stat.stat));
00098       return NFS_REQ_OK;
00099     }
00100 
00101   /* allow only reclaim lock request during recovery and visa versa */
00102   if((grace && !arg->reclaim) ||
00103      (!grace && arg->reclaim))
00104     {
00105       pres->res_nlm4.stat.stat = NLM4_DENIED_GRACE_PERIOD;
00106       LogDebug(COMPONENT_NLM, "REQUEST RESULT: %s %s",
00107                proc_name, lock_result_str(pres->res_nlm4.stat.stat));
00108       return NFS_REQ_OK;
00109     }
00110 
00111   rc = nlm_process_parameters(preq,
00112                               arg->exclusive,
00113                               &arg->alock,
00114                               &lock,
00115                               &pentry,
00116                               pcontext,
00117                               care,
00118                               &nsm_client,
00119                               &nlm_client,
00120                               &nlm_owner,
00121                               &pblock_data);
00122 
00123   if(rc >= 0)
00124     {
00125       /* Present the error back to the client */
00126       pres->res_nlm4.stat.stat = (nlm4_stats)rc;
00127       LogDebug(COMPONENT_NLM, "REQUEST RESULT: %s %s",
00128                proc_name, lock_result_str(pres->res_nlm4.stat.stat));
00129       return NFS_REQ_OK;
00130     }
00131 
00132   /* Cast the state number into a state pointer to protect
00133    * locks from a client that has rebooted from the SM_NOTIFY
00134    * that will release old locks
00135    */
00136   if(state_lock(pentry,
00137                 pcontext,
00138                 pexport,
00139                 nlm_owner,
00140                 (void *) (ptrdiff_t) arg->state,
00141                 arg->block ? STATE_NLM_BLOCKING : STATE_NON_BLOCKING,
00142                 pblock_data,
00143                 &lock,
00144                 &holder,
00145                 &conflict,
00146                 &state_status) != STATE_SUCCESS)
00147     {
00148       pres->res_nlm4test.test_stat.stat = nlm_convert_state_error(state_status);
00149 
00150       if(state_status == STATE_LOCK_CONFLICT)
00151         {
00152           nlm_process_conflict(&pres->res_nlm4test.test_stat.nlm4_testrply_u.holder,
00153                                holder,
00154                                &conflict);
00155         }
00156 
00157       /* If we didn't block, release the block data */
00158       if(state_status != STATE_LOCK_BLOCKED && pblock_data != NULL)
00159         gsh_free(pblock_data);
00160     }
00161   else
00162     {
00163       pres->res_nlm4.stat.stat = NLM4_GRANTED;
00164     }
00165 
00166   /* Release the NLM Client and NLM Owner references we have */
00167   dec_nsm_client_ref(nsm_client);
00168   dec_nlm_client_ref(nlm_client);
00169   dec_state_owner_ref(nlm_owner);
00170   cache_inode_put(pentry);
00171 
00172   LogDebug(COMPONENT_NLM, "REQUEST RESULT: %s %s",
00173            proc_name, lock_result_str(pres->res_nlm4.stat.stat));
00174   return NFS_REQ_OK;
00175 }
00176 
00177 static void nlm4_lock_message_resp(state_async_queue_t *arg)
00178 {
00179   state_nlm_async_data_t * nlm_arg = &arg->state_async_data.state_nlm_async_data;
00180 
00181   if(isFullDebug(COMPONENT_NLM))
00182     {
00183       char buffer[1024];
00184       netobj_to_string(&nlm_arg->nlm_async_args.nlm_async_res.res_nlm4test.cookie, buffer, 1024);
00185       LogFullDebug(COMPONENT_NLM,
00186                    "Calling nlm_send_async cookie=%s status=%s",
00187                    buffer, lock_result_str(nlm_arg->nlm_async_args.nlm_async_res.res_nlm4.stat.stat));
00188     }
00189   nlm_send_async(NLMPROC4_LOCK_RES,
00190                  nlm_arg->nlm_async_host,
00191                  &(nlm_arg->nlm_async_args.nlm_async_res),
00192                  NULL);
00193   nlm4_Lock_Free(&nlm_arg->nlm_async_args.nlm_async_res);
00194   dec_nsm_client_ref(nlm_arg->nlm_async_host->slc_nsm_client);
00195   dec_nlm_client_ref(nlm_arg->nlm_async_host);
00196   gsh_free(arg);
00197 }
00198 
00210 int nlm4_Lock_Message(nfs_arg_t *parg,
00211                       exportlist_t *pexport,
00212                       fsal_op_context_t *pcontext,
00213                       nfs_worker_data_t *pworker,
00214                       struct svc_req *preq,
00215                       nfs_res_t *pres)
00216 {
00217   state_nlm_client_t * nlm_client = NULL;
00218   state_nsm_client_t * nsm_client;
00219   nlm4_lockargs      * arg = &parg->arg_nlm4_lock;
00220   int                  rc = NFS_REQ_OK;
00221 
00222   LogDebug(COMPONENT_NLM, "REQUEST PROCESSING: Calling nlm_Lock_Message");
00223 
00224   nsm_client = get_nsm_client(CARE_NO_MONITOR, preq->rq_xprt, arg->alock.caller_name);
00225 
00226   if(nsm_client != NULL)
00227     nlm_client = get_nlm_client(CARE_NO_MONITOR, preq->rq_xprt, nsm_client, arg->alock.caller_name);
00228 
00229   if(nlm_client == NULL)
00230     rc = NFS_REQ_DROP;
00231   else
00232     rc = nlm4_Lock(parg, pexport, pcontext, pworker, preq, pres);
00233 
00234   if(rc == NFS_REQ_OK)
00235     rc = nlm_send_async_res_nlm4(nlm_client, nlm4_lock_message_resp, pres);
00236 
00237   if(rc == NFS_REQ_DROP)
00238     {
00239       if(nsm_client != NULL)
00240         dec_nsm_client_ref(nsm_client);
00241       if(nlm_client != NULL)
00242         dec_nlm_client_ref(nlm_client);
00243       LogCrit(COMPONENT_NLM,
00244             "Could not send async response for nlm_Lock_Message");
00245     }
00246 
00247   return NFS_REQ_DROP;
00248 
00249 }
00250 
00259 void nlm4_Lock_Free(nfs_res_t * pres)
00260 {
00261   netobj_free(&pres->res_nlm4test.cookie);
00262   return;
00263 }