diff options
author | Stefan Siegl <stesie@brokenpipe.de> | 2006-01-30 22:37:59 +0000 |
---|---|---|
committer | Stefan Siegl <stesie@brokenpipe.de> | 2006-01-30 22:37:59 +0000 |
commit | ad506a98d82194fd632409b687a0d7fd61a1eb4c (patch) | |
tree | 2eba0f18e696113b9a6667942bfd9bbbb13b5a5d /src/netnode.c | |
parent | a88f3f1d9f48e360d03baef9f7c14e4f6e311f10 (diff) |
moved headers into new include/ directory, sources moved into new src/ directory.
Diffstat (limited to 'src/netnode.c')
-rw-r--r-- | src/netnode.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/netnode.c b/src/netnode.c new file mode 100644 index 000000000..9727097c1 --- /dev/null +++ b/src/netnode.c @@ -0,0 +1,175 @@ +/********************************************************** + * netnode.c + * + * Copyright(C) 2004, 2005 by Stefan Siegl <ssiegl@gmx.de>, Germany + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Publice License, + * version 2 or any later. The license is contained in the COPYING + * file that comes with the libfuse distribution. + * + * netnode handling + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <error.h> +#include <string.h> +#include <rwlock.h> +#include <hurd/netfs.h> + +#include "fuse_i.h" +#include "fuse.h" + +#define HASH_BUCKETS 256 + +struct hash_element; +static struct hash_element { + struct netnode *nn; + struct hash_element *next; /* singly linked list */ +} fuse_netnodes[HASH_BUCKETS] = {{ 0 }}; + +/* rwlock needs to be held when touching either fuse_netnodes hash or + * fuse_next_inode variable + */ +struct rwlock fuse_netnodes_lock = RWLOCK_INITIALIZER; + +/* next inode number that will be assigned + * (fuse_netnodes_lock must be write locked, when touching this) + */ +ino_t fuse_next_inode = 1; + + + +static int +fuse_netnode_hash_value(const char *path) +{ + int hash = 0; + int maxlen = 12; /* use the first 12 chars for hash generation only */ + + while(maxlen -- && *path) + hash += *(path ++); + + return hash % HASH_BUCKETS; +} + + + +struct netnode * +fuse_make_netnode(struct netnode *parent, const char *path) +{ + struct hash_element *hash_el; + struct netnode *nn; + int hash_value = fuse_netnode_hash_value(path); + + DEBUG("netnodes_lock", "aquiring rwlock_reader_lock for %s.\n", path); + rwlock_reader_lock(&fuse_netnodes_lock); + + hash_el = &fuse_netnodes[hash_value]; + if(hash_el->nn) + do + if(! strcmp(hash_el->nn->path, path)) + { + nn = hash_el->nn; + rwlock_reader_unlock(&fuse_netnodes_lock); + DEBUG("netnodes_lock", "releasing rwlock_reader_lock.\n"); + + return nn; + } + while((hash_el = hash_el->next)); + + rwlock_reader_unlock(&fuse_netnodes_lock); + DEBUG("netnodes_lock", "releasing rwlock_reader_lock.\n"); + + nn = malloc(sizeof(*nn)); + if(! nn) + return NULL; /* unfortunately we cannot serve a netnode .... */ + + nn->path = strdup(path); + nn->parent = parent; + nn->node = NULL; + mutex_init(&nn->lock); + + DEBUG("netnodes_lock", "aquiring rwlock_writer_lock for %s.\n", path); + rwlock_writer_lock(&fuse_netnodes_lock); + + nn->inode = fuse_next_inode ++; + + /* unable to find hash element, need to generate a new one */ + if(! hash_el) + hash_el = &fuse_netnodes[hash_value]; + + if(hash_el->nn) + { + struct hash_element *new = malloc(sizeof(*new)); + + if(! new) { + rwlock_writer_unlock(&fuse_netnodes_lock); + DEBUG("netnodes_lock", "releasing rwlock_writer_lock.\n"); + free(nn); + return NULL; /* can't help, sorry. */ + } + + /* enqueue new hash_element */ + new->next = hash_el->next; + hash_el->next = new; + + hash_el = new; + } + + hash_el->nn = nn; + + rwlock_writer_unlock(&fuse_netnodes_lock); + DEBUG("netnodes_lock", "releasing rwlock_writer_lock.\n"); + return nn; +} + + +/* scan the whole netnode hash and call fuse_ops->fsync on every node, + * that may be out of sync + */ +error_t +fuse_sync_filesystem(void) +{ + int i; + error_t err = 0; + + if(! FUSE_OP_HAVE(fsync)) + return err; /* success */ + + /* make sure, nobody tries to confuse us */ + rwlock_writer_lock(&fuse_netnodes_lock); + + for(i = 0; i < HASH_BUCKETS; i ++) + { + struct hash_element *he = &fuse_netnodes[i]; + + if(he->nn) + do + { + if(he->nn->may_need_sync) + { + err = -(fuse_ops ? + fuse_ops->fsync(he->nn->path, 0, &he->nn->info) : + fuse_ops_compat->fsync(he->nn->path, 0)); + + if(err) + goto out; + else + he->nn->may_need_sync = 0; + } + + if(he->nn->node) + DEBUG("netnode-scan", "netnode=%s has attached node\n", + he->nn->path); + } + while((he = he->next)); + } + + out: + rwlock_writer_unlock(&fuse_netnodes_lock); + return err; +} |