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 <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 }