diff options
Diffstat (limited to 'lufis/dircache.c')
-rw-r--r-- | lufis/dircache.c | 478 |
1 files changed, 0 insertions, 478 deletions
diff --git a/lufis/dircache.c b/lufis/dircache.c deleted file mode 100644 index bdd8717..0000000 --- a/lufis/dircache.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * dircache.c - * Copyright (C) 2002 Florin Malita <mali@go.ro> - * - * This file is part of LUFS, a free userspace filesystem implementation. - * See http://lufs.sourceforge.net/ for updates. - * - * LUFS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * LUFS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <pthread.h> - -#include <sys/stat.h> - -#include <lufs/proto.h> -#include <lufs/fs.h> - -#include "list.h" -#include "dircache.h" - -static char root_dir[]="/"; -static char current_dir[]="."; - -static unsigned long -hash(char *name){ - unsigned long res = 0; - unsigned int i; - - for(i = 0; i < strlen(name); i++) - if(name[i] != '/') - res = 0x21413 * (res + name[i]); - - return res % NBUCKETS; -} - -static void -delete_dir(struct directory *d){ - struct list_head *p, *tmp; - struct direntry *de; - - TRACE("in"); - list_for_each_safe(p, tmp, &d->d_entries){ - de = list_entry(p, struct direntry, e_list); - list_del(&de->e_list); - free(de->e_name); - if(de->e_link) - free(de->e_link); - free(de); - } - - list_del(&d->d_list); - free(d->d_name); - free(d); - - TRACE("out"); -} - -struct dir_cache* -lu_cache_create(struct list_head *cfg){ - struct dir_cache *cache; - int i; - const char *c; - - TRACE("creating dir cache..."); - - if(!(cache = malloc(sizeof(struct dir_cache)))) - return NULL; - - memset(cache, 0, sizeof(struct dir_cache)); - - for(i = 0; i < NBUCKETS; i++) - INIT_LIST_HEAD(&cache->buckets[i]); - - pthread_mutex_init(&cache->lock, NULL); - - cache->ttl = DEF_TTL; - if((c = lu_opt_getchar(cfg, "LUFSD", "DirCacheTTL")) && atoi(c)) - cache->ttl = atoi(c); - if((c = lu_opt_getchar(cfg, "MOUNT", "dir_cache_ttl")) && atoi(c)) - cache->ttl = atoi(c); - - cache->entries = DEF_NENTRIES; - if((c = lu_opt_getchar(cfg, "LUFSD", "DirCacheEntries")) && atoi(c)) - cache->entries = atoi(c); - if((c = lu_opt_getchar(cfg, "MOUNT", "dir_cache_entries")) && atoi(c)) - cache->entries = atoi(c); - - TRACE("entries: %d, ttl: %d", cache->entries, cache->ttl); - - return cache; -} - -void -lu_cache_destroy(struct dir_cache *cache){ - struct list_head *p, *tmp; - int i; - - for(i = 0; i < NBUCKETS; i++){ - list_for_each_safe(p, tmp, &cache->buckets[i]){ - delete_dir(list_entry(p, struct directory, d_list)); - } - } - - free(cache); -} - -static struct directory* -search(struct dir_cache *cache, char *dir){ - struct list_head *p, *tmp; - struct directory *d; - int hsh; - - hsh = hash(dir); - - TRACE("search %s in bucket %u, size=%u", dir, hsh, cache->lengths[hsh]); - - list_for_each_safe(p, tmp, &cache->buckets[hsh]){ - d = list_entry(p, struct directory, d_list); - - if(time(NULL) - d->d_stamp >= (unsigned long) cache->ttl){ - TRACE("%s expired...", d->d_name); - delete_dir(d); - cache->lengths[hsh]--; - TRACE("directory deleted"); - }else if(!strcmp(dir, d->d_name)){ - TRACE("%s found", dir); - d->d_stamp = time(NULL); - return d; - } - } - - TRACE("dir not found"); - return NULL; -} - -int -lu_cache_lookup(struct dir_cache *cache, char *dir, char *file, struct lufs_fattr *fattr, char *link, int buflen){ - struct directory *d; - struct direntry *de; - struct list_head *p; - int res = -1; - - TRACE("looking up %s in dir %s", file, dir); - - pthread_mutex_lock(&cache->lock); - - if(!(d = search(cache, dir))) - goto out; - - list_for_each(p, &d->d_entries){ - de = list_entry(p, struct direntry, e_list); - if(!strcmp(file, de->e_name)){ - TRACE("file found"); - - memcpy(fattr, &de->e_attr, sizeof(struct lufs_fattr)); - if(link){ - if(de->e_link){ - if(snprintf(link, buflen, "%s", de->e_link) >= buflen){ - WARN("link too long!"); - link[buflen - 1] =0; - } - }else{ - link[0] = 0; - } - } - - res = 0; - goto out; - } - } - - TRACE("file not found!"); - - out: - pthread_mutex_unlock(&cache->lock); - return res; -} - -static void -shrink(struct dir_cache *cache, int hsh){ - struct directory *dir; - - TRACE("shrinking bucket %u, len=%u", hsh, cache->lengths[hsh]); - - if(list_empty(&cache->buckets[hsh])) - return; - - dir = list_entry(cache->buckets[hsh].prev, struct directory, d_list); - - TRACE("deleting dir %s", dir->d_name); - - delete_dir(dir); - cache->lengths[hsh]--; -} - -static void -check_dir(struct directory *d){ - struct list_head *p, *tmp; - struct direntry *e; - struct lufs_fattr dummy; - int dot = 0, dotdot = 0; - - memset(&dummy, 0, sizeof(struct lufs_fattr)); - dummy.f_nlink = 1; - dummy.f_uid = dummy.f_gid = 1; - dummy.f_mode = S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP; - dummy.f_mtime = dummy.f_atime = dummy.f_ctime = time(NULL); - dummy.f_size = 512; - - do{ - list_for_each_safe(p, tmp, &d->d_entries){ - e = list_entry(p, struct direntry, e_list); - - if(!strcmp(e->e_name, ".")){ - TRACE("'.' entry found"); - list_del(&e->e_list); - list_add(&e->e_list, &d->d_entries); - dot = 1; - continue; - } - - if(!strcmp(e->e_name, "..")){ - TRACE("'..' entry found"); - list_del(&e->e_list); - if(!dot) - list_add(&e->e_list, &d->d_entries); - else - list_add(&e->e_list, d->d_entries.next); - - dotdot = 1; - } - } - - if(!dot) - lu_cache_add2dir(d, ".", NULL, &dummy); - - if(!dotdot) - lu_cache_add2dir(d, "..", NULL, &dummy); - - }while((!dot) || (!dotdot)); - -} - -void -lu_cache_add_dir(struct dir_cache *cache, struct directory *d){ - struct directory *dir; - int hsh; - - hsh = hash(d->d_name); - - TRACE("adding dir %s to bucket %i", d->d_name, hsh); - - check_dir(d); - - pthread_mutex_lock(&cache->lock); - - if((dir = search(cache, d->d_name))){ - TRACE("directory already in cache, deleting..."); - delete_dir(dir); - cache->lengths[hsh]--; - } - - d->d_stamp = time(NULL); - - list_add(&d->d_list, &cache->buckets[hsh]); - cache->lengths[hsh]++; - - while(cache->lengths[hsh] > cache->entries) - shrink(cache, hsh); - - pthread_mutex_unlock(&cache->lock); - - TRACE("out"); -} - -int lu_cache_readdir(struct dir_cache *cache, char *dir, - fuse_dirh_t h, fuse_dirfil_t filler) -{ - struct directory *d; - struct direntry *de; - struct list_head *p; - int res = -1; - - TRACE("reading directory %s", dir); - - pthread_mutex_lock(&cache->lock); - - if(!(d = search(cache, dir))) - goto out; - - list_for_each(p, &d->d_entries){ - de = list_entry(p, struct direntry, e_list); -#if FUSE_MAJOR_VERSION < 2 || (FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION < 1) - filler(h, de->e_name, 0); -#else - filler(h, de->e_name, 0, 0); -#endif - } - - d->d_stamp = time(NULL); - - res = 0; - - out: - pthread_mutex_unlock(&cache->lock); - TRACE("out"); - return res; -} - -int -lu_cache_lookup_file(struct dir_cache *cache, char *file, struct lufs_fattr *fattr, char *link, int buflen){ - int res; - - char *sep, *dir; - - if(!(sep = strrchr(file, '/'))){ - WARN("separator not present!"); - return -1; - } - - *sep = 0; - - if(sep == file) - dir = root_dir; - else - dir = file; - - if(*(sep+1)) - file = sep + 1; - else - file = current_dir; - - TRACE("dir: %s, file: %s", dir, file); - - res = lu_cache_lookup(cache, dir, file, fattr, link, buflen); - *sep = '/'; - - return res; -} - -int -lu_cache_invalidate(struct dir_cache *cache, char *file){ - struct directory *d; - char *sep, *dir; - - if(!(sep = strrchr(file, '/'))){ - WARN("separator not present!"); - return -1; - } - - *sep = 0; - - if(sep == file) - dir = root_dir; - else - dir = file; - - TRACE("invalidating dir %s", dir); - - pthread_mutex_lock(&cache->lock); - - if(!(d = search(cache, dir))){ - *sep = '/'; - pthread_mutex_unlock(&cache->lock); - return -1; - } - - d->d_stamp = 0; - - pthread_mutex_unlock(&cache->lock); - *sep = '/'; - - return 0; -} - -struct directory* -lu_cache_mkdir(char *dir){ - struct directory *res; - - TRACE("create dir %s", dir); - - if(!(res = malloc(sizeof(struct directory)))){ - WARN("out of mem!"); - return NULL; - } - - memset(res, 0, sizeof(struct directory)); - - if(!(res->d_name = malloc(strlen(dir) + 1))){ - WARN("out of mem!"); - free(res); - return NULL; - } - - INIT_LIST_HEAD(&res->d_entries); - res->d_stamp = time(NULL); - strcpy(res->d_name, dir); - - return res; -} - -int -lu_cache_add2dir(struct directory *d, char *fname, char *link, struct lufs_fattr *fattr){ - struct direntry *de; - - TRACE("adding %s->%s to %s", fname, link, d->d_name); - - if(!(de = malloc(sizeof(struct direntry)))) - goto fail; - - - if(!(de->e_name = malloc(strlen(fname) + 1))) - goto fail_de; - - - if(link) - de->e_link = malloc(strlen(link) + 1); - else - de->e_link = malloc(2); - - if(!de->e_link) - goto fail_ename; - - memcpy(&de->e_attr, fattr, sizeof(struct lufs_fattr)); - strcpy(de->e_name, fname); - if(link) - strcpy(de->e_link, link); - else - strcpy(de->e_link, ""); - - list_add_tail(&de->e_list, &d->d_entries); - - return 0; - - fail_ename: - free(de->e_name); - fail_de: - free(de); - fail: - WARN("out of mem!"); - return -1; -} - -void -lu_cache_killdir(struct directory *d){ - struct list_head *p, *tmp; - struct direntry *de; - - TRACE("in"); - - list_for_each_safe(p, tmp, &d->d_entries){ - de = list_entry(p, struct direntry, e_list); - list_del(&de->e_list); - free(de->e_name); - if(de->e_link) - free(de->e_link); - free(de); - } - - free(d->d_name); - free(d); - -} |