/** * * clean_entry_dupreq: cleans an entry in the dupreq cache. * * cleans an entry in the dupreq cache. * * @param pentry [INOUT] entry to be cleaned. * @param addparam [IN] additional parameter used for cleaning. * * @return 0 if ok, other values mean an error. * */ int clean_entry_dupreq(LRU_entry_t * pentry, void *addparam) { hash_buffer_t buffkey; struct prealloc_pool *dupreq_pool = (struct prealloc_pool *) addparam; dupreq_entry_t *pdupreq = (dupreq_entry_t *) (pentry->buffdata.pdata); dupreq_key_t dupkey; hash_table_t * ht_dupreq = NULL ; /* Get the socket address for the key */ memcpy((char *)&dupkey.addr, (char *)&pdupreq->addr, sizeof(dupkey.addr)); dupkey.xid = pdupreq->xid; dupkey.checksum = pdupreq->checksum; /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, * this also means that buffkey->len will be 0 */ buffkey.pdata = (caddr_t) &dupkey; buffkey.len = sizeof(dupreq_key_t); /* Get correct HT depending on proto used */ if( pdupreq->ipproto == IPPROTO_TCP ) ht_dupreq = ht_dupreq_tcp ; else ht_dupreq = ht_dupreq_udp ; LogDupReq("Garbage collection on", &pdupreq->addr, pdupreq->xid, pdupreq->rq_prog); return _remove_dupreq(ht_dupreq, &buffkey, pdupreq, dupreq_pool, NFS_REQ_OK); } /* clean_entry_dupreq */
/** * * nfs_dupreq_get: Tries to get a duplicated requests for dupreq cache * * Tries to get a duplicated requests for dupreq cache. * * @param xid [IN] the transfer id we are looking for * @param pstatus [OUT] the pointer to the status for the operation * * @return the result previously set if *pstatus == DUPREQ_SUCCESS * */ nfs_res_t nfs_dupreq_get(long xid, struct svc_req *ptr_req, SVCXPRT *xprt, int *pstatus) { hash_buffer_t buffkey; hash_buffer_t buffval; nfs_res_t res_nfs; dupreq_key_t dupkey; hash_table_t * ht_dupreq = NULL ; /* Get correct HT depending on proto used */ ht_dupreq = get_ht_by_xprt( xprt ) ; memset(&res_nfs, 0, sizeof(res_nfs)); /* Get the socket address for the key */ if(copy_xprt_addr(&dupkey.addr, xprt) == 0) { *pstatus = DUPREQ_NOT_FOUND; return res_nfs; } dupkey.xid = xid; dupkey.checksum = 0; /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, * this also means that buffkey->len will be 0 */ buffkey.pdata = (caddr_t) &dupkey; buffkey.len = sizeof(dupreq_key_t); if(HashTable_Get(ht_dupreq, &buffkey, &buffval) == HASHTABLE_SUCCESS) { dupreq_entry_t *pdupreq = (dupreq_entry_t *)buffval.pdata; /* reset timestamp */ pdupreq->timestamp = time(NULL); *pstatus = DUPREQ_SUCCESS; res_nfs = pdupreq->res_nfs; LogDupReq(" dupreq_get: Hit in the dupreq cache for", &pdupreq->addr, pdupreq->xid, pdupreq->rq_prog); } else { LogDupReq("Failed to get dupreq entry", &dupkey.addr, dupkey.xid, ptr_req->rq_prog); *pstatus = DUPREQ_NOT_FOUND; } return res_nfs; } /* nfs_dupreq_get */
int nfs_dupreq_finish(long xid, struct svc_req *ptr_req, SVCXPRT *xprt, nfs_res_t * p_res_nfs, LRU_list_t * lru_dupreq) { hash_buffer_t buffkey; hash_buffer_t buffval; LRU_entry_t *pentry = NULL; LRU_status_t lru_status; dupreq_key_t dupkey; dupreq_entry_t *pdupreq; hash_table_t * ht_dupreq = NULL ; /* Get correct HT depending on proto used */ ht_dupreq = get_ht_by_xprt( xprt ) ; /* Get the socket address for the key */ if(copy_xprt_addr(&dupkey.addr, xprt) == 0) return DUPREQ_NOT_FOUND; dupkey.xid = xid; dupkey.checksum = 0; /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, * this also means that buffkey->len will be 0 */ buffkey.pdata = (caddr_t) &dupkey; buffkey.len = sizeof(dupreq_key_t); if(HashTable_Get(ht_dupreq, &buffkey, &buffval) != HASHTABLE_SUCCESS) return DUPREQ_NOT_FOUND; pdupreq = (dupreq_entry_t *)buffval.pdata; LogDupReq("Finish", &pdupreq->addr, pdupreq->xid, pdupreq->rq_prog); P(pdupreq->dupreq_mutex); pdupreq->res_nfs = *p_res_nfs; pdupreq->timestamp = time(NULL); pdupreq->processing = 0; V(pdupreq->dupreq_mutex); /* Add it to lru list */ if((pentry = LRU_new_entry(lru_dupreq, &lru_status)) == NULL) return DUPREQ_INSERT_MALLOC_ERROR; pentry->buffdata.pdata = buffval.pdata; pentry->buffdata.len = buffval.len; return DUPREQ_SUCCESS; } /* nfs_dupreq_finish */
int nfs_dupreq_delete(long xid, struct svc_req *ptr_req, SVCXPRT *xprt, struct prealloc_pool *dupreq_pool) { int status; hash_buffer_t buffkey; hash_buffer_t buffval; dupreq_key_t dupkey; dupreq_entry_t *pdupreq; hash_table_t * ht_dupreq = NULL ; /* Get correct HT depending on proto used */ ht_dupreq = get_ht_by_xprt( xprt ) ; /* Get the socket address for the key */ if(copy_xprt_addr(&dupkey.addr, xprt) == 0) return DUPREQ_NOT_FOUND; dupkey.xid = xid; dupkey.checksum = 0; /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, * this also means that buffkey->len will be 0 */ buffkey.pdata = (caddr_t) &dupkey; buffkey.len = sizeof(dupreq_key_t); if(HashTable_Get(ht_dupreq, &buffkey, &buffval) == HASHTABLE_SUCCESS) { pdupreq = (dupreq_entry_t *) buffval.pdata; /* reset timestamp */ pdupreq->timestamp = time(NULL); status = DUPREQ_SUCCESS; } else { return DUPREQ_NOT_FOUND; } LogDupReq("REMOVING", &pdupreq->addr, pdupreq->xid, pdupreq->rq_prog); status = _remove_dupreq( ht_dupreq, &buffkey, pdupreq, dupreq_pool, ! NFS_REQ_OK); return status; }
int nfs_dupreq_add_not_finished(long xid, struct svc_req *ptr_req, SVCXPRT *xprt, struct prealloc_pool *dupreq_pool, nfs_res_t *res_nfs) { hash_buffer_t buffkey; hash_buffer_t buffval; hash_buffer_t buffdata; dupreq_entry_t *pdupreq = NULL; int status = 0; dupreq_key_t *pdupkey = NULL; /* Entry to be cached */ GetFromPool(pdupreq, dupreq_pool, dupreq_entry_t); if(pdupreq == NULL) return DUPREQ_INSERT_MALLOC_ERROR; if((pdupkey = (dupreq_key_t *) Mem_Alloc(sizeof(dupreq_key_t))) == NULL) { ReleaseToPool(pdupreq, dupreq_pool); return DUPREQ_INSERT_MALLOC_ERROR; } /* Get the socket address for the key and the request */ if(copy_xprt_addr(&pdupkey->addr, xprt) == 0 || copy_xprt_addr(&pdupreq->addr, xprt) == 0) { Mem_Free(pdupkey); ReleaseToPool(pdupreq, dupreq_pool); return DUPREQ_INSERT_MALLOC_ERROR; } pdupkey->xid = xid; pdupreq->xid = xid; /* Checksum the request */ pdupkey->checksum = 0; pdupreq->checksum = 0; /* I have to keep an integer as key, I wil use the pointer buffkey->pdata for this, * this also means that buffkey->len will be 0 */ buffkey.pdata = (caddr_t) pdupkey; buffkey.len = sizeof(dupreq_key_t); /* I build the data with the request pointer that should be in state 'IN USE' */ pdupreq->rq_prog = ptr_req->rq_prog; pdupreq->rq_vers = ptr_req->rq_vers; pdupreq->rq_proc = ptr_req->rq_proc; pdupreq->timestamp = time(NULL); pdupreq->processing = 1; buffdata.pdata = (caddr_t) pdupreq; buffdata.len = sizeof(dupreq_entry_t); LogDupReq("Add Not Finished", &pdupreq->addr, pdupreq->xid, pdupreq->rq_prog); status = HashTable_Test_And_Set(ht_dupreq, &buffkey, &buffdata, HASHTABLE_SET_HOW_SET_NO_OVERWRITE); if (status == HASHTABLE_ERROR_KEY_ALREADY_EXISTS) { if(HashTable_Get(ht_dupreq, &buffkey, &buffval) == HASHTABLE_SUCCESS) { P(((dupreq_entry_t *)buffval.pdata)->dupreq_mutex); if ( ((dupreq_entry_t *)buffval.pdata)->processing == 1) { V(((dupreq_entry_t *)buffval.pdata)->dupreq_mutex); status = DUPREQ_BEING_PROCESSED; } else { *res_nfs = ((dupreq_entry_t *) buffval.pdata)->res_nfs; V(((dupreq_entry_t *)buffval.pdata)->dupreq_mutex); status = DUPREQ_ALREADY_EXISTS; } } else status = DUPREQ_NOT_FOUND; } else if (status == HASHTABLE_INSERT_MALLOC_ERROR) status = DUPREQ_INSERT_MALLOC_ERROR; else status = DUPREQ_SUCCESS; if (status != DUPREQ_SUCCESS) ReleaseToPool(pdupreq, dupreq_pool); return status; } /* nfs_dupreq_add_not_finished */