diff options
author | 2001-10-30 15:06:52 +0000 | |
---|---|---|
committer | 2001-10-30 15:06:52 +0000 | |
commit | 19dff1ba9dfe6f474d22224267a7407c949d6803 (patch) | |
tree | 5e150c70866bc04869930c402bf80b6a99540489 /kernel | |
parent | b483c93623dd64eb5f1dcf23f32adb32f616ee0e (diff) |
x
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/dev.c | 12 | ||||
-rw-r--r-- | kernel/dir.c | 113 | ||||
-rw-r--r-- | kernel/inode.c | 3 |
3 files changed, 84 insertions, 44 deletions
diff --git a/kernel/dev.c b/kernel/dev.c index a91a176..d32589d 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -53,14 +53,14 @@ static int request_check(struct fuse_req *req, struct fuse_out *outp) oh = (struct fuse_out_header *) req->out; size = req->outsize - OHSIZE; - if (oh->result <= -512 || oh->result > 0) { - printk("fuse: bad result\n"); + if (oh->error <= -512 || oh->error > 0) { + printk("fuse: bad error value: %i\n", oh->error); return -EPROTO; } if(size > outp->argsize || - (oh->result == 0 && !outp->argvar && size != outp->argsize) || - (oh->result != 0 && size != 0)) { + (oh->error == 0 && !outp->argvar && size != outp->argsize) || + (oh->error != 0 && size != 0)) { printk("fuse: invalid argument length: %i (%i)\n", size, req->opcode); return -EPROTO; @@ -71,7 +71,7 @@ static int request_check(struct fuse_req *req, struct fuse_out *outp) if(size) memcpy(outp->arg, req->out + OHSIZE, size); - return oh->result; + return oh->error; } static void request_free(struct fuse_req *req) @@ -158,7 +158,7 @@ void request_send(struct fuse_conn *fc, struct fuse_in *inp, spin_unlock(&fuse_lock); out: if(outp) - outp->h.result = ret; + outp->h.error = ret; } static int request_wait(struct fuse_conn *fc) diff --git a/kernel/dir.c b/kernel/dir.c index 065ac01..b23def7 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -22,6 +22,7 @@ static struct inode_operations fuse_special_inode_operations; static struct file_operations fuse_dir_operations; static struct file_operations fuse_file_operations; +static struct dentry_operations fuse_dentry_opertations; static void change_attributes(struct inode *inode, struct fuse_attr *attr) { @@ -57,7 +58,6 @@ void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) } } - static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry) { struct fuse_conn *fc = dir->i_sb->u.generic_sbp; @@ -74,19 +74,18 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry) out.arg = &arg; request_send(fc, &in, &out); - if(out.h.result) { - /* Negative dentries are not hashed */ - if(out.h.result == -ENOENT) - return NULL; - else - return ERR_PTR(out.h.result); + inode = NULL; + if(!out.h.error) { + inode = iget(dir->i_sb, arg.ino); + if(!inode) + return ERR_PTR(-ENOMEM); + + fuse_init_inode(inode, &arg.attr); } + else if(out.h.error != -ENOENT) + return ERR_PTR(out.h.error); - inode = iget(dir->i_sb, arg.ino); - if(!inode) - return ERR_PTR(-ENOMEM); - - fuse_init_inode(inode, &arg.attr); + entry->d_op = &fuse_dentry_opertations; d_add(entry, inode); return NULL; } @@ -121,15 +120,15 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, request_send(fc, &in, &out); kfree(inarg); - if(out.h.result) - return out.h.result; + if(out.h.error) + return out.h.error; inode = iget(dir->i_sb, outarg.ino); if(!inode) return -ENOMEM; fuse_init_inode(inode, &outarg.attr); - d_add(entry, inode); + d_instantiate(entry, inode); return 0; } @@ -163,7 +162,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode) request_send(fc, &in, &out); kfree(inarg); - return out.h.result; + return out.h.error; } static int fuse_symlink(struct inode *dir, struct dentry *entry, @@ -190,7 +189,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, request_send(fc, &in, &out); kfree(inarg); - return out.h.result; + return out.h.error; } static int fuse_remove(struct inode *dir, struct dentry *entry, @@ -205,12 +204,7 @@ static int fuse_remove(struct inode *dir, struct dentry *entry, in.argsize = entry->d_name.len + 1; in.arg = entry->d_name.name; request_send(fc, &in, &out); - if(!out.h.result) { - d_drop(entry); - entry->d_inode->i_nlink = 0; - } - - return out.h.result; + return out.h.error; } static int fuse_unlink(struct inode *dir, struct dentry *entry) @@ -251,7 +245,35 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, request_send(fc, &in, &out); kfree(inarg); - return out.h.result; + return out.h.error; +} + +static int fuse_link(struct dentry *entry, struct inode *newdir, + struct dentry *newent) +{ + struct inode *inode = entry->d_inode; + struct fuse_conn *fc = inode->i_sb->u.generic_sbp; + struct fuse_in in = FUSE_IN_INIT; + struct fuse_out out = FUSE_OUT_INIT; + struct fuse_link_in *inarg; + unsigned int insize; + + insize = offsetof(struct fuse_link_in, name) + newent->d_name.len + 1; + inarg = kmalloc(insize, GFP_KERNEL); + if(!inarg) + return -ENOMEM; + + inarg->newdir = newdir->i_ino; + strcpy(inarg->name, newent->d_name.name); + + in.h.opcode = FUSE_LINK; + in.h.ino = inode->i_ino; + in.argsize = insize; + in.arg = inarg; + request_send(fc, &in, &out); + kfree(inarg); + + return out.h.error; } static int fuse_permission(struct inode *inode, int mask) @@ -259,6 +281,8 @@ static int fuse_permission(struct inode *inode, int mask) return 0; } +/* Only revalidate the root inode, since lookup is always redone on + the last path segment, and lookup refreshes the attributes */ static int fuse_revalidate(struct dentry *dentry) { struct inode *inode = dentry->d_inode; @@ -267,18 +291,19 @@ static int fuse_revalidate(struct dentry *dentry) struct fuse_out out = FUSE_OUT_INIT; struct fuse_getattr_out arg; + if(inode->i_ino != FUSE_ROOT_INO) + return 0; + in.h.opcode = FUSE_GETATTR; in.h.ino = inode->i_ino; out.argsize = sizeof(arg); out.arg = &arg; request_send(fc, &in, &out); - if(out.h.result == 0) + if(!out.h.error) change_attributes(inode, &arg.attr); - else - d_drop(dentry); - - return out.h.result; + + return out.h.error; } static int parse_dirfile(char *buf, size_t nbytes, struct file *file, @@ -347,9 +372,9 @@ static int read_link(struct dentry *dentry, char **bufp) out.argsize = PAGE_SIZE - 1; out.argvar = 1; request_send(fc, &in, &out); - if(out.h.result) { + if(out.h.error) { free_page(page); - return out.h.result; + return out.h.error; } *bufp = (char *) page; @@ -405,7 +430,7 @@ static int fuse_dir_open(struct inode *inode, struct file *file) out.argsize = sizeof(outarg); out.arg = &outarg; request_send(fc, &in, &out); - if(out.h.result == 0) { + if(!out.h.error) { struct file *cfile = outarg.file; struct inode *inode; if(!cfile) { @@ -422,7 +447,7 @@ static int fuse_dir_open(struct inode *inode, struct file *file) file->private_data = cfile; } - return out.h.result; + return out.h.error; } static int fuse_dir_release(struct inode *inode, struct file *file) @@ -437,6 +462,14 @@ static int fuse_dir_release(struct inode *inode, struct file *file) return 0; } +static int fuse_dentry_revalidate(struct dentry *entry, int flags) +{ + if(!entry->d_inode || !(flags & LOOKUP_CONTINUE)) + return 0; + else + return 1; +} + static struct inode_operations fuse_dir_inode_operations = { lookup: fuse_lookup, @@ -447,12 +480,12 @@ static struct inode_operations fuse_dir_inode_operations = unlink: fuse_unlink, rmdir: fuse_rmdir, rename: fuse_rename, -#if 0 link: fuse_link, +#if 0 setattr: fuse_setattr, #endif permission: fuse_permission, - revalidate: fuse_revalidate, + revalidate: fuse_revalidate, }; static struct file_operations fuse_dir_operations = { @@ -464,12 +497,12 @@ static struct file_operations fuse_dir_operations = { static struct inode_operations fuse_file_inode_operations = { permission: fuse_permission, - revalidate: fuse_revalidate, + revalidate: fuse_revalidate, }; static struct inode_operations fuse_special_inode_operations = { permission: fuse_permission, - revalidate: fuse_revalidate, + revalidate: fuse_revalidate, }; static struct file_operations fuse_file_operations = { @@ -479,7 +512,11 @@ static struct inode_operations fuse_symlink_inode_operations = { readlink: fuse_readlink, follow_link: fuse_follow_link, - revalidate: fuse_revalidate, + revalidate: fuse_revalidate, +}; + +static struct dentry_operations fuse_dentry_opertations = { + d_revalidate: fuse_dentry_revalidate, }; /* diff --git a/kernel/inode.c b/kernel/inode.c index b59a146..702ef57 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -182,6 +182,9 @@ static struct super_block *fuse_read_super(struct super_block *sb, sb->u.generic_sbp = fc; sb->s_root = d_alloc_root(root); + if(!sb->s_root) + goto err; + fc->sb = sb; spin_unlock(&fuse_lock); |