aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2004-11-02 17:32:03 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2004-11-02 17:32:03 +0000
commita13d90020721d30c3ac03b4e6905aa54cab1aed7 (patch)
tree7a919bf696f6fedbca5177bec5451894d5f81433 /kernel
parent874e3c166213a1dec3d191f78adc87b156c3f6e8 (diff)
added support for setting the st_ino field
Diffstat (limited to 'kernel')
-rw-r--r--kernel/dev.c24
-rw-r--r--kernel/dir.c168
-rw-r--r--kernel/file.c24
-rw-r--r--kernel/fuse_i.h18
-rw-r--r--kernel/inode.c74
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;