nfs-ganesha 1.4

nlm_util.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 <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 "nsm.h"
00041 #include "nlm_async.h"
00042 #include "nfs_core.h"
00043 #include "nfs_tcb.h"
00044 
00045 /* nlm grace time tracking */
00046 static struct timeval nlm_grace_tv;
00047 #define NLM4_GRACE_PERIOD 10
00048 /*
00049  * Time after which we should retry the granted
00050  * message request again
00051  */
00052 #define NLM4_CLIENT_GRACE_PERIOD 3
00053 
00054 /* We manage our own cookie for GRANTED call backs
00055  * Cookie 
00056  */
00057 typedef struct granted_cookie_t
00058 {
00059   unsigned long gc_seconds;
00060   unsigned long gc_microseconds;
00061   unsigned long gc_cookie;
00062 } granted_cookie_t;
00063 
00064 granted_cookie_t granted_cookie;
00065 pthread_mutex_t granted_mutex = PTHREAD_MUTEX_INITIALIZER;
00066 
00067 void next_granted_cookie(granted_cookie_t *cookie)
00068 {
00069   P(granted_mutex);
00070   granted_cookie.gc_cookie++;
00071   *cookie = granted_cookie;
00072   V(granted_mutex);
00073 }
00074 
00075 const char *lock_result_str(int rc)
00076 {
00077   switch(rc)
00078     {
00079       case NLM4_GRANTED:             return "NLM4_GRANTED";
00080       case NLM4_DENIED:              return "NLM4_DENIED";
00081       case NLM4_DENIED_NOLOCKS:      return "NLM4_DENIED_NOLOCKS";
00082       case NLM4_BLOCKED:             return "NLM4_BLOCKED";
00083       case NLM4_DENIED_GRACE_PERIOD: return "NLM4_DENIED_GRACE_PERIOD";
00084       case NLM4_DEADLCK:             return "NLM4_DEADLCK";
00085       case NLM4_ROFS:                return "NLM4_ROFS";
00086       case NLM4_STALE_FH:            return "NLM4_STALE_FH";
00087       case NLM4_FBIG:                return "NLM4_FBIG";
00088       case NLM4_FAILED:              return "NLM4_FAILED";
00089       default: return "Unknown";
00090     }
00091 }
00092 
00093 inline uint64_t lock_end(uint64_t start, uint64_t len)
00094 {
00095   if(len == 0)
00096     return UINT64_MAX;
00097   else
00098     return start + len - 1;
00099 }
00100 
00101 bool_t fill_netobj(netobj * dst, char *data, int len)
00102 {
00103   dst->n_len   = 0;
00104   dst->n_bytes = NULL;
00105   if(len != 0)
00106     {
00107       dst->n_bytes = gsh_malloc(len);
00108       if(dst->n_bytes != NULL)
00109         {
00110           dst->n_len = len;
00111           memcpy(dst->n_bytes, data, len);
00112         }
00113       else
00114         return FALSE;
00115     }
00116   return TRUE;
00117 }
00118 
00119 netobj *copy_netobj(netobj * dst, netobj * src)
00120 {
00121   if(dst == NULL)
00122     return NULL;
00123   dst->n_len = 0;
00124   if(src->n_len != 0)
00125     {
00126       dst->n_bytes = gsh_malloc(src->n_len);
00127       if(!dst->n_bytes)
00128         return NULL;
00129       memcpy(dst->n_bytes, src->n_bytes, src->n_len);
00130     }
00131   else
00132     dst->n_bytes = NULL;
00133 
00134   dst->n_len = src->n_len;
00135   return dst;
00136 }
00137 
00138 void netobj_free(netobj * obj)
00139 {
00140   if(obj->n_bytes)
00141     gsh_free(obj->n_bytes);
00142 }
00143 
00144 void netobj_to_string(netobj *obj, char *buffer, int maxlen)
00145 {
00146   int len = obj->n_len;
00147   if((len * 2) + 10 > maxlen)
00148     len = (maxlen - 10) / 2;
00149 
00150   DisplayOpaqueValue(obj->n_bytes, len, buffer);
00151 }
00152 
00153 void nlm_init(void)
00154 {
00155   /* start NLM grace period */
00156   gettimeofday(&nlm_grace_tv, NULL);
00157 
00158   /* also use this time to initialize granted_cookie */
00159   granted_cookie.gc_seconds      = (unsigned long) nlm_grace_tv.tv_sec;
00160   granted_cookie.gc_microseconds = (unsigned long) nlm_grace_tv.tv_usec;
00161   granted_cookie.gc_cookie       = 0;
00162 }
00163 
00164 void free_grant_arg(state_async_queue_t *arg)
00165 {
00166   state_nlm_async_data_t * nlm_arg = &arg->state_async_data.state_nlm_async_data;
00167   netobj_free(&nlm_arg->nlm_async_args.nlm_async_grant.cookie);
00168   netobj_free(&nlm_arg->nlm_async_args.nlm_async_grant.alock.oh);
00169   netobj_free(&nlm_arg->nlm_async_args.nlm_async_grant.alock.fh);
00170   if(nlm_arg->nlm_async_args.nlm_async_grant.alock.caller_name != NULL)
00171     gsh_free(nlm_arg->nlm_async_args.nlm_async_grant.alock.caller_name);
00172   gsh_free(arg);
00173 }
00174 
00181 static void nlm4_send_grant_msg(state_async_queue_t *arg)
00182 {
00183   int                      retval;
00184   char                     buffer[1024];
00185   state_status_t           state_status = STATE_SUCCESS;
00186   state_cookie_entry_t   * cookie_entry;
00187   fsal_op_context_t        context, * pcontext = &context;
00188   state_nlm_async_data_t * nlm_arg = &arg->state_async_data.state_nlm_async_data;
00189 
00190   if(isDebug(COMPONENT_NLM))
00191     {
00192       netobj_to_string(&nlm_arg->nlm_async_args.nlm_async_grant.cookie,
00193                        buffer, sizeof(buffer));
00194 
00195       LogDebug(COMPONENT_NLM,
00196                "Sending GRANTED for arg=%p svid=%d start=%llx len=%llx cookie=%s",
00197                arg, nlm_arg->nlm_async_args.nlm_async_grant.alock.svid,
00198                (unsigned long long) nlm_arg->nlm_async_args.nlm_async_grant.alock.l_offset,
00199                (unsigned long long) nlm_arg->nlm_async_args.nlm_async_grant.alock.l_len,
00200                buffer);
00201     }
00202 
00203   retval = nlm_send_async(NLMPROC4_GRANTED_MSG,
00204                           nlm_arg->nlm_async_host,
00205                           &(nlm_arg->nlm_async_args.nlm_async_grant),
00206                           nlm_arg->nlm_async_key);
00207 
00208   dec_nlm_client_ref(nlm_arg->nlm_async_host);
00209   free_grant_arg(arg);
00210 
00211   /* If success, we are done. */
00212   if(retval == RPC_SUCCESS)
00213     return;
00214 
00215   /*
00216    * We are not able call granted callback. Some client may retry
00217    * the lock again. So remove the existing blocked nlm entry
00218    */
00219   LogMajor(COMPONENT_NLM,
00220            "GRANTED_MSG RPC call failed with return code %d. Removing the blocking lock",
00221            retval);
00222 
00223   if(state_find_grant(nlm_arg->nlm_async_args.nlm_async_grant.cookie.n_bytes,
00224                       nlm_arg->nlm_async_args.nlm_async_grant.cookie.n_len,
00225                       &cookie_entry,
00226                       &state_status) != STATE_SUCCESS)
00227     {
00228       /* This must be an old NLM_GRANTED_RES */
00229       LogFullDebug(COMPONENT_NLM,
00230                    "Could not find cookie=%s status=%s",
00231                    buffer, state_err_str(state_status));
00232       return;
00233     }
00234 
00235   pthread_rwlock_wrlock(&cookie_entry->sce_pentry->state_lock);
00236 
00237   if(cookie_entry->sce_lock_entry->sle_block_data == NULL ||
00238      !nlm_block_data_to_fsal_context(cookie_entry->sce_lock_entry->sle_block_data,
00239                                      pcontext))
00240     {
00241       /* Wow, we're not doing well... */
00242       pthread_rwlock_unlock(&cookie_entry->sce_pentry->state_lock);
00243       LogFullDebug(COMPONENT_NLM,
00244                    "Could not find block data for cookie=%s (must be an old NLM_GRANTED_RES)",
00245                    buffer);
00246       return;
00247     }
00248 
00249   pthread_rwlock_unlock(&cookie_entry->sce_pentry->state_lock);
00250 
00251   if(state_release_grant(pcontext,
00252                          cookie_entry,
00253                          &state_status) != STATE_SUCCESS)
00254     {
00255       /* Huh? */
00256       LogFullDebug(COMPONENT_NLM,
00257                    "Could not release cookie=%s status=%s",
00258                    buffer, state_err_str(state_status));
00259     }
00260 }
00261 
00262 int nlm_process_parameters(struct svc_req        * preq,
00263                            bool_t                  exclusive,
00264                            nlm4_lock             * alock,
00265                            fsal_lock_param_t     * plock,
00266                            cache_entry_t        ** ppentry,
00267                            fsal_op_context_t     * pcontext,
00268                            care_t                  care,
00269                            state_nsm_client_t   ** ppnsm_client,
00270                            state_nlm_client_t   ** ppnlm_client,
00271                            state_owner_t        ** ppowner,
00272                            state_block_data_t   ** ppblock_data)
00273 {
00274   cache_inode_fsal_data_t fsal_data;
00275   fsal_attrib_list_t      attr;
00276   cache_inode_status_t    cache_status;
00277   SVCXPRT                *ptr_svc = preq->rq_xprt;
00278   int                     rc;
00279 
00280   *ppnsm_client = NULL;
00281   *ppnlm_client = NULL;
00282   *ppowner      = NULL;
00283 
00284   /* Convert file handle into a cache entry */
00285   if(alock->fh.n_len > MAX_NETOBJ_SZ ||
00286      !nfs3_FhandleToFSAL((nfs_fh3 *) &alock->fh, &fsal_data.fh_desc, pcontext))
00287     {
00288       /* handle is not valid */
00289       return NLM4_STALE_FH;
00290     }
00291 
00292   /* Now get the cached inode attributes */
00293   *ppentry = cache_inode_get(&fsal_data,
00294                              &attr,
00295                              pcontext,
00296                              NULL,
00297                              &cache_status);
00298   if(*ppentry == NULL)
00299     {
00300       /* handle is not valid */
00301       return NLM4_STALE_FH;
00302     }
00303 
00304   *ppnsm_client = get_nsm_client(care, ptr_svc, alock->caller_name);
00305 
00306   if(*ppnsm_client == NULL)
00307     {
00308       /* If NSM Client is not found, and we don't care (such as unlock),
00309        * just return GRANTED (the unlock must succeed, there can't be
00310        * any locks).
00311        */
00312       if(care != CARE_NOT)
00313         rc = NLM4_DENIED_NOLOCKS;
00314       else
00315         rc = NLM4_GRANTED;
00316 
00317       goto out_put;
00318     }
00319 
00320   *ppnlm_client = get_nlm_client(care, ptr_svc, *ppnsm_client, alock->caller_name);
00321 
00322   if(*ppnlm_client == NULL)
00323     {
00324       /* If NLM Client is not found, and we don't care (such as unlock),
00325        * just return GRANTED (the unlock must succeed, there can't be
00326        * any locks).
00327        */
00328       dec_nsm_client_ref(*ppnsm_client);
00329 
00330       if(care != CARE_NOT)
00331         rc = NLM4_DENIED_NOLOCKS;
00332       else
00333         rc = NLM4_GRANTED;
00334 
00335       goto out_put;
00336     }
00337 
00338   *ppowner = get_nlm_owner(care, *ppnlm_client, &alock->oh, alock->svid);
00339 
00340   if(*ppowner == NULL)
00341     {
00342       LogDebug(COMPONENT_NLM,
00343                "Could not get NLM Owner");
00344       dec_nsm_client_ref(*ppnsm_client);
00345       dec_nlm_client_ref(*ppnlm_client);
00346       *ppnlm_client = NULL;
00347 
00348       /* If owner is not found, and we don't care (such as unlock),
00349        * just return GRANTED (the unlock must succeed, there can't be
00350        * any locks).
00351        */
00352       if(care != CARE_NOT)
00353         rc = NLM4_DENIED_NOLOCKS;
00354       else
00355         rc = NLM4_GRANTED;
00356 
00357       goto out_put;
00358     }
00359 
00360   if(ppblock_data != NULL)
00361     {
00362          *ppblock_data = gsh_malloc(sizeof(**ppblock_data));
00363       /* Fill in the block data, if we don't get one, we will just proceed
00364        * without (which will mean the lock doesn't block.
00365        */
00366       if(*ppblock_data != NULL)
00367         {
00368           memset(*ppblock_data, 0, sizeof(**ppblock_data));
00369           if(copy_xprt_addr(&(*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_hostaddr, ptr_svc) == 0)
00370             {
00371               LogFullDebug(COMPONENT_NLM,
00372                            "copy_xprt_addr failed for Program %d, Version %d, Function %d",
00373                            (int)preq->rq_prog, (int)preq->rq_vers, (int)preq->rq_proc);
00374               gsh_free(*ppblock_data);
00375               *ppblock_data = NULL;
00376               rc = NLM4_FAILED;
00377               goto out_put;
00378             }
00379           (*ppblock_data)->sbd_granted_callback = nlm_granted_callback;
00380           (*ppblock_data)->sbd_block_data_to_fsal_context = nlm_block_data_to_fsal_context;
00381           (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh.n_bytes =
00382             (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh_buf;
00383           (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh.n_len = alock->fh.n_len;
00384           memcpy((*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh_buf,
00385                  alock->fh.n_bytes,
00386                  alock->fh.n_len);
00387           /* FSF TODO: Ultimately I think the following will go away, we won't need the context, just the export */
00388           /* Copy credentials from pcontext */
00389 #ifdef _USE_HPSS
00390 
00391           (*ppblock_data)->sbd_credential.user  =  pcontext->credential.hpss_usercred.Uid ;
00392           (*ppblock_data)->sbd_credential.group =  pcontext->credential.hpss_usercred.Gid ;
00393 #else
00394           (*ppblock_data)->sbd_credential = pcontext->credential;
00395 #endif
00396         }
00397     }
00398   /* Fill in plock */
00399   plock->lock_type   = exclusive ? FSAL_LOCK_W : FSAL_LOCK_R;
00400   plock->lock_start  = alock->l_offset;
00401   plock->lock_length = alock->l_len;
00402 
00403   LogFullDebug(COMPONENT_NLM,
00404                "Parameters Processed");
00405 
00406   return -1;
00407 
00408  out_put:
00409 
00410   cache_inode_put(*ppentry);
00411   *ppentry = NULL;
00412   return rc;
00413 }
00414 
00415 int nlm_process_share_parms(struct svc_req        * preq,
00416                             nlm4_share            * share,
00417                             cache_entry_t        ** ppentry,
00418                             fsal_op_context_t     * pcontext,
00419                             care_t                  care,
00420                             state_nsm_client_t   ** ppnsm_client,
00421                             state_nlm_client_t   ** ppnlm_client,
00422                             state_owner_t        ** ppowner)
00423 {
00424   cache_inode_fsal_data_t fsal_data;
00425   fsal_attrib_list_t      attr;
00426   cache_inode_status_t    cache_status;
00427   SVCXPRT                *ptr_svc = preq->rq_xprt;
00428   int                     rc;
00429 
00430   *ppnsm_client = NULL;
00431   *ppnlm_client = NULL;
00432   *ppowner      = NULL;
00433 
00434   /* Convert file handle into a cache entry */
00435   if(share->fh.n_len > MAX_NETOBJ_SZ ||
00436      !nfs3_FhandleToFSAL((nfs_fh3 *) &share->fh, &fsal_data.fh_desc, pcontext))
00437     {
00438       /* handle is not valid */
00439       return NLM4_STALE_FH;
00440     }
00441 
00442   /* Now get the cached inode attributes */
00443   *ppentry = cache_inode_get(&fsal_data,
00444                              &attr,
00445                              pcontext,
00446                              NULL,
00447                              &cache_status);
00448 
00449   if(*ppentry == NULL)
00450     {
00451       /* handle is not valid */
00452       return NLM4_STALE_FH;
00453     }
00454 
00455   *ppnsm_client = get_nsm_client(care, ptr_svc, share->caller_name);
00456 
00457   if(*ppnsm_client == NULL)
00458     {
00459       /* If NSM Client is not found, and we don't care (for unshare),
00460        * just return GRANTED (the unshare must succeed, there can't be
00461        * any shares).
00462        */
00463       if(care != CARE_NOT)
00464         rc = NLM4_DENIED_NOLOCKS;
00465       else
00466         rc = NLM4_GRANTED;
00467 
00468       goto out_put;
00469     }
00470 
00471   *ppnlm_client = get_nlm_client(care, ptr_svc, *ppnsm_client, share->caller_name);
00472 
00473   if(*ppnlm_client == NULL)
00474     {
00475       /* If NLM Client is not found, and we don't care (such as unlock),
00476        * just return GRANTED (the unlock must succeed, there can't be
00477        * any locks).
00478        */
00479       dec_nsm_client_ref(*ppnsm_client);
00480 
00481       if(care != CARE_NOT)
00482         rc = NLM4_DENIED_NOLOCKS;
00483       else
00484         rc = NLM4_GRANTED;
00485 
00486       goto out_put;
00487     }
00488 
00489   *ppowner = get_nlm_owner(care, *ppnlm_client, &share->oh, 0);
00490 
00491   if(*ppowner == NULL)
00492     {
00493       LogDebug(COMPONENT_NLM,
00494                "Could not get NLM Owner");
00495       dec_nsm_client_ref(*ppnsm_client);
00496       dec_nlm_client_ref(*ppnlm_client);
00497       *ppnlm_client = NULL;
00498 
00499       /* If owner is not found, and we don't care (such as unlock),
00500        * just return GRANTED (the unlock must succeed, there can't be
00501        * any locks).
00502        */
00503       if(care != CARE_NOT)
00504         rc = NLM4_DENIED_NOLOCKS;
00505       else
00506         rc = NLM4_GRANTED;
00507 
00508       goto out_put;
00509     }
00510 
00511   LogFullDebug(COMPONENT_NLM,
00512                "Parameters Processed");
00513 
00514   return -1;
00515 
00516  out_put:
00517 
00518   cache_inode_put(*ppentry);
00519   *ppentry = NULL;
00520   return rc;
00521 }
00522 
00523 void nlm_process_conflict(nlm4_holder          * nlm_holder,
00524                           state_owner_t        * holder,
00525                           fsal_lock_param_t    * conflict)
00526 {
00527   if(conflict != NULL)
00528     {
00529       nlm_holder->exclusive = conflict->lock_type == FSAL_LOCK_W;
00530       nlm_holder->l_offset  = conflict->lock_start;
00531       nlm_holder->l_len     = conflict->lock_length;
00532     }
00533   else
00534     {
00535       /* For some reason, don't have an actual conflict,
00536        * just make it exclusive over the whole file
00537        * (which would conflict with any lock requested).
00538        */
00539       nlm_holder->exclusive = TRUE;
00540       nlm_holder->l_offset  = 0;
00541       nlm_holder->l_len     = 0;
00542     }
00543 
00544   if(holder != NULL)
00545     {
00546       if(holder->so_type == STATE_LOCK_OWNER_NLM)
00547         nlm_holder->svid = holder->so_owner.so_nlm_owner.so_nlm_svid;
00548       else
00549         nlm_holder->svid = 0;
00550       fill_netobj(&nlm_holder->oh,
00551                   holder->so_owner_val,
00552                   holder->so_owner_len);
00553     }
00554   else
00555     {
00556       /* If we don't have an NLM owner, not much we can do. */
00557       nlm_holder->svid       = 0;
00558       fill_netobj(&nlm_holder->oh,
00559                   unknown_owner.so_owner_val,
00560                   unknown_owner.so_owner_len);
00561     }
00562 
00563   /* Release any lock owner reference passed back from SAL */
00564   if(holder != NULL)
00565     dec_state_owner_ref(holder);
00566 }
00567 
00568 nlm4_stats nlm_convert_state_error(state_status_t status)
00569 {
00570   switch(status)
00571     {
00572       case STATE_SUCCESS:        return NLM4_GRANTED;
00573       case STATE_LOCK_CONFLICT:  return NLM4_DENIED;
00574       case STATE_STATE_CONFLICT: return NLM4_DENIED;
00575       case STATE_MALLOC_ERROR:   return NLM4_DENIED_NOLOCKS;
00576       case STATE_LOCK_BLOCKED:   return NLM4_BLOCKED;
00577       case STATE_GRACE_PERIOD:   return NLM4_DENIED_GRACE_PERIOD;
00578       case STATE_LOCK_DEADLOCK:  return NLM4_DEADLCK;
00579       case STATE_READ_ONLY_FS:   return NLM4_ROFS;
00580       case STATE_NOT_FOUND:      return NLM4_STALE_FH;
00581       case STATE_FSAL_ESTALE:    return NLM4_STALE_FH;
00582       case STATE_FILE_BIG:       return NLM4_FBIG;
00583       default:                   return NLM4_FAILED;
00584     }
00585 }
00586 
00587 bool_t nlm_block_data_to_fsal_context(state_block_data_t * block_data,
00588                                       fsal_op_context_t  * fsal_context)
00589 {
00590   exportlist_t           * pexport = NULL;
00591   short                    exportid;
00592   fsal_status_t            fsal_status;
00593   state_nlm_block_data_t * nlm_block_data = &block_data->sbd_block_data.sbd_nlm_block_data;
00594 
00595   /* Get export ID from handle */
00596   exportid = nlm4_FhandleToExportId(&nlm_block_data->sbd_nlm_fh);
00597 
00598   /* Get export matching export ID */
00599   if(exportid < 0 ||
00600      (pexport = nfs_Get_export_by_id(nfs_param.pexportlist, exportid)) == NULL ||
00601      (pexport->options & EXPORT_OPTION_NFSV3) == 0)
00602     {
00603       /* Reject the request for authentication reason (incompatible file handle) */
00604       if(isInfo(COMPONENT_NLM))
00605         {
00606           char dumpfh[1024];
00607           char *reason;
00608           char addrbuf[SOCK_NAME_MAX];
00609           sprint_sockaddr(&nlm_block_data->sbd_nlm_hostaddr,
00610                           addrbuf,
00611                           sizeof(addrbuf));
00612           if(exportid < 0)
00613             reason = "has badly formed handle";
00614           else if(pexport == NULL)
00615             reason = "has invalid export";
00616           else
00617             reason = "V3 not allowed on this export";
00618           sprint_fhandle_nlm(dumpfh, &nlm_block_data->sbd_nlm_fh);
00619           LogMajor(COMPONENT_NLM,
00620                    "NLM4 granted lock from host %s %s, FH=%s",
00621                    addrbuf, reason, dumpfh);
00622         }
00623 
00624       return FALSE;
00625     }
00626 
00627   LogFullDebug(COMPONENT_NLM,
00628                "Found export entry for dirname=%s as exportid=%d",
00629                pexport->dirname, pexport->id);
00630   /* Build the credentials */
00631   fsal_status = FSAL_GetClientContext(fsal_context,
00632                                       &pexport->FS_export_context,
00633                                       block_data->sbd_credential.user,
00634                                       block_data->sbd_credential.group,
00635                                       block_data->sbd_credential.alt_groups,
00636                                       block_data->sbd_credential.nbgroups);
00637 
00638   if(FSAL_IS_ERROR(fsal_status))
00639     {
00640       LogEvent(COMPONENT_NLM,
00641                "Could not get credentials for (uid=%d,gid=%d), fsal error=(%d,%d)",
00642                block_data->sbd_credential.user,
00643                block_data->sbd_credential.group,
00644                fsal_status.major, fsal_status.minor);
00645       return FALSE;
00646     }
00647   else
00648     LogDebug(COMPONENT_NLM,
00649              "FSAL Cred acquired for (uid=%d,gid=%d)",
00650              block_data->sbd_credential.user,
00651              block_data->sbd_credential.group);
00652 
00653   return TRUE;
00654 }
00655 
00656 state_status_t nlm_granted_callback(cache_entry_t        * pentry,
00657                                     state_lock_entry_t   * lock_entry,
00658                                     state_status_t       * pstatus)
00659 {
00660   fsal_op_context_t        fsal_context, *pcontext = &fsal_context;
00661   state_block_data_t     * block_data     = lock_entry->sle_block_data;
00662   state_nlm_block_data_t * nlm_block_data = &block_data->sbd_block_data.sbd_nlm_block_data;
00663   state_cookie_entry_t   * cookie_entry = NULL;
00664   state_async_queue_t    * arg;
00665   nlm4_testargs          * inarg;
00666   state_nlm_owner_t      * nlm_grant_owner  = &lock_entry->sle_owner->so_owner.so_nlm_owner;
00667   state_nlm_client_t     * nlm_grant_client = nlm_grant_owner->so_client;
00668   granted_cookie_t         nlm_grant_cookie;
00669   state_status_t           dummy_status;
00670 
00671   if(nlm_block_data_to_fsal_context(block_data, &fsal_context) != TRUE)
00672     {
00673       *pstatus = STATE_INCONSISTENT_ENTRY;
00674       return *pstatus;
00675     }
00676 
00677   arg = gsh_malloc(sizeof(*arg));
00678   if(arg == NULL)
00679     {
00680       /* If we fail allocation the best is to delete the block entry
00681       * so that client can try again and get the lock. May be
00682       * by then we are able to allocate objects
00683       */
00684       *pstatus = STATE_MALLOC_ERROR;
00685       return *pstatus;
00686    }
00687 
00688   memset(arg, 0, sizeof(*arg));
00689 
00690   /* Get a cookie to use for this grant */
00691   next_granted_cookie(&nlm_grant_cookie);
00692 
00693   /* Add a cookie to the blocked lock pending grant.
00694    * It will also request lock from FSAL.
00695    * Could return STATE_LOCK_BLOCKED because FSAL would have had to block.
00696    */
00697   if(state_add_grant_cookie(pentry,
00698                             pcontext,
00699                             &nlm_grant_cookie,
00700                             sizeof(nlm_grant_cookie),
00701                             lock_entry,
00702                             &cookie_entry,
00703                             pstatus) != STATE_SUCCESS)
00704     {
00705       free_grant_arg(arg);
00706       return *pstatus;
00707     }
00708 
00709   /* Fill in the arguments for the NLMPROC4_GRANTED_MSG call */
00710   inc_nlm_client_ref(nlm_grant_client);
00711   arg->state_async_func = nlm4_send_grant_msg;
00712   arg->state_async_data.state_nlm_async_data.nlm_async_host = nlm_grant_client;
00713   arg->state_async_data.state_nlm_async_data.nlm_async_key  = cookie_entry;
00714   inarg = &arg->state_async_data.state_nlm_async_data.nlm_async_args.nlm_async_grant;
00715 
00716   if(!copy_netobj(&inarg->alock.fh, &nlm_block_data->sbd_nlm_fh))
00717     goto grant_fail_malloc;
00718 
00719   if(!fill_netobj(&inarg->alock.oh,
00720                   lock_entry->sle_owner->so_owner_val,
00721                   lock_entry->sle_owner->so_owner_len))
00722     goto grant_fail_malloc;
00723 
00724   if(!fill_netobj(&inarg->cookie,
00725                   (char *) &nlm_grant_cookie,
00726                   sizeof(nlm_grant_cookie)))
00727     goto grant_fail_malloc;
00728 
00729   inarg->alock.caller_name = gsh_strdup(nlm_grant_client->slc_nlm_caller_name);
00730   if(!inarg->alock.caller_name)
00731     goto grant_fail_malloc;
00732 
00733   inarg->exclusive      = lock_entry->sle_lock.lock_type == FSAL_LOCK_W;
00734   inarg->alock.svid     = nlm_grant_owner->so_nlm_svid;
00735   inarg->alock.l_offset = lock_entry->sle_lock.lock_start;
00736   inarg->alock.l_len    = lock_entry->sle_lock.lock_length;
00737   if(isDebug(COMPONENT_NLM))
00738     {
00739       char buffer[1024];
00740 
00741       netobj_to_string(&inarg->cookie, buffer, sizeof(buffer));
00742 
00743       LogDebug(COMPONENT_NLM,
00744                "Sending GRANTED for arg=%p svid=%d start=%llx len=%llx cookie=%s",
00745                arg, inarg->alock.svid,
00746                (unsigned long long) inarg->alock.l_offset, (unsigned long long) inarg->alock.l_len,
00747                buffer);
00748     }
00749 
00750   /* Now try to schedule NLMPROC4_GRANTED_MSG call */
00751   *pstatus = state_async_schedule(arg);
00752 
00753   if(*pstatus != STATE_SUCCESS)
00754     goto grant_fail;
00755 
00756   return *pstatus;
00757 
00758  grant_fail_malloc:
00759   *pstatus = STATE_MALLOC_ERROR;
00760 
00761  grant_fail:
00762 
00763   /* Something went wrong after we added a grant cookie, need to clean up */
00764 
00765   dec_nlm_client_ref(nlm_grant_client);
00766 
00767   /* Clean up NLMPROC4_GRANTED_MSG arguments */
00768   free_grant_arg(arg);
00769 
00770   /* Cancel the pending grant to release the cookie */
00771   if(state_cancel_grant(pcontext,
00772                         cookie_entry,
00773                         &dummy_status) != STATE_SUCCESS)
00774     {
00775       /* Not much we can do other than log that something bad happened. */
00776       LogCrit(COMPONENT_NLM,
00777               "Unable to clean up GRANTED lock after error");
00778     }
00779 
00780   return *pstatus;
00781 }