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 * This program is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public License 00010 * as published by the Free Software Foundation; either version 3 of 00011 * the License, or (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, but 00014 * WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00021 * 02110-1301 USA 00022 * 00023 * --------------------------------------- 00024 */ 00025 00034 #ifdef HAVE_CONFIG_H 00035 #include "config.h" 00036 #endif 00037 00038 #ifdef _SOLARIS 00039 #include "solaris_port.h" 00040 #endif 00041 00042 #include <stdio.h> 00043 #include <sys/types.h> 00044 #include <ctype.h> /* for having isalnum */ 00045 #include <stdlib.h> /* for having atoi */ 00046 #include <dirent.h> /* for having MAXNAMLEN */ 00047 #include <netdb.h> 00048 #include <netinet/in.h> 00049 #include <arpa/inet.h> 00050 #include <string.h> 00051 #include <pthread.h> 00052 #include <fcntl.h> 00053 #include <sys/file.h> /* for having FNDELAY */ 00054 #include <pwd.h> 00055 #include <grp.h> 00056 00057 #include "rpcal.h" 00058 #include "LRU_List.h" 00059 #include "HashData.h" 00060 #include "HashTable.h" 00061 #include "log.h" 00062 #include "nfs_core.h" 00063 #include "nfs23.h" 00064 #include "nfs4.h" 00065 #include "fsal.h" 00066 #include "nfs_tools.h" 00067 #include "nfs_exports.h" 00068 #include "nfs_file_handle.h" 00069 #include "nfs_dupreq.h" 00070 00071 extern nfs_function_desc_t nfs2_func_desc[]; 00072 extern nfs_function_desc_t nfs3_func_desc[]; 00073 extern nfs_function_desc_t nfs4_func_desc[]; 00074 extern nfs_function_desc_t mnt1_func_desc[]; 00075 extern nfs_function_desc_t mnt3_func_desc[]; 00076 #ifdef _USE_NLM 00077 extern nfs_function_desc_t nlm4_func_desc[]; 00078 #endif /* _USE_NLM */ 00079 #ifdef _USE_RQUOTA 00080 extern nfs_function_desc_t rquota1_func_desc[]; 00081 extern nfs_function_desc_t rquota2_func_desc[]; 00082 #endif /* _USE_QUOTA */ 00083 /* Structure used for duplicated request cache */ 00084 hash_table_t *ht_dupreq_udp; 00085 hash_table_t *ht_dupreq_tcp; 00086 00087 void LogDupReq(const char *label, sockaddr_t *addr, long xid, u_long rq_prog) 00088 { 00089 char namebuf[SOCK_NAME_MAX]; 00090 00091 sprint_sockaddr(addr, namebuf, sizeof(namebuf)); 00092 00093 LogFullDebug(COMPONENT_DUPREQ, 00094 "%s addr=%s xid=%ld rq_prog=%ld", 00095 label, namebuf, xid, rq_prog); 00096 } 00097 00098 static unsigned int get_ipproto_by_xprt( SVCXPRT * xprt ) 00099 { 00100 if( xprt->xp_p2 != NULL ) 00101 return IPPROTO_UDP ; 00102 else if ( xprt->xp_p1 != NULL ) 00103 return IPPROTO_TCP; 00104 else 00105 return IPPROTO_IP ; /* Dummy output */ 00106 } 00107 00108 00109 static hash_table_t * get_ht_by_xprt( SVCXPRT * xprt ) 00110 { 00111 return (get_ipproto_by_xprt( xprt )==IPPROTO_UDP)?ht_dupreq_udp:ht_dupreq_tcp ; 00112 } 00113 00114 00127 int print_entry_dupreq(LRU_data_t data, char *str) 00128 { 00129 strcpy(str, ""); 00130 return 0; 00131 } 00132 00133 static int _remove_dupreq(hash_table_t *ht_dupreq, hash_buffer_t *buffkey, 00134 dupreq_entry_t *pdupreq, int nfs_req_status) 00135 { 00136 int rc; 00137 nfs_function_desc_t funcdesc = nfs2_func_desc[0]; 00138 hash_buffer_t usedbuffkey; 00139 00140 rc = HashTable_Del(ht_dupreq, buffkey, &usedbuffkey, NULL); 00141 00142 /* if hashtable no such key => dupreq garbaged by another thread */ 00143 if(rc != HASHTABLE_SUCCESS && rc != HASHTABLE_ERROR_NO_SUCH_KEY) 00144 return 1; /* Error while cleaning */ 00145 else if(rc == HASHTABLE_ERROR_NO_SUCH_KEY) 00146 return 0; /* don't free the dupreq twice */ 00147 00148 /* Locate the function descriptor associated with this cached request */ 00149 if(pdupreq->rq_prog == nfs_param.core_param.program[P_NFS]) 00150 { 00151 switch (pdupreq->rq_vers) 00152 { 00153 case NFS_V2: 00154 funcdesc = nfs2_func_desc[pdupreq->rq_proc]; 00155 break; 00156 00157 case NFS_V3: 00158 funcdesc = nfs3_func_desc[pdupreq->rq_proc]; 00159 break; 00160 00161 case NFS_V4: 00162 funcdesc = nfs4_func_desc[pdupreq->rq_proc]; 00163 break; 00164 00165 default: 00166 /* We should never go there (this situation is filtered in nfs_rpc_getreq) */ 00167 LogMajor(COMPONENT_DUPREQ, 00168 "NFS Protocol version %d unknown in dupreq_gc", 00169 (int)pdupreq->rq_vers); 00170 } 00171 } 00172 else if(pdupreq->rq_prog == nfs_param.core_param.program[P_MNT]) 00173 { 00174 switch (pdupreq->rq_vers) 00175 { 00176 case MOUNT_V1: 00177 funcdesc = mnt1_func_desc[pdupreq->rq_proc]; 00178 break; 00179 00180 case MOUNT_V3: 00181 funcdesc = mnt3_func_desc[pdupreq->rq_proc]; 00182 break; 00183 00184 default: 00185 /* We should never go there (this situation is filtered in nfs_rpc_getreq) */ 00186 LogMajor(COMPONENT_DUPREQ, 00187 "MOUNT Protocol version %d unknown in dupreq_gc", 00188 (int)pdupreq->rq_vers); 00189 break; 00190 } /* switch( pdupreq->vers ) */ 00191 } 00192 #ifdef _USE_NLM 00193 else if(pdupreq->rq_prog == nfs_param.core_param.program[P_NLM]) 00194 { 00195 00196 switch (pdupreq->rq_vers) 00197 { 00198 case NLM4_VERS: 00199 funcdesc = nlm4_func_desc[pdupreq->rq_proc]; 00200 break; 00201 } /* switch( pdupreq->vers ) */ 00202 } 00203 #endif /* _USE_NLM */ 00204 #ifdef _USE_RQUOTA 00205 else if(pdupreq->rq_prog == nfs_param.core_param.program[P_RQUOTA]) 00206 { 00207 00208 switch (pdupreq->rq_vers) 00209 { 00210 case RQUOTAVERS: 00211 funcdesc = rquota1_func_desc[pdupreq->rq_proc]; 00212 break; 00213 00214 case EXT_RQUOTAVERS: 00215 funcdesc = rquota2_func_desc[pdupreq->rq_proc]; 00216 break; 00217 } /* switch( pdupreq->vers ) */ 00218 } 00219 #endif 00220 else 00221 { 00222 /* We should never go there (this situation is filtered in nfs_rpc_getreq) */ 00223 LogMajor(COMPONENT_DUPREQ, 00224 "protocol %d is not managed", 00225 (int)pdupreq->rq_prog); 00226 } 00227 00228 /* Call the free function */ 00229 if (nfs_req_status == NFS_REQ_OK) 00230 funcdesc.free_function(&(pdupreq->res_nfs)); 00231 00232 /* Send the entry back to the pool */ 00233 pool_free(dupreq_pool, pdupreq); 00234 gsh_free(usedbuffkey.pdata); 00235 00236 return DUPREQ_SUCCESS; 00237 } 00238 00239 int nfs_dupreq_delete(struct svc_req *req) 00240 { 00241 int status; 00242 00243 hash_buffer_t buffkey; 00244 hash_buffer_t buffval; 00245 dupreq_key_t dupkey; 00246 dupreq_entry_t *pdupreq; 00247 hash_table_t * ht_dupreq = NULL; 00248 00249 /* Get correct HT depending on proto used */ 00250 ht_dupreq = get_ht_by_xprt(req->rq_xprt) ; 00251 00252 /* Get the socket address for the key */ 00253 if(copy_xprt_addr(&dupkey.addr, req->rq_xprt) == 0) 00254 return DUPREQ_NOT_FOUND; 00255 00256 dupkey.xid = req->rq_xid; 00257 dupkey.checksum = 0; 00258 00259 /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, 00260 * this also means that buffkey->len will be 0 */ 00261 buffkey.pdata = (caddr_t) &dupkey; 00262 buffkey.len = sizeof(dupreq_key_t); 00263 00264 if(HashTable_Get(ht_dupreq, &buffkey, &buffval) == HASHTABLE_SUCCESS) 00265 { 00266 pdupreq = (dupreq_entry_t *) buffval.pdata; 00267 00268 /* reset timestamp */ 00269 pdupreq->timestamp = time(NULL); 00270 00271 status = DUPREQ_SUCCESS; 00272 } 00273 else { 00274 return DUPREQ_NOT_FOUND; 00275 } 00276 00277 LogDupReq("REMOVING", &pdupreq->addr, pdupreq->xid, pdupreq->rq_prog); 00278 00279 status = _remove_dupreq( ht_dupreq, &buffkey, pdupreq, !NFS_REQ_OK); 00280 return status; 00281 } 00282 00295 int clean_entry_dupreq(LRU_entry_t *pentry, void *addparam) 00296 { 00297 hash_buffer_t buffkey; 00298 dupreq_entry_t *pdupreq = (dupreq_entry_t *) (pentry->buffdata.pdata); 00299 dupreq_key_t dupkey; 00300 hash_table_t * ht_dupreq = NULL ; 00301 00302 /* Get the socket address for the key */ 00303 memcpy((char *)&dupkey.addr, (char *)&pdupreq->addr, sizeof(dupkey.addr)); 00304 dupkey.xid = pdupreq->xid; 00305 dupkey.checksum = pdupreq->checksum; 00306 00307 /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, 00308 * this also means that buffkey->len will be 0 */ 00309 buffkey.pdata = (caddr_t) &dupkey; 00310 buffkey.len = sizeof(dupreq_key_t); 00311 00312 /* Get correct HT depending on proto used */ 00313 if( pdupreq->ipproto == IPPROTO_TCP ) 00314 ht_dupreq = ht_dupreq_tcp ; 00315 else 00316 ht_dupreq = ht_dupreq_udp ; 00317 00318 LogDupReq("Garbage collection on", &pdupreq->addr, pdupreq->xid, pdupreq->rq_prog); 00319 00320 return _remove_dupreq(ht_dupreq, &buffkey, pdupreq, NFS_REQ_OK); 00321 } /* clean_entry_dupreq */ 00322 00340 uint32_t dupreq_value_hash_func(hash_parameter_t * p_hparam, 00341 hash_buffer_t * buffclef) 00342 { 00343 dupreq_key_t *pdupkey = (dupreq_key_t *)(buffclef->pdata); 00344 unsigned long addr_hash = hash_sockaddr((sockaddr_t *) &pdupkey->addr, CHECK_PORT); 00345 00346 return (((unsigned long)pdupkey->xid + addr_hash)^(pdupkey->checksum)) % p_hparam->index_size; 00347 } /* dupreq_value_hash_func */ 00348 00365 uint64_t dupreq_rbt_hash_func(hash_parameter_t * p_hparam, hash_buffer_t * buffclef) 00366 { 00367 dupreq_key_t *pdupkey = (dupreq_key_t *)(buffclef->pdata); 00368 00369 unsigned long addr_hash = hash_sockaddr((sockaddr_t *) &pdupkey->addr, CHECK_PORT); 00370 00371 return (((unsigned long)pdupkey->xid + addr_hash)^(pdupkey->checksum)); 00372 } /* dupreq_rbt_hash_func */ 00373 00390 int compare_req(hash_buffer_t * buff1, hash_buffer_t * buff2) 00391 { 00392 dupreq_key_t *key1 = (dupreq_key_t *)(buff1->pdata); 00393 dupreq_key_t *key2 = (dupreq_key_t *)(buff2->pdata); 00394 00395 if (key1->xid != key2->xid) 00396 return 1; 00397 if (cmp_sockaddr(&key1->addr, &key2->addr, CHECK_PORT) == 0) 00398 return 1; 00399 if (key1->checksum != key2->checksum) 00400 return 1; 00401 return 0; 00402 } /* compare_xid */ 00403 00417 int display_req_key(hash_buffer_t * pbuff, char *str) 00418 { 00419 dupreq_key_t *pdupkey = (dupreq_key_t *)(pbuff->pdata); 00420 char namebuf[SOCK_NAME_MAX]; 00421 00422 sprint_sockaddr(&pdupkey->addr, namebuf, sizeof(namebuf)); 00423 00424 return sprintf(str, "addr=%s xid=%ld checksum=%d", 00425 namebuf, pdupkey->xid, pdupkey->checksum); 00426 00427 } 00428 00442 int display_req_val(hash_buffer_t *pbuff, char *str) 00443 { 00444 dupreq_entry_t *pdupreq = (dupreq_entry_t *)(pbuff->pdata); 00445 char namebuf[SOCK_NAME_MAX]; 00446 00447 sprint_sockaddr(&pdupreq->addr, namebuf, sizeof(namebuf)); 00448 00449 return sprintf(str, "addr=%s xid=%ld checksum=%d rq_prog=%lu rq_vers=%lu rq_proc=%lu", 00450 namebuf, pdupreq->xid, pdupreq->checksum, 00451 pdupreq->rq_prog, pdupreq->rq_vers, pdupreq->rq_proc); 00452 } 00453 00465 int nfs_Init_dupreq(nfs_rpc_dupreq_parameter_t param) 00466 { 00467 if((ht_dupreq_udp = HashTable_Init(¶m.hash_param)) == NULL) 00468 { 00469 LogCrit(COMPONENT_DUPREQ, 00470 "Cannot init the duplicate request hash table"); 00471 return -1; 00472 } 00473 00474 if((ht_dupreq_tcp = HashTable_Init(¶m.hash_param)) == NULL) 00475 { 00476 LogCrit(COMPONENT_DUPREQ, 00477 "Cannot init the duplicate request hash table"); 00478 return -1; 00479 } 00480 00481 00482 return DUPREQ_SUCCESS; 00483 } /* nfs_Init_dupreq */ 00484 00499 int nfs_dupreq_add_not_finished(struct svc_req *req, 00500 nfs_res_t *res_nfs) 00501 { 00502 hash_buffer_t buffkey; 00503 hash_buffer_t buffval; 00504 hash_buffer_t buffdata; 00505 dupreq_entry_t *pdupreq = NULL; 00506 int status = 0; 00507 dupreq_key_t *pdupkey = NULL; 00508 hash_table_t * ht_dupreq = NULL ; 00509 00510 /* Get correct HT depending on proto used */ 00511 ht_dupreq = get_ht_by_xprt(req->rq_xprt); 00512 /* Entry to be cached */ 00513 pdupreq = pool_alloc(dupreq_pool, NULL); 00514 if(pdupreq == NULL) 00515 return DUPREQ_INSERT_MALLOC_ERROR; 00516 00517 if(pthread_mutex_init(&pdupreq->dupreq_mutex, NULL) == -1) 00518 { 00519 pool_free(dupreq_pool, pdupreq); 00520 return DUPREQ_INSERT_MALLOC_ERROR; 00521 } 00522 00523 if((pdupkey = gsh_malloc(sizeof(dupreq_key_t))) == NULL) 00524 { 00525 pool_free(dupreq_pool, pdupreq); 00526 return DUPREQ_INSERT_MALLOC_ERROR; 00527 } 00528 00529 /* Get the socket address for the key and the request */ 00530 if(copy_xprt_addr(&pdupkey->addr, req->rq_xprt) == 0 || 00531 copy_xprt_addr(&pdupreq->addr, req->rq_xprt) == 0) 00532 { 00533 gsh_free(pdupkey); 00534 pool_free(dupreq_pool, pdupreq); 00535 return DUPREQ_INSERT_MALLOC_ERROR; 00536 } 00537 00538 pdupkey->xid = req->rq_xid; 00539 pdupreq->xid = req->rq_xid; 00540 00541 /* Checksum the request */ 00542 pdupkey->checksum = 0; 00543 pdupreq->checksum = 0; 00544 00545 /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, 00546 * this also means that buffkey->len will be 0 */ 00547 buffkey.pdata = (caddr_t) pdupkey; 00548 buffkey.len = sizeof(dupreq_key_t); 00549 00550 /* I build the data with the request pointer that should be in state 'IN USE' */ 00551 pdupreq->rq_prog = req->rq_prog; 00552 pdupreq->rq_vers = req->rq_vers; 00553 pdupreq->rq_proc = req->rq_proc; 00554 pdupreq->timestamp = time(NULL); 00555 pdupreq->processing = 1; 00556 pdupreq->ipproto = get_ipproto_by_xprt(req->rq_xprt) ; 00557 buffdata.pdata = (caddr_t) pdupreq; 00558 buffdata.len = sizeof(dupreq_entry_t); 00559 00560 LogDupReq("Add Not Finished", &pdupreq->addr, pdupreq->xid, pdupreq->rq_prog); 00561 00562 status = HashTable_Test_And_Set(ht_dupreq, &buffkey, &buffdata, 00563 HASHTABLE_SET_HOW_SET_NO_OVERWRITE); 00564 00565 if (status == HASHTABLE_ERROR_KEY_ALREADY_EXISTS) 00566 { 00567 if(HashTable_Get(ht_dupreq, &buffkey, &buffval) == HASHTABLE_SUCCESS) 00568 { 00569 P(((dupreq_entry_t *)buffval.pdata)->dupreq_mutex); 00570 if ( ((dupreq_entry_t *)buffval.pdata)->processing == 1) 00571 { 00572 status = DUPREQ_BEING_PROCESSED; 00573 } 00574 else 00575 { 00576 *res_nfs = ((dupreq_entry_t *) buffval.pdata)->res_nfs; 00577 status = DUPREQ_ALREADY_EXISTS; 00578 } 00579 V(((dupreq_entry_t *)buffval.pdata)->dupreq_mutex); 00580 } 00581 else 00582 status = DUPREQ_NOT_FOUND; 00583 } 00584 else if (status == HASHTABLE_INSERT_MALLOC_ERROR) 00585 status = DUPREQ_INSERT_MALLOC_ERROR; 00586 else 00587 status = DUPREQ_SUCCESS; 00588 if (status != DUPREQ_SUCCESS) { 00589 pool_free(dupreq_pool, pdupreq); 00590 gsh_free(pdupkey); 00591 } 00592 return status; 00593 } /* nfs_dupreq_add_not_finished */ 00594 00612 int nfs_dupreq_finish(struct svc_req *req, nfs_res_t *p_res_nfs, 00613 LRU_list_t *lru_dupreq) 00614 { 00615 hash_buffer_t buffkey; 00616 hash_buffer_t buffval; 00617 LRU_entry_t *pentry = NULL; 00618 LRU_status_t lru_status; 00619 dupreq_key_t dupkey; 00620 dupreq_entry_t *pdupreq; 00621 hash_table_t *ht_dupreq = NULL ; 00622 00623 /* Get correct HT depending on proto used */ 00624 ht_dupreq = get_ht_by_xprt(req->rq_xprt) ; 00625 00626 00627 /* Get the socket address for the key */ 00628 if(copy_xprt_addr(&dupkey.addr, req->rq_xprt) == 0) 00629 return DUPREQ_NOT_FOUND; 00630 00631 dupkey.xid = req->rq_xid; 00632 dupkey.checksum = 0; 00633 00634 /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, 00635 * this also means that buffkey->len will be 0 */ 00636 buffkey.pdata = (caddr_t) &dupkey; 00637 buffkey.len = sizeof(dupreq_key_t); 00638 if(HashTable_Get(ht_dupreq, &buffkey, &buffval) != HASHTABLE_SUCCESS) 00639 return DUPREQ_NOT_FOUND; 00640 00641 pdupreq = (dupreq_entry_t *)buffval.pdata; 00642 00643 LogDupReq("Finish", &pdupreq->addr, pdupreq->xid, pdupreq->rq_prog); 00644 00645 P(pdupreq->dupreq_mutex); 00646 00647 pdupreq->res_nfs = *p_res_nfs; 00648 pdupreq->timestamp = time(NULL); 00649 pdupreq->processing = 0; 00650 00651 V(pdupreq->dupreq_mutex); 00652 00653 /* Add it to lru list */ 00654 if((pentry = LRU_new_entry(lru_dupreq, &lru_status)) == NULL) 00655 return DUPREQ_INSERT_MALLOC_ERROR; 00656 pentry->buffdata.pdata = buffval.pdata; 00657 pentry->buffdata.len = buffval.len; 00658 00659 return DUPREQ_SUCCESS; 00660 } /* nfs_dupreq_finish */ 00661 00675 nfs_res_t nfs_dupreq_get(struct svc_req *req, int *pstatus) 00676 { 00677 hash_buffer_t buffkey; 00678 hash_buffer_t buffval; 00679 nfs_res_t res_nfs; 00680 dupreq_key_t dupkey; 00681 hash_table_t * ht_dupreq = NULL ; 00682 00683 /* Get correct HT depending on proto used */ 00684 ht_dupreq = get_ht_by_xprt(req->rq_xprt) ; 00685 00686 00687 memset(&res_nfs, 0, sizeof(res_nfs)); 00688 00689 /* Get the socket address for the key */ 00690 if(copy_xprt_addr(&dupkey.addr, req->rq_xprt) == 0) 00691 { 00692 *pstatus = DUPREQ_NOT_FOUND; 00693 return res_nfs; 00694 } 00695 00696 dupkey.xid = req->rq_xid; 00697 dupkey.checksum = 0; 00698 00699 /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, 00700 * this also means that buffkey->len will be 0 */ 00701 buffkey.pdata = (caddr_t) &dupkey; 00702 buffkey.len = sizeof(dupreq_key_t); 00703 if(HashTable_Get(ht_dupreq, &buffkey, &buffval) == HASHTABLE_SUCCESS) 00704 { 00705 dupreq_entry_t *pdupreq = (dupreq_entry_t *)buffval.pdata; 00706 /* reset timestamp */ 00707 pdupreq->timestamp = time(NULL); 00708 00709 *pstatus = DUPREQ_SUCCESS; 00710 res_nfs = pdupreq->res_nfs; 00711 LogDupReq(" dupreq_get: Hit in the dupreq cache for", &pdupreq->addr, 00712 pdupreq->xid, pdupreq->rq_prog); 00713 } 00714 else 00715 { 00716 LogDupReq("Failed to get dupreq entry", &dupkey.addr, dupkey.xid, req->rq_prog); 00717 *pstatus = DUPREQ_NOT_FOUND; 00718 } 00719 return res_nfs; 00720 } /* nfs_dupreq_get */ 00721 00736 int nfs_dupreq_gc_function(LRU_entry_t * pentry, void *addparam) 00737 { 00738 dupreq_entry_t *pdupreq = NULL; 00739 00740 pdupreq = (dupreq_entry_t *) (pentry->buffdata.pdata); 00741 00742 /* Test if entry is expired */ 00743 if(time(NULL) - pdupreq->timestamp > nfs_param.core_param.expiration_dupreq) 00744 return LRU_LIST_SET_INVALID; 00745 00746 return LRU_LIST_DO_NOT_SET_INVALID; 00747 } /* nfs_dupreq_fc_function */ 00748 00762 void nfs_dupreq_get_stats(hash_stat_t * phstat_udp, hash_stat_t * phstat_tcp ) 00763 { 00764 HashTable_GetStats(ht_dupreq_udp, phstat_udp); 00765 HashTable_GetStats(ht_dupreq_tcp, phstat_tcp); 00766 } /* nfs_dupreq_get_stats */