improvements to the kernel interface
diff --git a/lib/fuse.c b/lib/fuse.c
index ffb3489..079220a 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -81,11 +81,9 @@
abort();
}
-static void hash_ino(struct fuse *f, struct node *node, fino_t ino)
+static void hash_ino(struct fuse *f, struct node *node)
{
- size_t hash = ino % f->ino_table_size;
- node->ino = ino;
-
+ size_t hash = node->ino % f->ino_table_size;
node->ino_next = f->ino_table[hash];
f->ino_table[hash] = node;
}
@@ -102,16 +100,13 @@
}
}
-static fino_t get_ino(struct node *node)
-{
- return node->ino;
-}
-
static fino_t next_ino(struct fuse *f)
{
- do f->ctr++;
- while(f->ctr == 0 || __get_node(f, f->ctr) != NULL);
-
+ do {
+ f->ctr++;
+ if(!f->ctr)
+ f->generation ++;
+ } while(f->ctr == 0 || __get_node(f, f->ctr) != NULL);
return f->ctr;
}
@@ -176,8 +171,8 @@
}
}
-static fino_t find_node(struct fuse *f, fino_t parent, char *name,
- struct fuse_attr *attr, int version)
+static struct node *find_node(struct fuse *f, fino_t parent, char *name,
+ struct fuse_attr *attr, int version)
{
struct node *node;
int mode = attr->mode & S_IFMT;
@@ -198,13 +193,15 @@
node = (struct node *) calloc(1, sizeof(struct node));
node->mode = mode;
node->rdev = rdev;
- hash_ino(f, node, next_ino(f));
+ node->ino = next_ino(f);
+ node->generation = f->generation;
+ hash_ino(f, node);
hash_name(f, node, parent, name);
out:
node->version = version;
pthread_mutex_unlock(&f->lock);
- return get_ino(node);
+ return node;
}
static char *add_name(char *buf, char *s, const char *name)
@@ -407,11 +404,33 @@
return res;
}
+static int lookup_path(struct fuse *f, fino_t ino, int version, char *name,
+ const char *path, struct fuse_lookup_out *arg)
+{
+ int res;
+ struct stat buf;
+
+ res = f->op.getattr(path, &buf);
+ if(res == 0) {
+ struct node *node;
+
+ memset(arg, 0, sizeof(struct fuse_lookup_out));
+ convert_stat(&buf, &arg->attr);
+ node = find_node(f, ino, name, &arg->attr, version);
+ arg->ino = node->ino;
+ arg->generation = node->generation;
+ if(f->flags & FUSE_DEBUG) {
+ printf(" INO: %li\n", arg->ino);
+ fflush(stdout);
+ }
+ }
+ return res;
+}
+
static void do_lookup(struct fuse *f, struct fuse_in_header *in, char *name)
{
int res;
char *path;
- struct stat buf;
struct fuse_lookup_out arg;
res = -ENOENT;
@@ -423,19 +442,9 @@
}
res = -ENOSYS;
if(f->op.getattr)
- res = f->op.getattr(path, &buf);
+ res = lookup_path(f, in->ino, in->unique, name, path, &arg);
free(path);
}
-
- if(res == 0) {
- memset(&arg, 0, sizeof(struct fuse_lookup_out));
- convert_stat(&buf, &arg.attr);
- arg.ino = find_node(f, in->ino, name, &arg.attr, in->unique);
- if(f->flags & FUSE_DEBUG) {
- printf(" LOOKUP: %li\n", arg.ino);
- fflush(stdout);
- }
- }
send_reply(f, in, res, &arg, sizeof(arg));
}
@@ -609,27 +618,24 @@
{
int res;
char *path;
- struct fuse_mknod_out outarg;
- struct stat buf;
+ char *name = PARAM(inarg);
+ struct fuse_lookup_out outarg;
res = -ENOENT;
- path = get_path_name(f, in->ino, PARAM(inarg));
+ path = get_path_name(f, in->ino, name);
if(path != NULL) {
+ if(f->flags & FUSE_DEBUG) {
+ printf("MKNOD %s\n", path);
+ fflush(stdout);
+ }
res = -ENOSYS;
if(f->op.mknod && f->op.getattr) {
res = f->op.mknod(path, inarg->mode, inarg->rdev);
if(res == 0)
- res = f->op.getattr(path, &buf);
+ res = lookup_path(f, in->ino, in->unique, name, path, &outarg);
}
free(path);
}
- if(res == 0) {
- memset(&outarg, 0, sizeof(struct fuse_mknod_out));
- convert_stat(&buf, &outarg.attr);
- outarg.ino = find_node(f, in->ino, PARAM(inarg), &outarg.attr,
- in->unique);
- }
-
send_reply(f, in, res, &outarg, sizeof(outarg));
}
@@ -638,16 +644,25 @@
{
int res;
char *path;
+ char *name = PARAM(inarg);
+ struct fuse_lookup_out outarg;
res = -ENOENT;
- path = get_path_name(f, in->ino, PARAM(inarg));
+ path = get_path_name(f, in->ino, name);
if(path != NULL) {
+ if(f->flags & FUSE_DEBUG) {
+ printf("MKDIR %s\n", path);
+ fflush(stdout);
+ }
res = -ENOSYS;
- if(f->op.mkdir)
+ if(f->op.mkdir && f->op.getattr) {
res = f->op.mkdir(path, inarg->mode);
+ if(res == 0)
+ res = lookup_path(f, in->ino, in->unique, name, path, &outarg);
+ }
free(path);
}
- send_reply(f, in, res, NULL, 0);
+ send_reply(f, in, res, &outarg, sizeof(outarg));
}
static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name)
@@ -679,16 +694,24 @@
{
int res;
char *path;
+ struct fuse_lookup_out outarg;
res = -ENOENT;
path = get_path_name(f, in->ino, name);
if(path != NULL) {
+ if(f->flags & FUSE_DEBUG) {
+ printf("SYMLINK %s\n", path);
+ fflush(stdout);
+ }
res = -ENOSYS;
- if(f->op.symlink)
+ if(f->op.symlink && f->op.getattr) {
res = f->op.symlink(link, path);
+ if(res == 0)
+ res = lookup_path(f, in->ino, in->unique, name, path, &outarg);
+ }
free(path);
}
- send_reply(f, in, res, NULL, 0);
+ send_reply(f, in, res, &outarg, sizeof(outarg));
}
static void do_rename(struct fuse *f, struct fuse_in_header *in,
@@ -725,20 +748,30 @@
int res;
char *oldpath;
char *newpath;
+ char *name = PARAM(arg);
+ struct fuse_lookup_out outarg;
res = -ENOENT;
oldpath = get_path(f, in->ino);
if(oldpath != NULL) {
- newpath = get_path_name(f, arg->newdir, PARAM(arg));
+ newpath = get_path_name(f, arg->newdir, name);
if(newpath != NULL) {
+ if(f->flags & FUSE_DEBUG) {
+ printf("LINK %s\n", newpath);
+ fflush(stdout);
+ }
res = -ENOSYS;
- if(f->op.link)
+ if(f->op.link && f->op.getattr) {
res = f->op.link(oldpath, newpath);
+ if(res == 0)
+ res = lookup_path(f, arg->newdir, in->unique, name,
+ newpath, &outarg);
+ }
free(newpath);
}
free(oldpath);
}
- send_reply(f, in, res, NULL, 0);
+ send_reply(f, in, res, &outarg, sizeof(outarg));
}
static void do_open(struct fuse *f, struct fuse_in_header *in,
@@ -1090,6 +1123,7 @@
f->flags = flags;
f->fd = fd;
f->ctr = 0;
+ f->generation = 0;
/* FIXME: Dynamic hash table */
f->name_table_size = 14057;
f->name_table = (struct node **)
@@ -1111,7 +1145,9 @@
root->rdev = 0;
root->name = strdup("/");
root->parent = 0;
- hash_ino(f, root, FUSE_ROOT_INO);
+ root->ino = FUSE_ROOT_INO;
+ root->generation = 0;
+ hash_ino(f, root);
return f;
}
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 52f1fdc..4eaa5ba 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -16,6 +16,7 @@
struct node *name_next;
struct node *ino_next;
fino_t ino;
+ unsigned int generation;
fino_t parent;
char *name;
int mode;
@@ -32,6 +33,7 @@
struct node **ino_table;
size_t ino_table_size;
fino_t ctr;
+ unsigned int generation;
pthread_mutex_t lock;
int numworker;
int numavail;