/* * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. */ #include #include #include #include #include "include/defex_caches.h" static struct defex_file_cache_list file_cache; DEFINE_SPINLOCK(defex_caches_lock); void defex_file_cache_init(void) { int i; struct defex_file_cache_entry *current_entry; unsigned long flags; spin_lock_irqsave(&defex_caches_lock, flags); for (i = 0; i < FILE_CACHE_SIZE; i++) { current_entry = &file_cache.entry[i]; current_entry->next_entry = i + 1; current_entry->prev_entry = i - 1; current_entry->pid = -1; current_entry->file_addr = NULL; } file_cache.first_entry = 0; file_cache.last_entry = FILE_CACHE_SIZE - 1; file_cache.entry[file_cache.first_entry].prev_entry = file_cache.last_entry; file_cache.entry[file_cache.last_entry].next_entry = file_cache.first_entry; spin_unlock_irqrestore(&defex_caches_lock, flags); } void defex_file_cache_add(int pid, struct file *file_addr) { struct defex_file_cache_entry *current_entry; struct file *old_file_addr; unsigned long flags; spin_lock_irqsave(&defex_caches_lock, flags); current_entry = &file_cache.entry[file_cache.last_entry]; current_entry->pid = pid; old_file_addr = current_entry->file_addr; current_entry->file_addr = file_addr; current_entry->next_entry = file_cache.first_entry; file_cache.first_entry = file_cache.last_entry; file_cache.last_entry = current_entry->prev_entry; spin_unlock_irqrestore(&defex_caches_lock, flags); if (old_file_addr) { fput(old_file_addr); } } void defex_file_cache_update(struct file *file_addr) { struct defex_file_cache_entry *current_entry; struct file *old_file_addr; unsigned long flags; spin_lock_irqsave(&defex_caches_lock, flags); current_entry = &file_cache.entry[file_cache.first_entry]; old_file_addr = current_entry->file_addr; current_entry->file_addr = file_addr; spin_unlock_irqrestore(&defex_caches_lock, flags); if (old_file_addr) fput(old_file_addr); } void defex_file_cache_delete(int pid) { int current_index, cache_found = 0; struct defex_file_cache_entry *current_entry; struct file *old_file_addr = NULL; unsigned long flags; spin_lock_irqsave(&defex_caches_lock, flags); current_index = file_cache.first_entry; do { current_entry = &file_cache.entry[current_index]; if (current_entry->pid == pid) { if (current_index == file_cache.first_entry) { file_cache.first_entry = current_entry->next_entry; file_cache.last_entry = current_index; cache_found = 1; break; } if (current_index == file_cache.last_entry) { cache_found = 1; break; } file_cache.entry[current_entry->prev_entry].next_entry = current_entry->next_entry; file_cache.entry[current_entry->next_entry].prev_entry = current_entry->prev_entry; file_cache.entry[file_cache.first_entry].prev_entry = current_index; file_cache.entry[file_cache.last_entry].next_entry = current_index; current_entry->next_entry = file_cache.first_entry; current_entry->prev_entry = file_cache.last_entry; file_cache.last_entry = current_index; cache_found = 1; break; } current_index = current_entry->next_entry; } while (current_index != file_cache.first_entry); if (cache_found) { old_file_addr = current_entry->file_addr; current_entry->pid = -1; current_entry->file_addr = NULL; } spin_unlock_irqrestore(&defex_caches_lock, flags); if (old_file_addr) fput(old_file_addr); return; } struct file *defex_file_cache_find(int pid) { int current_index, cache_found = 0; struct defex_file_cache_entry *current_entry; unsigned long flags; spin_lock_irqsave(&defex_caches_lock, flags); current_index = file_cache.first_entry; do { current_entry = &file_cache.entry[current_index]; if (current_entry->pid == pid) { if (current_index == file_cache.first_entry) { cache_found = 1; break; } if (current_index == file_cache.last_entry) { current_entry->next_entry = file_cache.first_entry; file_cache.first_entry = file_cache.last_entry; file_cache.last_entry = current_entry->prev_entry; cache_found = 1; break; } file_cache.entry[current_entry->prev_entry].next_entry = current_entry->next_entry; file_cache.entry[current_entry->next_entry].prev_entry = current_entry->prev_entry; file_cache.entry[file_cache.first_entry].prev_entry = current_index; file_cache.entry[file_cache.last_entry].next_entry = current_index; current_entry->next_entry = file_cache.first_entry; current_entry->prev_entry = file_cache.last_entry; file_cache.first_entry = current_index; cache_found = 1; break; } current_index = current_entry->next_entry; } while (current_index != file_cache.first_entry); spin_unlock_irqrestore(&defex_caches_lock, flags); return (!cache_found)?NULL:current_entry->file_addr; }