You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.0 KiB
177 lines
5.0 KiB
/*
|
|
* 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 <linux/file.h>
|
|
#include <linux/types.h>
|
|
#include <linux/unistd.h>
|
|
#include <linux/spinlock.h>
|
|
#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;
|
|
}
|
|
|