diff options
author | 2004-11-02 17:32:03 +0000 | |
---|---|---|
committer | 2004-11-02 17:32:03 +0000 | |
commit | a13d90020721d30c3ac03b4e6905aa54cab1aed7 (patch) | |
tree | 7a919bf696f6fedbca5177bec5451894d5f81433 /kernel | |
parent | 874e3c166213a1dec3d191f78adc87b156c3f6e8 (diff) |
added support for setting the st_ino field
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/dev.c | 24 | ||||
-rw-r--r-- | kernel/dir.c | 168 | ||||
-rw-r--r-- | kernel/file.c | 24 | ||||
-rw-r--r-- | kernel/fuse_i.h | 18 | ||||
-rw-r--r-- | kernel/inode.c | 74 |
5 files changed, 197 insertions, 111 deletions
diff --git a/kernel/dev.c b/kernel/dev.c index c783ead..2e081d0 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -433,33 +433,21 @@ static inline int copy_out_header(struct fuse_out_header *oh, const char *buf, return 0; } -#ifdef KERNEL_2_6 static int fuse_invalidate(struct fuse_conn *fc, struct fuse_user_header *uh) { - struct inode *inode = ilookup(fc->sb, uh->ino); + struct inode *inode = fuse_ilookup(fc, uh->ino, uh->nodeid); if (!inode) return -ENOENT; fuse_sync_inode(inode); +#ifdef KERNEL_2_6 invalidate_inode_pages(inode->i_mapping); +#else + invalidate_inode_pages(inode); +#endif + iput(inode); return 0; } -#else -static int fuse_invalidate(struct fuse_conn *fc, struct fuse_user_header *uh) -{ - struct inode *inode = iget(fc->sb, uh->ino); - int err = -ENOENT; - if (inode) { - if (INO_FI(inode)) { - fuse_sync_inode(inode); - invalidate_inode_pages(inode); - err = 0; - } - iput(inode); - } - return err; -} -#endif static int fuse_user_request(struct fuse_conn *fc, const char *buf, size_t nbytes) diff --git a/kernel/dir.c b/kernel/dir.c index 36eb3bf..ce6df5d 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -35,6 +35,7 @@ static void change_attributes(struct inode *inode, struct fuse_attr *attr) #endif } + inode->i_ino = attr->ino; inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777); inode->i_nlink = attr->nlink; inode->i_uid = attr->uid; @@ -80,40 +81,102 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) printk("fuse_init_inode: bad file type: %o\n", inode->i_mode); } -struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation, - struct fuse_attr *attr, int version) +#ifdef KERNEL_2_6 +static int fuse_inode_eq(struct inode *inode, void *_nodeidp) +{ + unsigned long nodeid = *(unsigned long *) _nodeidp; + struct fuse_inode *fi = INO_FI(inode); + if (fi->nodeid == nodeid) + return 1; + else + return 0; +} + +static int fuse_inode_set(struct inode *inode, void *_nodeidp) +{ + unsigned long nodeid = *(unsigned long *) _nodeidp; + struct fuse_inode *fi = INO_FI(inode); + fi->nodeid = nodeid; + return 0; +} + +struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, + int generation, struct fuse_attr *attr, int version) { struct inode *inode; - inode = iget(sb, ino); - if (inode) { - if (!INO_FI(inode)) { - struct fuse_inode *fi = fuse_inode_alloc(); - if (!fi) { - iput(inode); - inode = NULL; - goto out; - } - INO_FI(inode) = fi; - inode->i_generation = generation; - fuse_init_inode(inode, attr); - } else if (inode->i_generation != generation) - printk("fuse_iget: bad generation for ino %lu\n", ino); - - change_attributes(inode, attr); - inode->i_version = version; - } - out: + inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); + if (!inode) + return NULL; + + if ((inode->i_state & I_NEW)) { + inode->i_generation = generation; + fuse_init_inode(inode, attr); + unlock_new_inode(inode); + } else if (inode->i_generation != generation) + printk("fuse_iget: bad generation for node %lu\n", nodeid); + + change_attributes(inode, attr); + inode->i_version = version; + return inode; +} + +struct inode *fuse_ilookup(struct fuse_conn *fc, ino_t ino, unsigned long nodeid) +{ + return ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid); +} +#else +static int fuse_inode_eq(struct inode *inode, unsigned long ino, void *_nodeidp){ + unsigned long nodeid = *(unsigned long *) _nodeidp; + struct fuse_inode *fi = INO_FI(inode); + if (inode->u.generic_ip && fi->nodeid == nodeid) + return 1; + else + return 0; +} + +struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, + int generation, struct fuse_attr *attr, int version) +{ + struct inode *inode; + + inode = iget4(sb, attr->ino, fuse_inode_eq, &nodeid); + if (!inode) + return NULL; + + if (!inode->u.generic_ip) { + struct fuse_inode *fi = INO_FI(inode); + fi->nodeid = nodeid; + inode->u.generic_ip = inode; + inode->i_generation = generation; + fuse_init_inode(inode, attr); + } else if (inode->i_generation != generation) + printk("fuse_iget: bad generation for node %lu\n", nodeid); + + change_attributes(inode, attr); + inode->i_version = version; + return inode; +} +struct inode *fuse_ilookup(struct fuse_conn *fc, ino_t ino, unsigned long nodeid) +{ + struct inode *inode = iget4(fc->sb, ino, fuse_inode_eq, &nodeid); + if (inode && !inode->u.generic_ip) { + iput(inode); + inode = NULL; + } return inode; } +#endif + static int fuse_send_lookup(struct fuse_conn *fc, struct fuse_req *req, struct inode *dir, struct dentry *entry, struct fuse_entry_out *outarg, int *version) { + struct fuse_inode *fi = INO_FI(dir); req->in.h.opcode = FUSE_LOOKUP; - req->in.h.ino = dir->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = entry->d_name.len + 1; req->in.args[0].value = entry->d_name.name; @@ -171,10 +234,10 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry, err = fuse_send_lookup(fc, req, dir, entry, &outarg, &version); if (!err) { - inode = fuse_iget(dir->i_sb, outarg.ino, outarg.generation, + inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, &outarg.attr, version); if (!inode) { - fuse_send_forget(fc, req, outarg.ino, version); + fuse_send_forget(fc, req, outarg.nodeid, version); return -ENOMEM; } } @@ -208,10 +271,10 @@ static int lookup_new_entry(struct fuse_conn *fc, struct fuse_req *req, { struct inode *inode; struct fuse_inode *fi; - inode = fuse_iget(dir->i_sb, outarg->ino, outarg->generation, + inode = fuse_iget(dir->i_sb, outarg->nodeid, outarg->generation, &outarg->attr, version); if (!inode) { - fuse_send_forget(fc, req, outarg->ino, version); + fuse_send_forget(fc, req, outarg->nodeid, version); return -ENOMEM; } fuse_put_request(fc, req); @@ -240,6 +303,7 @@ static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode, dev_t rdev) { struct fuse_conn *fc = INO_FC(dir); + struct fuse_inode *fi = INO_FI(dir); struct fuse_req *req = fuse_get_request(fc); struct fuse_mknod_in inarg; struct fuse_entry_out outarg; @@ -252,7 +316,7 @@ static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode, inarg.mode = mode; inarg.rdev = new_encode_dev(rdev); req->in.h.opcode = FUSE_MKNOD; - req->in.h.ino = dir->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 2; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -280,6 +344,7 @@ static int _fuse_create(struct inode *dir, struct dentry *entry, int mode) static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode) { struct fuse_conn *fc = INO_FC(dir); + struct fuse_inode *fi = INO_FI(dir); struct fuse_req *req = fuse_get_request(fc); struct fuse_mkdir_in inarg; struct fuse_entry_out outarg; @@ -291,7 +356,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode) memset(&inarg, 0, sizeof(inarg)); inarg.mode = mode; req->in.h.opcode = FUSE_MKDIR; - req->in.h.ino = dir->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 2; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -314,6 +379,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, const char *link) { struct fuse_conn *fc = INO_FC(dir); + struct fuse_inode *fi = INO_FI(dir); struct fuse_req *req; struct fuse_entry_out outarg; unsigned int len = strlen(link) + 1; @@ -327,7 +393,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, return -ERESTARTSYS; req->in.h.opcode = FUSE_SYMLINK; - req->in.h.ino = dir->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 2; req->in.args[0].size = entry->d_name.len + 1; req->in.args[0].value = entry->d_name.name; @@ -349,6 +415,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, static int fuse_unlink(struct inode *dir, struct dentry *entry) { struct fuse_conn *fc = INO_FC(dir); + struct fuse_inode *fi = INO_FI(dir); struct fuse_req *req = fuse_get_request(fc); int err; @@ -356,7 +423,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) return -ERESTARTSYS; req->in.h.opcode = FUSE_UNLINK; - req->in.h.ino = dir->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = entry->d_name.len + 1; req->in.args[0].value = entry->d_name.name; @@ -379,6 +446,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) static int fuse_rmdir(struct inode *dir, struct dentry *entry) { struct fuse_conn *fc = INO_FC(dir); + struct fuse_inode *fi = INO_FI(dir); struct fuse_req *req = fuse_get_request(fc); int err; @@ -386,7 +454,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) return -ERESTARTSYS; req->in.h.opcode = FUSE_RMDIR; - req->in.h.ino = dir->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = entry->d_name.len + 1; req->in.args[0].value = entry->d_name.name; @@ -404,6 +472,8 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, struct inode *newdir, struct dentry *newent) { struct fuse_conn *fc = INO_FC(olddir); + struct fuse_inode *oldfi = INO_FI(olddir); + struct fuse_inode *newfi = INO_FI(newdir); struct fuse_req *req = fuse_get_request(fc); struct fuse_rename_in inarg; int err; @@ -412,9 +482,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, return -ERESTARTSYS; memset(&inarg, 0, sizeof(inarg)); - inarg.newdir = newdir->i_ino; + inarg.newdir = newfi->nodeid; req->in.h.opcode = FUSE_RENAME; - req->in.h.ino = olddir->i_ino; + req->in.h.nodeid = oldfi->nodeid; req->in.numargs = 3; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -438,6 +508,8 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, { struct inode *inode = entry->d_inode; struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); + struct fuse_inode *newfi = INO_FI(newdir); struct fuse_req *req = fuse_get_request(fc); struct fuse_link_in inarg; struct fuse_entry_out outarg; @@ -447,9 +519,9 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, return -ERESTARTSYS; memset(&inarg, 0, sizeof(inarg)); - inarg.newdir = newdir->i_ino; + inarg.newdir = newfi->nodeid; req->in.h.opcode = FUSE_LINK; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 2; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -482,7 +554,7 @@ int fuse_do_getattr(struct inode *inode) return -ERESTARTSYS; req->in.h.opcode = FUSE_GETATTR; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->out.numargs = 1; req->out.args[0].size = sizeof(arg); req->out.args[0].value = &arg; @@ -503,7 +575,7 @@ static int fuse_revalidate(struct dentry *entry) struct fuse_inode *fi = INO_FI(inode); struct fuse_conn *fc = INO_FC(inode); - if (inode->i_ino == FUSE_ROOT_INO) { + if (fi->nodeid == FUSE_ROOT_ID) { if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid && (!(fc->flags & FUSE_ALLOW_ROOT) || @@ -598,6 +670,7 @@ static int fuse_getdir(struct file *file) { struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_req *req = fuse_get_request(fc); struct fuse_getdir_out_i outarg; int err; @@ -606,7 +679,7 @@ static int fuse_getdir(struct file *file) return -ERESTARTSYS; req->in.h.opcode = FUSE_GETDIR; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->out.numargs = 1; req->out.args[0].size = sizeof(struct fuse_getdir_out); req->out.args[0].value = &outarg; @@ -651,6 +724,7 @@ static char *read_link(struct dentry *dentry) { struct inode *inode = dentry->d_inode; struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_req *req = fuse_get_request(fc); char *link; @@ -663,7 +737,7 @@ static char *read_link(struct dentry *dentry) goto out; } req->in.h.opcode = FUSE_READLINK; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->out.argvar = 1; req->out.numargs = 1; req->out.args[0].size = PAGE_SIZE - 1; @@ -793,7 +867,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) memset(&inarg, 0, sizeof(inarg)); inarg.valid = iattr_to_fattr(attr, &inarg.attr); req->in.h.opcode = FUSE_SETATTR; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -837,7 +911,7 @@ static int _fuse_dentry_revalidate(struct dentry *entry) if (ret) return 0; - if (outarg.ino != inode->i_ino) + if (outarg.nodeid != fi->nodeid) return 0; change_attributes(inode, &outarg.attr); @@ -942,6 +1016,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name, { struct inode *inode = entry->d_inode; struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_req *req; struct fuse_setxattr_in inarg; int err; @@ -960,7 +1035,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name, inarg.size = size; inarg.flags = flags; req->in.h.opcode = FUSE_SETXATTR; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 3; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -983,6 +1058,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name, { struct inode *inode = entry->d_inode; struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_req *req; struct fuse_getxattr_in inarg; struct fuse_getxattr_out outarg; @@ -998,7 +1074,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name, memset(&inarg, 0, sizeof(inarg)); inarg.size = size; req->in.h.opcode = FUSE_GETXATTR; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 2; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -1032,6 +1108,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) { struct inode *inode = entry->d_inode; struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_req *req; struct fuse_getxattr_in inarg; struct fuse_getxattr_out outarg; @@ -1047,7 +1124,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) memset(&inarg, 0, sizeof(inarg)); inarg.size = size; req->in.h.opcode = FUSE_LISTXATTR; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -1079,6 +1156,7 @@ static int fuse_removexattr(struct dentry *entry, const char *name) { struct inode *inode = entry->d_inode; struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_req *req; int err; @@ -1090,7 +1168,7 @@ static int fuse_removexattr(struct dentry *entry, const char *name) return -ERESTARTSYS; req->in.h.opcode = FUSE_REMOVEXATTR; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = strlen(name) + 1; req->in.args[0].value = name; diff --git a/kernel/file.c b/kernel/file.c index f4e0b56..aa9dba3 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -33,6 +33,7 @@ MODULE_PARM_DESC(user_mmap, "Allow non root user to create a shared writable map static int fuse_open(struct inode *inode, struct file *file) { struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_req *req; struct fuse_open_in inarg; struct fuse_open_out outarg; @@ -45,7 +46,7 @@ static int fuse_open(struct inode *inode, struct file *file) /* If opening the root node, no lookup has been performed on it, so the attributes must be refreshed */ - if (inode->i_ino == FUSE_ROOT_INO) { + if (fi->nodeid == FUSE_ROOT_ID) { int err = fuse_do_getattr(inode); if (err) return err; @@ -68,11 +69,10 @@ static int fuse_open(struct inode *inode, struct file *file) goto out_put_request; } - memset(&inarg, 0, sizeof(inarg)); inarg.flags = file->f_flags & ~O_EXCL; req->in.h.opcode = FUSE_OPEN; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -140,7 +140,7 @@ static int fuse_release(struct inode *inode, struct file *file) inarg->fh = ff->fh; inarg->flags = file->f_flags & ~O_EXCL; req->in.h.opcode = FUSE_RELEASE; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_release_in); req->in.args[0].value = inarg; @@ -157,6 +157,7 @@ static int fuse_flush(struct file *file) { struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_file *ff = file->private_data; struct fuse_req *req = ff->release_req; struct fuse_flush_in inarg; @@ -169,7 +170,7 @@ static int fuse_flush(struct file *file) memset(&inarg, 0, sizeof(inarg)); inarg.fh = ff->fh; req->in.h.opcode = FUSE_FLUSH; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -210,7 +211,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) inarg.fh = ff->fh; inarg.datasync = datasync; req->in.h.opcode = FUSE_FSYNC; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -228,6 +229,7 @@ static ssize_t fuse_send_read(struct file *file, struct inode *inode, char *buf, loff_t pos, size_t count) { struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_file *ff = file->private_data; struct fuse_req *req; struct fuse_read_in inarg; @@ -242,7 +244,7 @@ static ssize_t fuse_send_read(struct file *file, struct inode *inode, inarg.offset = pos; inarg.size = count; req->in.h.opcode = FUSE_READ; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -333,6 +335,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file, struct inode *inode) { struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_file *ff = file->private_data; struct fuse_read_in *inarg; loff_t pos; @@ -348,7 +351,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file, inarg->offset = pos; inarg->size = numpages * PAGE_CACHE_SIZE; req->in.h.opcode = FUSE_READ; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_read_in); req->in.args[0].value = inarg; @@ -588,6 +591,7 @@ static ssize_t fuse_send_write(struct fuse_req *req, int writepage, const char *buf, loff_t pos, size_t count) { struct fuse_conn *fc = INO_FC(inode); + struct fuse_inode *fi = INO_FI(inode); struct fuse_write_in inarg; struct fuse_write_out outarg; ssize_t res; @@ -598,7 +602,7 @@ static ssize_t fuse_send_write(struct fuse_req *req, int writepage, inarg.offset = pos; inarg.size = count; req->in.h.opcode = FUSE_WRITE; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; if (writepage) { req->in.h.uid = 0; req->in.h.gid = 0; @@ -757,7 +761,7 @@ static void send_write_nonblock(struct fuse_req *req, struct inode *inode, inarg->offset = ((loff_t) page->index << PAGE_CACHE_SHIFT); inarg->size = count; req->in.h.opcode = FUSE_WRITE; - req->in.h.ino = inode->i_ino; + req->in.h.nodeid = fi->nodeid; req->in.h.uid = 0; req->in.h.gid = 0; req->in.h.pid = 0; diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index 8e3b416..d0cde75 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -79,6 +79,7 @@ permission checking is done in the kernel */ /** FUSE specific inode data */ struct fuse_inode { + unsigned long nodeid; struct fuse_req *forget_req; struct rw_semaphore write_sem; unsigned long i_time; @@ -261,7 +262,7 @@ struct fuse_getdir_out_i { #endif #define INO_FC(inode) SB_FC((inode)->i_sb) #define DEV_FC(file) ((file)->private_data) -#define INO_FI(inode) ((inode)->u.generic_ip) +#define INO_FI(i) ((struct fuse_inode *) (((struct inode *)(i))+1)) /** @@ -278,15 +279,17 @@ extern spinlock_t fuse_lock; /** * Get a filled in inode */ -struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation, - struct fuse_attr *attr, int version); +struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, + int generation, struct fuse_attr *attr, int version); +struct inode *fuse_ilookup(struct fuse_conn *fc, ino_t ino, unsigned long nodeid); + /** * Send FORGET command */ -void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, ino_t ino, - int version); +void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, + unsigned long nodeid, int version); /** * Initialise operations on regular file @@ -381,11 +384,6 @@ int fuse_do_getattr(struct inode *inode); */ void fuse_sync_inode(struct inode *inode); -/** - * Allocate fuse specific inode data - */ -struct fuse_inode *fuse_inode_alloc(void); - /* * Local Variables: * indent-tabs-mode: t diff --git a/kernel/inode.c b/kernel/inode.c index 8de566c..6ad42ee 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -58,32 +58,39 @@ struct fuse_mount_data { unsigned int max_read; }; -struct fuse_inode *fuse_inode_alloc(void) +static struct inode *fuse_alloc_inode(struct super_block *sb) { + struct inode *inode; struct fuse_inode *fi; - fi = kmem_cache_alloc(fuse_inode_cachep, SLAB_KERNEL); - if (fi) { - memset(fi, 0, sizeof(*fi)); - fi->forget_req = fuse_request_alloc(); - if (!fi->forget_req) { - kmem_cache_free(fuse_inode_cachep, fi); - fi = NULL; - } else { - init_rwsem(&fi->write_sem); - INIT_LIST_HEAD(&fi->write_files); - } + inode = kmem_cache_alloc(fuse_inode_cachep, SLAB_KERNEL); + if (!inode) + return NULL; + +#ifndef KERNEL_2_6 + inode->u.generic_ip = NULL; +#endif + + fi = INO_FI(inode); + memset(fi, 0, sizeof(*fi)); + fi->forget_req = fuse_request_alloc(); + if (!fi->forget_req) { + kmem_cache_free(fuse_inode_cachep, inode); + return NULL; } + init_rwsem(&fi->write_sem); + INIT_LIST_HEAD(&fi->write_files); - return fi; + return inode; } -static void fuse_inode_free(struct fuse_inode *fi) +static void fuse_destroy_inode(struct inode *inode) { + struct fuse_inode *fi = INO_FI(inode); BUG_ON(!list_empty(&fi->write_files)); if (fi->forget_req) fuse_request_free(fi->forget_req); - kmem_cache_free(fuse_inode_cachep, fi); + kmem_cache_free(fuse_inode_cachep, inode); } static void fuse_read_inode(struct inode *inode) @@ -91,13 +98,13 @@ static void fuse_read_inode(struct inode *inode) /* No op */ } -void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, ino_t ino, - int version) +void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, + unsigned long nodeid, int version) { struct fuse_forget_in *inarg = &req->misc.forget_in; inarg->version = version; req->in.h.opcode = FUSE_FORGET; - req->in.h.ino = ino; + req->in.h.nodeid = nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_forget_in); req->in.args[0].value = inarg; @@ -107,15 +114,11 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, ino_t ino, static void fuse_clear_inode(struct inode *inode) { struct fuse_conn *fc = INO_FC(inode); - struct fuse_inode *fi = INO_FI(inode); - if (fi) { - if (fc) { - fuse_send_forget(fc, fi->forget_req, inode->i_ino, - inode->i_version); - fi->forget_req = NULL; - } - fuse_inode_free(fi); + if (fc) { + struct fuse_inode *fi = INO_FI(inode); + fuse_send_forget(fc, fi->forget_req, fi->nodeid, inode->i_version); + fi->forget_req = NULL; } } @@ -330,6 +333,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned int mode) memset(&attr, 0, sizeof(attr)); attr.mode = mode; + attr.ino = FUSE_ROOT_ID; return fuse_iget(sb, 1, 0, &attr, 0); } @@ -366,6 +370,8 @@ static struct export_operations fuse_export_operations = { #endif static struct super_operations fuse_super_operations = { + .alloc_inode = fuse_alloc_inode, + .destroy_inode = fuse_destroy_inode, .read_inode = fuse_read_inode, .clear_inode = fuse_clear_inode, .put_super = fuse_put_super, @@ -469,6 +475,17 @@ static struct super_block *fuse_read_super_compat(struct super_block *sb, static DECLARE_FSTYPE(fuse_fs_type, "fuse", fuse_read_super_compat, 0); #endif +static void fuse_inode_init_once(void * foo, kmem_cache_t * cachep, + unsigned long flags) +{ + struct inode * inode = (struct inode *) foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) + inode_init_once(inode); +} + + int fuse_fs_init() { int err; @@ -478,8 +495,9 @@ int fuse_fs_init() printk("fuse: failed to register filesystem\n"); else { fuse_inode_cachep = kmem_cache_create("fuse_inode", - sizeof(struct fuse_inode), - 0, 0, NULL, NULL); + sizeof(struct inode) + sizeof(struct fuse_inode) , + 0, SLAB_HWCACHE_ALIGN, + fuse_inode_init_once, NULL); if (!fuse_inode_cachep) { unregister_filesystem(&fuse_fs_type); err = -ENOMEM; |