opt
/
kaspersky
/
kav4fs
/
src
/
kernel
➕ New
📤 Upload
✎ Editing:
cache.c
← Back
/* * This source file is a part of a Kaspersky Antivirus Monitor. * Copyright (C) Kaspersky Lab, 1997-2010 * See License.txt for details * */ #include "module.h" struct cache_entry { struct list_head lru_list; unsigned int lru_index; file_info file; }; static lock_declare(cache_lock); static struct cache_entry** hash_tbl; static struct cache_entry* cache_entries; static int hash_tbl_sz_mask = 0; static int max_cache_files = -1; static KLIST_HEAD(lru_list); #define HASH_SCALE 4 #define HASH_FIND_DEPTH 5 static void Monitor_cache_stop_nolock(void); void Monitor_cache_init(void) { lock_init(&cache_lock, "kavmonitor cache"); } void Monitor_cache_finit(void) { Monitor_cache_stop(); lock_finit(&cache_lock); } static void* insistent_alloc(size_t size, int max_retries) { int retry = 0; do { void* ptr = MEM_ALLOC(size); if (ptr) return ptr; } while (!max_retries || (retry++ < max_retries)); return NULL; } void Monitor_cache_start(int size) { int i, sz2 = size; int hash_tbl_sz = 0; struct cache_entry** l_hash_tbl = NULL; struct cache_entry* l_cache_entries = NULL; // round max_cache_files to power of 2 if ((sz2 - 1) & sz2) { while (1) { int tmp = (sz2 - 1) & sz2; if (!tmp) break; sz2 = tmp; } sz2 <<= 1; } hash_tbl_sz = sz2 * HASH_SCALE; l_hash_tbl = (struct cache_entry**)insistent_alloc( sizeof(struct cache_entry*) * hash_tbl_sz, 256); if (!l_hash_tbl) { PRN_ERR("klflt: files cache memory allocation error, cache disabled.\n"); return; } memset(l_hash_tbl, 0, sizeof(struct cache_entry*) * hash_tbl_sz); l_cache_entries = (struct cache_entry*)insistent_alloc(sizeof(struct cache_entry) * sz2, 256); if (!l_cache_entries) { PRN_ERR("klflt: files cache entries allocation error, cache disabled.\n"); MEM_FREE(l_hash_tbl); return; } memset(l_cache_entries, 0, sizeof(struct cache_entry) * sz2); write_lock(&cache_lock); if (max_cache_files != -1) Monitor_cache_stop_nolock(); hash_tbl = l_hash_tbl; cache_entries = l_cache_entries; /* place all free etries to lru list */ KINIT_LIST_HEAD(&lru_list); for (i = 0; i < sz2; ++i) list_add(&cache_entries[i].lru_list, &lru_list); max_cache_files = sz2; hash_tbl_sz_mask = hash_tbl_sz - 1; write_unlock(&cache_lock); return; } static void Monitor_cache_stop_nolock(void) { if (max_cache_files == -1) return; max_cache_files = -1; MEM_FREE(cache_entries); cache_entries = NULL; MEM_FREE(hash_tbl); hash_tbl = NULL; hash_tbl_sz_mask = 0; } void Monitor_cache_stop(void) { write_lock(&cache_lock); Monitor_cache_stop_nolock(); write_unlock(&cache_lock); } static int hash_func(const file_info* file) { int tmp = file->dev + file->ino; tmp ^= tmp << 7; tmp ^= tmp >> 5; return (tmp & hash_tbl_sz_mask); } /* Requirement: cache_lock locked */ static void move_to_lru_list_tail(struct cache_entry* cent) { cent->lru_index = list_entry(lru_list.prev, struct cache_entry, lru_list)->lru_index + 1; list_del(¢->lru_list); list_add_tail(¢->lru_list, &lru_list); } /* Requirement: cache_lock locked */ static int hash_find_index_to_replace(const file_info* file) { int hind = hash_func(file), i = 0, min_lru_hind, hind_val; unsigned int head_lrui, min_lrui = 0; if (!hash_tbl[hind]) goto l_empty; if (FILE_EQUAL(&hash_tbl[hind]->file, file)) goto l_value_exist; head_lrui = list_entry(lru_list.next, struct cache_entry, lru_list)->lru_index; min_lru_hind = hind; min_lrui = hash_tbl[hind]->lru_index - head_lrui; for (++i; i < HASH_FIND_DEPTH; ++i) { int lrui; ++hind; hind &= hash_tbl_sz_mask; if (!hash_tbl[hind]) goto l_empty; if (FILE_EQUAL(&hash_tbl[hind]->file, file)) goto l_value_exist; lrui = hash_tbl[hind]->lru_index; lrui -= head_lrui; if (lrui < min_lrui) { min_lrui = lrui; min_lru_hind = hind; } } return min_lru_hind; l_empty: for (++i, hind_val = hind; i < HASH_FIND_DEPTH; ++i) { ++hind_val; hind_val &= hash_tbl_sz_mask; if (hash_tbl[hind_val] && FILE_EQUAL(&hash_tbl[hind_val]->file, file)) { /* move the value closer to its hash index */ hash_tbl[hind] = hash_tbl[hind_val]; hash_tbl[hind_val] = NULL; return -1; } } return hind; l_value_exist: move_to_lru_list_tail(hash_tbl[hind]); return -1; } /* Requirement: cache_lock locked */ static int hash_find_index(const file_info* file) { int hind, iend; for (hind = hash_func(file), iend = hind + HASH_FIND_DEPTH; hind < iend; ++hind) { int hind_m = hind & hash_tbl_sz_mask; if (hash_tbl[hind_m] && FILE_EQUAL(&hash_tbl[hind_m]->file, file)) return hind_m; } return -1; } void Monitor_cache_add(const file_info* file) { int hind; struct cache_entry* cent; write_lock(&cache_lock); if (max_cache_files <= 0) { write_unlock(&cache_lock); return; } hind = hash_find_index_to_replace(file); if (-1 == hind) { write_unlock(&cache_lock); return; } /* value is already in cache */ if (hash_tbl[hind]) cent = hash_tbl[hind]; else { cent = list_entry(lru_list.next, struct cache_entry, lru_list); if (cent->lru_index != list_entry(lru_list.next->next, struct cache_entry, lru_list)->lru_index) { /* the cache entry can be in hash table */ int cent_hind = hash_find_index(¢->file); if (-1 != cent_hind) hash_tbl[cent_hind] = NULL; } hash_tbl[hind] = cent; } cent->file = *file; move_to_lru_list_tail(cent); write_unlock(&cache_lock); } void Monitor_cache_del(dev_t dev, unsigned long ino) { file_info file; int hind; /* #ifdef __linux__ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) touch_softlockup_watchdog(); #endif #endif */ write_lock(&cache_lock); if (max_cache_files <= 0) { write_unlock(&cache_lock); return; } file.dev = dev; file.ino = ino; hind = hash_find_index(&file); if (-1 == hind) { write_unlock(&cache_lock); return; } hash_tbl[hind]->lru_index = list_entry(lru_list.next, struct cache_entry, lru_list)->lru_index; list_del(&hash_tbl[hind]->lru_list); list_add(&hash_tbl[hind]->lru_list, &lru_list); hash_tbl[hind] = NULL; write_unlock(&cache_lock); } const file_info* Monitor_cached(dev_t dev, unsigned long ino) { file_info file; int hind; struct cache_entry* cent; write_lock(&cache_lock); if (max_cache_files <= 0) { write_unlock(&cache_lock); return NULL; } file.dev = dev; file.ino = ino; hind = hash_find_index(&file); if (-1 == hind) { write_unlock(&cache_lock); return NULL; } cent = hash_tbl[hind]; move_to_lru_list_tail(cent); write_unlock(&cache_lock); return ¢->file; } void Monitor_cache_clear(void) { int i; write_lock(&cache_lock); if (max_cache_files <= 0) { write_unlock(&cache_lock); return; } for (i = 0; i < hash_tbl_sz_mask + 1; ++i) { if (hash_tbl[i]) { hash_tbl[i]->lru_index = 0; hash_tbl[i] = NULL; } } write_unlock(&cache_lock); }
💾 Save Changes
Cancel
📤 Upload File
×
Select File
Upload
Cancel
➕ Create New
×
Type
📄 File
📁 Folder
Name
Create
Cancel
✎ Rename Item
×
Current Name
New Name
Rename
Cancel
🔐 Change Permissions
×
Target File
Permission (e.g., 0755, 0644)
0755
0644
0777
Apply
Cancel