nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 * 00004 * Copyright CEA/DAM/DIF (2008) 00005 * contributeur : Philippe DENIEL philippe.deniel@cea.fr 00006 * Thomas LEIBOVICI thomas.leibovici@cea.fr 00007 * 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public License 00011 * as published by the Free Software Foundation; either version 3 of 00012 * the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, but 00015 * WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00022 * 02110-1301 USA 00023 */ 00024 00029 #ifdef HAVE_CONFIG_H 00030 #include "config.h" 00031 #endif 00032 00033 #ifdef _SOLARIS 00034 #include "solaris_port.h" 00035 #endif 00036 00037 #include <pthread.h> 00038 #include <ctype.h> 00039 #include "log.h" 00040 #include "HashData.h" 00041 #include "HashTable.h" 00042 #include "nfs4.h" 00043 #include "sal_functions.h" 00044 #include "nfs_proto_functions.h" 00045 #include "nfs_core.h" 00046 00047 size_t strnlen(const char *s, size_t maxlen); 00048 00049 hash_table_t *ht_nfs4_owner; 00050 00051 uint32_t nfs4_owner_counter = 0; 00052 pthread_mutex_t nfs4_owner_counter_lock = PTHREAD_MUTEX_INITIALIZER; 00053 00054 int display_nfs4_owner_key(hash_buffer_t * pbuff, char *str) 00055 { 00056 char * type; 00057 char * strtmp = str; 00058 state_nfs4_owner_name_t * pname = (state_nfs4_owner_name_t *) pbuff->pdata; 00059 00060 if(pname->son_islock) 00061 type = "lock"; 00062 else 00063 type = "open"; 00064 00065 strtmp += sprintf(strtmp, "clientid=%"PRIx64" %s owner=", 00066 pname->son_clientid, 00067 type); 00068 00069 strtmp += DisplayOpaqueValue(pname->son_owner_val, 00070 pname->son_owner_len, 00071 strtmp); 00072 00073 return strtmp - str; 00074 } 00075 00076 int display_nfs4_owner(state_owner_t *powner, char *str) 00077 { 00078 char * strtmp = str; 00079 00080 strtmp += sprintf(strtmp, "%s %p:", 00081 state_owner_type_to_str(powner->so_type), 00082 powner); 00083 00084 strtmp += sprintf(strtmp, " clientid={%"PRIx64"} owner=", 00085 powner->so_owner.so_nfs4_owner.so_clientid); 00086 00087 strtmp += DisplayOpaqueValue(powner->so_owner_val, 00088 powner->so_owner_len, 00089 strtmp); 00090 00091 strtmp += sprintf(strtmp, " confirmed=%u counter=%u seqid=%u refcount=%d", 00092 powner->so_owner.so_nfs4_owner.so_confirmed, 00093 powner->so_owner.so_nfs4_owner.so_counter, 00094 powner->so_owner.so_nfs4_owner.so_seqid, 00095 powner->so_refcount); 00096 00097 if(powner->so_owner.so_nfs4_owner.so_related_owner != NULL) 00098 { 00099 strtmp += sprintf(strtmp, " related_owner={"); 00100 strtmp += display_nfs4_owner(powner->so_owner.so_nfs4_owner.so_related_owner, strtmp); 00101 strtmp += sprintf(strtmp, "}"); 00102 } 00103 00104 return strtmp - str; 00105 } 00106 00107 int display_nfs4_owner_val(hash_buffer_t * pbuff, char *str) 00108 { 00109 return display_nfs4_owner((state_owner_t *) (pbuff->pdata), str); 00110 } 00111 00112 int compare_nfs4_owner(state_owner_t * powner1, 00113 state_owner_t * powner2) 00114 { 00115 if(isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE)) 00116 { 00117 char str1[HASHTABLE_DISPLAY_STRLEN]; 00118 char str2[HASHTABLE_DISPLAY_STRLEN]; 00119 00120 display_nfs4_owner(powner1, str1); 00121 display_nfs4_owner(powner2, str2); 00122 LogFullDebug(COMPONENT_STATE, 00123 "{%s} vs {%s}", str1, str2); 00124 } 00125 00126 if(powner1 == NULL || powner2 == NULL) 00127 return 1; 00128 00129 if(powner1 == powner2) 00130 return 0; 00131 00132 if(powner1->so_type == STATE_LOCK_OWNER_NFSV4 && 00133 powner2->so_type == STATE_OPEN_OWNER_NFSV4) 00134 return compare_nfs4_owner(powner1->so_owner.so_nfs4_owner.so_related_owner, 00135 powner2); 00136 00137 if(powner2->so_type == STATE_LOCK_OWNER_NFSV4 && 00138 powner1->so_type == STATE_OPEN_OWNER_NFSV4) 00139 return compare_nfs4_owner(powner2->so_owner.so_nfs4_owner.so_related_owner, 00140 powner1); 00141 00142 if(powner1->so_type != powner2->so_type) 00143 return 1; 00144 00145 if(powner1->so_owner.so_nfs4_owner.so_clientid != 00146 powner2->so_owner.so_nfs4_owner.so_clientid) 00147 return 1; 00148 00149 if(powner1->so_owner_len != 00150 powner2->so_owner_len) 00151 return 1; 00152 00153 return memcmp(powner1->so_owner_val, 00154 powner2->so_owner_val, 00155 powner1->so_owner_len); 00156 } 00157 00158 int compare_nfs4_owner_key(hash_buffer_t * buff1, hash_buffer_t * buff2) 00159 { 00160 if(isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE)) 00161 { 00162 char str1[HASHTABLE_DISPLAY_STRLEN]; 00163 char str2[HASHTABLE_DISPLAY_STRLEN]; 00164 00165 display_nfs4_owner_key(buff1, str1); 00166 display_nfs4_owner_key(buff2, str2); 00167 if(isDebug(COMPONENT_HASHTABLE)) 00168 LogFullDebug(COMPONENT_STATE, 00169 "{%s} vs {%s}", str1, str2); 00170 } 00171 00172 state_nfs4_owner_name_t *pname1 = (state_nfs4_owner_name_t *) buff1->pdata; 00173 state_nfs4_owner_name_t *pname2 = (state_nfs4_owner_name_t *) buff2->pdata; 00174 00175 if(pname1 == NULL || pname2 == NULL) 00176 return 1; 00177 00178 if(pname1->son_islock != pname2->son_islock) 00179 return 1; 00180 00181 if(pname1->son_clientid != pname2->son_clientid) 00182 return 1; 00183 00184 if(pname1->son_owner_len != pname2->son_owner_len) 00185 return 1; 00186 00187 return memcmp(pname1->son_owner_val, pname2->son_owner_val, pname1->son_owner_len); 00188 } /* compare_nfs4_owner */ 00189 00190 uint32_t nfs4_owner_value_hash_func(hash_parameter_t * p_hparam, 00191 hash_buffer_t * buffclef) 00192 { 00193 unsigned int sum = 0; 00194 unsigned int i = 0; 00195 unsigned char c = 0; 00196 unsigned long res = 0; 00197 00198 state_nfs4_owner_name_t *pname = (state_nfs4_owner_name_t *) buffclef->pdata; 00199 00200 /* Compute the sum of all the characters */ 00201 for(i = 0; i < pname->son_owner_len; i++) 00202 { 00203 c = ((char *)pname->son_owner_val)[i]; 00204 sum += c; 00205 } 00206 00207 res = (unsigned long)(pname->son_clientid) + (unsigned long)sum + pname->son_owner_len + pname->son_islock; 00208 00209 if(isDebug(COMPONENT_HASHTABLE)) 00210 LogFullDebug(COMPONENT_STATE, 00211 "value = %lu", res % p_hparam->index_size); 00212 00213 return (unsigned long)(res % p_hparam->index_size); 00214 00215 } /* nfs4_owner_value_hash_func */ 00216 00217 uint64_t nfs4_owner_rbt_hash_func(hash_parameter_t * p_hparam, 00218 hash_buffer_t * buffclef) 00219 { 00220 state_nfs4_owner_name_t *pname = (state_nfs4_owner_name_t *) buffclef->pdata; 00221 00222 unsigned int sum = 0; 00223 unsigned int i = 0; 00224 unsigned char c = 0; 00225 unsigned long res = 0; 00226 00227 /* Compute the sum of all the characters */ 00228 for(i = 0; i < pname->son_owner_len; i++) 00229 { 00230 c = ((char *)pname->son_owner_val)[i]; 00231 sum += c; 00232 } 00233 00234 res = (unsigned long)(pname->son_clientid) + (unsigned long)sum + pname->son_owner_len + pname->son_islock; 00235 00236 if(isDebug(COMPONENT_HASHTABLE)) 00237 LogFullDebug(COMPONENT_STATE, "rbt = %lu", res); 00238 00239 return res; 00240 } /* state_id_rbt_hash_func */ 00241 00242 void remove_nfs4_owner(state_owner_t * powner, 00243 const char * str) 00244 { 00245 hash_buffer_t buffkey, old_key, old_value; 00246 state_nfs4_owner_name_t oname; 00247 int rc; 00248 00249 memset(&oname, 0, sizeof(oname)); 00250 00251 oname.son_clientid = powner->so_owner.so_nfs4_owner.so_clientid; 00252 oname.son_owner_len = powner->so_owner_len; 00253 oname.son_islock = powner->so_type == STATE_LOCK_OWNER_NFSV4; 00254 memcpy(oname.son_owner_val, powner->so_owner_val, powner->so_owner_len); 00255 00256 buffkey.pdata = (caddr_t) &oname; 00257 buffkey.len = sizeof(*powner); 00258 00259 rc = HashTable_DelRef(ht_nfs4_owner, 00260 &buffkey, 00261 &old_key, 00262 &old_value, 00263 Hash_dec_state_owner_ref); 00264 00265 switch(rc) 00266 { 00267 case HASHTABLE_SUCCESS: 00268 if(powner->so_type == STATE_LOCK_OWNER_NFSV4 && 00269 powner->so_owner.so_nfs4_owner.so_related_owner != NULL) 00270 dec_state_owner_ref(powner->so_owner.so_nfs4_owner.so_related_owner); 00271 00272 /* Release the owner_name (key) and owner (data) back to appropriate pools */ 00273 LogFullDebug(COMPONENT_STATE, "Free %s", str); 00274 00275 nfs4_Compound_FreeOne(&powner->so_owner.so_nfs4_owner.so_resp); 00276 00277 P(powner->so_owner.so_nfs4_owner.so_pclientid->cid_mutex); 00278 00279 glist_del(&powner->so_owner.so_nfs4_owner.so_perclient); 00280 00281 V(powner->so_owner.so_nfs4_owner.so_pclientid->cid_mutex); 00282 00283 dec_client_id_ref(powner->so_owner.so_nfs4_owner.so_pclientid); 00284 00285 pool_free(state_owner_pool, old_value.pdata); 00286 pool_free(state_nfs4_owner_name_pool, old_key.pdata); 00287 break; 00288 00289 case HASHTABLE_NOT_DELETED: 00290 /* ref count didn't end up at 0, don't free. */ 00291 LogDebug(COMPONENT_STATE, 00292 "HashTable_DelRef didn't reduce refcount to 0 for %s", 00293 str); 00294 break; 00295 00296 default: 00297 /* some problem occurred */ 00298 LogDebug(COMPONENT_STATE, 00299 "HashTable_DelRef failed (%s) for %s", 00300 hash_table_err_to_str(rc), str); 00301 break; 00302 } 00303 } 00304 00316 int Init_nfs4_owner(nfs4_owner_parameter_t param) 00317 { 00318 00319 if((ht_nfs4_owner = HashTable_Init(¶m.hash_param)) == NULL) 00320 { 00321 LogCrit(COMPONENT_STATE, 00322 "Cannot init NFS Open Owner cache"); 00323 return -1; 00324 } 00325 00326 return 0; 00327 } /* nfs4_Init_nfs4_owner */ 00328 00338 int nfs4_owner_Set(state_nfs4_owner_name_t * pname, 00339 state_owner_t * powner) 00340 { 00341 hash_buffer_t buffkey; 00342 hash_buffer_t buffval; 00343 int rc; 00344 00345 buffkey.pdata = (caddr_t) pname; 00346 buffkey.len = sizeof(state_nfs4_owner_name_t); 00347 00348 if(isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE)) 00349 { 00350 char str[HASHTABLE_DISPLAY_STRLEN]; 00351 00352 display_nfs4_owner_key(&buffkey, str); 00353 LogFullDebug(COMPONENT_STATE, 00354 "KEY {%s}", str); 00355 } 00356 00357 buffval.pdata = (caddr_t) powner; 00358 buffval.len = sizeof(state_owner_t); 00359 00360 P(nfs4_owner_counter_lock); 00361 nfs4_owner_counter += 1; 00362 powner->so_owner.so_nfs4_owner.so_counter = nfs4_owner_counter; 00363 V(nfs4_owner_counter_lock); 00364 00365 rc = HashTable_Test_And_Set 00366 (ht_nfs4_owner, &buffkey, &buffval, 00367 HASHTABLE_SET_HOW_SET_NO_OVERWRITE); 00368 if(rc != HASHTABLE_SUCCESS) 00369 { 00370 LogDebug(COMPONENT_STATE, 00371 "Failed to insert nfs4 owner into hash table rc = %d", rc); 00372 return 0; 00373 } 00374 00375 return 1; 00376 } /* nfs4_owner_Set */ 00377 00390 int nfs4_owner_Get_Pointer(state_nfs4_owner_name_t * pname, 00391 state_owner_t ** powner) 00392 { 00393 hash_buffer_t buffkey; 00394 hash_buffer_t buffval; 00395 00396 buffkey.pdata = (caddr_t) pname; 00397 buffkey.len = sizeof(state_nfs4_owner_name_t); 00398 00399 if(isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE)) 00400 { 00401 char str[HASHTABLE_DISPLAY_STRLEN]; 00402 00403 display_nfs4_owner_key(&buffkey, str); 00404 LogFullDebug(COMPONENT_STATE, 00405 "KEY {%s}", str); 00406 } 00407 00408 if(HashTable_GetRef(ht_nfs4_owner, 00409 &buffkey, 00410 &buffval, 00411 Hash_inc_state_owner_ref) != HASHTABLE_SUCCESS) 00412 { 00413 *powner = NULL; 00414 LogFullDebug(COMPONENT_STATE, 00415 "NOTFOUND"); 00416 return 0; 00417 } 00418 00419 *powner = (state_owner_t *) buffval.pdata; 00420 00421 LogFullDebug(COMPONENT_STATE, 00422 "FOUND"); 00423 00424 return 1; 00425 } /* nfs4_owner_Get_Pointer */ 00426 00436 void nfs4_owner_PrintAll(void) 00437 { 00438 HashTable_Log(COMPONENT_STATE, ht_nfs4_owner); 00439 } /* nfs4_owner_PrintAll */ 00440 00441 void convert_nfs4_open_owner(open_owner4 * pnfsowner, 00442 state_nfs4_owner_name_t * pname_owner, 00443 clientid4 clientid) 00444 { 00445 memset(pname_owner, 0, sizeof(*pname_owner)); 00446 00447 if (clientid) 00448 { 00449 pname_owner->son_clientid = clientid; 00450 } 00451 else 00452 { 00453 pname_owner->son_clientid = pnfsowner->clientid; 00454 } 00455 pname_owner->son_owner_len = pnfsowner->owner.owner_len; 00456 pname_owner->son_islock = FALSE; 00457 memcpy(pname_owner->son_owner_val, 00458 pnfsowner->owner.owner_val, 00459 pnfsowner->owner.owner_len); 00460 } /* convert_nfs4_open_owner */ 00461 00462 void convert_nfs4_lock_owner(lock_owner4 * pnfsowner, 00463 state_nfs4_owner_name_t * pname_owner, 00464 clientid4 clientid) 00465 { 00466 memset(pname_owner, 0, sizeof(*pname_owner)); 00467 00468 if (clientid) 00469 { 00470 pname_owner->son_clientid = clientid; 00471 } 00472 else 00473 { 00474 pname_owner->son_clientid = pnfsowner->clientid; 00475 } 00476 pname_owner->son_owner_len = pnfsowner->owner.owner_len; 00477 pname_owner->son_islock = TRUE; 00478 memcpy(pname_owner->son_owner_val, 00479 pnfsowner->owner.owner_val, 00480 pnfsowner->owner.owner_len); 00481 } /* convert_nfs4_lock_owner */ 00482 00483 state_owner_t *create_nfs4_owner(state_nfs4_owner_name_t * pname, 00484 nfs_client_id_t * pclientid, 00485 state_owner_type_t type, 00486 state_owner_t * related_owner, 00487 unsigned int init_seqid) 00488 { 00489 state_owner_t * powner; 00490 state_nfs4_owner_name_t * powner_name; 00491 00492 /* This lock owner is not known yet, allocated and set up a new one */ 00493 powner = pool_alloc(state_owner_pool, NULL); 00494 00495 if(powner == NULL) 00496 return NULL; 00497 00498 powner_name = pool_alloc(state_nfs4_owner_name_pool, NULL); 00499 00500 if(powner_name == NULL) 00501 { 00502 pool_free(state_owner_pool, powner); 00503 return NULL; 00504 } 00505 00506 *powner_name = *pname; 00507 00508 /* set up the content of the open_owner */ 00509 memset(powner, 0, sizeof(*powner)); 00510 powner->so_type = type; 00511 powner->so_owner.so_nfs4_owner.so_seqid = init_seqid; 00512 powner->so_owner.so_nfs4_owner.so_related_owner = related_owner; 00513 powner->so_owner.so_nfs4_owner.so_clientid = pname->son_clientid; 00514 powner->so_owner.so_nfs4_owner.so_pclientid = pclientid; 00515 powner->so_owner_len = pname->son_owner_len; 00516 powner->so_owner.so_nfs4_owner.so_resp.resop = NFS4_OP_ILLEGAL; 00517 powner->so_owner.so_nfs4_owner.so_args.argop = NFS4_OP_ILLEGAL; 00518 powner->so_refcount = 1; 00519 #if 0 00520 /* WAITING FOR COMMUNITY FIX */ 00521 /* setting lock owner confirmed */ 00522 if ( type == STATE_LOCK_OWNER_NFSV4) 00523 powner->so_owner.so_nfs4_owner.so_confirmed = 1; 00524 #endif 00525 init_glist(&powner->so_lock_list); 00526 init_glist(&powner->so_owner.so_nfs4_owner.so_state_list); 00527 00528 memcpy(powner->so_owner_val, 00529 pname->son_owner_val, 00530 pname->son_owner_len); 00531 00532 powner->so_owner_val[powner->so_owner_len] = '\0'; 00533 00534 if(pthread_mutex_init(&powner->so_mutex, NULL) == -1) 00535 { 00536 pool_free(state_owner_pool, powner); 00537 pool_free(state_nfs4_owner_name_pool, powner_name); 00538 return NULL; 00539 } 00540 00541 if(!nfs4_owner_Set(powner_name, powner)) 00542 { 00543 pool_free(state_owner_pool, powner); 00544 pool_free(state_nfs4_owner_name_pool, powner_name); 00545 return NULL; 00546 } 00547 00548 if(isFullDebug(COMPONENT_STATE)) 00549 { 00550 char str[HASHTABLE_DISPLAY_STRLEN]; 00551 00552 DisplayOwner(powner, str); 00553 LogFullDebug(COMPONENT_STATE, 00554 "New Owner %s", str); 00555 } 00556 00557 /* Increment refcount on related owner */ 00558 if(related_owner != NULL) 00559 inc_state_owner_ref(related_owner); 00560 00561 P(pclientid->cid_mutex); 00562 00563 if (type == STATE_OPEN_OWNER_NFSV4) 00564 { 00565 /* If open owner, add to clientid lock owner list */ 00566 powner->so_refcount++; 00567 glist_add_tail(&pclientid->cid_openowners, &powner->so_owner.so_nfs4_owner.so_perclient); 00568 } 00569 else if(type == STATE_LOCK_OWNER_NFSV4) 00570 { 00571 /* If lock owner, add to clientid open owner list */ 00572 powner->so_refcount++; 00573 glist_add_tail(&pclientid->cid_lockowners, &powner->so_owner.so_nfs4_owner.so_perclient); 00574 } 00575 00576 /* Increment reference count for clientid record */ 00577 inc_client_id_ref(pclientid); 00578 00579 V(pclientid->cid_mutex); 00580 00581 return powner; 00582 } 00583 00584 void Process_nfs4_conflict(LOCK4denied * denied, /* NFS v4 LOck4denied structure to fill in */ 00585 state_owner_t * holder, /* owner that holds conflicting lock */ 00586 fsal_lock_param_t * conflict) /* description of conflicting lock */ 00587 { 00588 /* A conflicting lock from a different lock_owner, returns NFS4ERR_DENIED */ 00589 denied->offset = conflict->lock_start; 00590 denied->length = conflict->lock_length; 00591 00592 if(conflict->lock_type == FSAL_LOCK_R) 00593 denied->locktype = READ_LT; 00594 else 00595 denied->locktype = WRITE_LT; 00596 00597 if(holder != NULL && holder->so_owner_len != 0) 00598 denied->owner.owner.owner_val = gsh_malloc(holder->so_owner_len); 00599 else 00600 denied->owner.owner.owner_val = NULL; 00601 00602 LogFullDebug(COMPONENT_STATE, 00603 "denied->owner.owner.owner_val = %p", 00604 denied->owner.owner.owner_val); 00605 00606 if(denied->owner.owner.owner_val != NULL) 00607 { 00608 denied->owner.owner.owner_len = holder->so_owner_len; 00609 00610 memcpy(denied->owner.owner.owner_val, 00611 holder->so_owner_val, 00612 holder->so_owner_len); 00613 } 00614 else 00615 { 00616 denied->owner.owner.owner_len = unknown_owner.so_owner_len; 00617 denied->owner.owner.owner_val = unknown_owner.so_owner_val; 00618 } 00619 00620 if(holder != NULL && holder->so_type == STATE_LOCK_OWNER_NFSV4) 00621 denied->owner.clientid = holder->so_owner.so_nfs4_owner.so_clientid; 00622 else 00623 denied->owner.clientid = 0; 00624 00625 /* Release any lock owner reference passed back from SAL */ 00626 if(holder != NULL) 00627 dec_state_owner_ref(holder); 00628 } 00629 00630 void Release_nfs4_denied(LOCK4denied * denied) 00631 { 00632 if(denied->owner.owner.owner_val != unknown_owner.so_owner_val && 00633 denied->owner.owner.owner_val != NULL) 00634 gsh_free(denied->owner.owner.owner_val); 00635 } 00636 00637 void Copy_nfs4_denied(LOCK4denied * denied_dst, LOCK4denied * denied_src) 00638 { 00639 memcpy(denied_dst, denied_src, sizeof(*denied_dst)); 00640 00641 if(denied_src->owner.owner.owner_val != unknown_owner.so_owner_val && 00642 denied_src->owner.owner.owner_val != NULL) 00643 { 00644 denied_dst->owner.owner.owner_val 00645 = gsh_malloc(denied_src->owner.owner.owner_len); 00646 LogFullDebug(COMPONENT_STATE, 00647 "denied_dst->owner.owner.owner_val = %p", 00648 denied_dst->owner.owner.owner_val); 00649 } 00650 00651 if(denied_dst->owner.owner.owner_val == NULL) 00652 { 00653 denied_dst->owner.owner.owner_len = unknown_owner.so_owner_len; 00654 denied_dst->owner.owner.owner_val = unknown_owner.so_owner_val; 00655 } 00656 } 00657 00658 void Copy_nfs4_state_req(state_owner_t * powner, 00659 seqid4 seqid, 00660 nfs_argop4 * args, 00661 compound_data_t * data, 00662 nfs_resop4 * resp, 00663 const char * tag) 00664 { 00665 /* Simplify use of this function when we may not be keeping any data for the 00666 * state owner 00667 */ 00668 if(powner == NULL) 00669 return; 00670 00671 LogFullDebug(COMPONENT_STATE, 00672 "%s: saving response %p so_seqid %u new seqid %u", 00673 tag, powner, powner->so_owner.so_nfs4_owner.so_seqid, seqid); 00674 00675 /* Free previous response */ 00676 nfs4_Compound_FreeOne(&powner->so_owner.so_nfs4_owner.so_resp); 00677 00678 /* Copy new response */ 00679 nfs4_Compound_CopyResOne(&powner->so_owner.so_nfs4_owner.so_resp, resp); 00680 00681 /* Deep copy OPEN args? */ 00682 if(powner->so_owner.so_nfs4_owner.so_args.argop == NFS4_OP_OPEN) 00683 { 00684 } 00685 00686 /* Copy bnew args */ 00687 memcpy(&powner->so_owner.so_nfs4_owner.so_args, 00688 args, 00689 sizeof(powner->so_owner.so_nfs4_owner.so_args)); 00690 00691 /* Copy new file */ 00692 powner->so_owner.so_nfs4_owner.so_last_pentry = data->current_entry; 00693 00694 /* Deep copy OPEN args? */ 00695 if(args->argop == NFS4_OP_OPEN) 00696 { 00697 } 00698 00699 /* Store new seqid */ 00700 powner->so_owner.so_nfs4_owner.so_seqid = seqid; 00701 } 00702 00714 bool_t Check_nfs4_seqid(state_owner_t * powner, 00715 seqid4 seqid, 00716 nfs_argop4 * args, 00717 compound_data_t * data, 00718 nfs_resop4 * resp, 00719 const char * tag) 00720 { 00721 seqid4 next; 00722 00723 /* Check if any owner to verify seqid against */ 00724 if(powner == NULL) 00725 { 00726 LogFullDebug(COMPONENT_STATE, 00727 "%s: Unknown owner doesn't have saved seqid, req seqid %u", 00728 tag, seqid); 00729 return TRUE; 00730 } 00731 00732 /* If this is a new state owner, client may start with any seqid */ 00733 if(powner->so_owner.so_nfs4_owner.so_last_pentry == NULL) 00734 { 00735 LogFullDebug(COMPONENT_STATE, 00736 "%s: New owner %p doesn't have saved seqid, req seqid %u", 00737 tag, powner, seqid); 00738 return TRUE; 00739 } 00740 00741 /* Check for valid next seqid */ 00742 next = powner->so_owner.so_nfs4_owner.so_seqid + 1; 00743 00744 LogFullDebug(COMPONENT_STATE, 00745 "%s: Check powner %p so_seqid %u next %u req seqid %u", 00746 tag, powner, powner->so_owner.so_nfs4_owner.so_seqid, next, seqid); 00747 00748 if(seqid == next) 00749 return TRUE; 00750 00751 /* All NFS4 responses have the status in the same place, so use any to set NFS4ERR_BAD_SEQID */ 00752 resp->nfs_resop4_u.oplock.status = NFS4ERR_BAD_SEQID; 00753 00754 /* Now check for valid replay */ 00755 if(powner->so_owner.so_nfs4_owner.so_seqid != seqid) 00756 { 00757 LogDebug(COMPONENT_STATE, 00758 "%s: Invalid seqid %u in request (not replay), expected seqid %u, returning NFS4ERR_BAD_SEQID", 00759 tag, seqid, powner->so_owner.so_nfs4_owner.so_seqid); 00760 return FALSE; 00761 } 00762 00763 if(args->argop != powner->so_owner.so_nfs4_owner.so_args.argop) 00764 { 00765 LogDebug(COMPONENT_STATE, 00766 "%s: Invalid seqid in request %u (not replay - not same op), returning NFS4ERR_BAD_SEQID", 00767 tag, seqid); 00768 return FALSE; 00769 } 00770 00771 if(powner->so_owner.so_nfs4_owner.so_last_pentry != data->current_entry) 00772 { 00773 LogDebug(COMPONENT_STATE, 00774 "%s: Invalid seqid in request %u (not replay - wrong file), returning NFS4ERR_BAD_SEQID", 00775 tag, seqid); 00776 return FALSE; 00777 } 00778 00779 // TODO FSF: add more checks here... 00780 00781 LogDebug(COMPONENT_STATE, 00782 "%s: Copying saved response for seqid %u", 00783 tag, seqid); 00784 00785 /* Copy the saved response and tell caller to use it */ 00786 nfs4_Compound_CopyResOne(resp, &powner->so_owner.so_nfs4_owner.so_resp); 00787 00788 return FALSE; 00789 } 00790 00792 state_status_t get_clientid_owner(clientid4 clientid, 00793 state_owner_t **clientid_owner) 00794 { 00795 /* Pointer to client record, retrieved by ID and in which the 00796 client state owner is stored */ 00797 nfs_client_id_t *pclientid = NULL; 00798 /* Return code for error checking */ 00799 int rc = 0; 00800 00801 if ((rc = nfs_client_id_get_confirmed(clientid, &pclientid)) 00802 != CLIENT_ID_SUCCESS) 00803 { 00804 return STATE_NOT_FOUND; 00805 } 00806 else 00807 { 00808 *clientid_owner = &pclientid->cid_owner; 00809 dec_client_id_ref(pclientid); 00810 return STATE_SUCCESS; 00811 } 00812 }