summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2007-12-12 18:59:44 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2007-12-12 18:59:44 +0000
commit2429afb7f70da6706d65a06a34c4503daf151067 (patch)
treecf86f83d35a4b961f16a3fdb2e6a6a7881931782
parent5e32023279d2a11e304dbb2310bf67b8950e91f5 (diff)
downloadfuse-2429afb7f70da6706d65a06a34c4503daf151067.tar.gz
Fix kernel module compile for 2.6.24
-rw-r--r--ChangeLog9
-rw-r--r--kernel/dir.c6
-rw-r--r--kernel/fuse_i.h5
-rw-r--r--kernel/inode.c133
4 files changed, 132 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index 3917511..ad4c8ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,13 @@
2007-12-12 Miklos Szeredi <miklos@szeredi.hu>
- * Released 2.7.2
+ * Fix kernel module compile for 2.6.24
-2007-12-12 Miklos Szeredi <miklos@szeredi.hu>
+ * Invalidate attributes of parent directory after create(), since
+ the modification time changes. Invalidate attributes on rename,
+ since some filesystems may update st_ctime. Reported by Szabolcs
+ Szakacsits
+
+ * Fix NFS exporting to handle 64bit node IDs
* Disable old symbol versions if __UCLIBC__ is defined. If a
symbol in a library has multiple versions, the runtime linker in
diff --git a/kernel/dir.c b/kernel/dir.c
index c5316d9..b1fe4c6 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -191,7 +191,7 @@ static int invalid_nodeid(u64 nodeid)
return !nodeid || nodeid == FUSE_ROOT_ID;
}
-static struct dentry_operations fuse_dentry_operations = {
+struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
};
@@ -378,6 +378,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
}
fuse_put_request(fc, forget_req);
d_instantiate(entry, inode);
+ fuse_invalidate_attr(dir);
fuse_change_timeout(entry, &outentry);
file = lookup_instantiate_filp(nd, entry, generic_file_open);
if (IS_ERR(file)) {
@@ -619,6 +620,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
err = req->out.h.error;
fuse_put_request(fc, req);
if (!err) {
+ /* ctime changes */
+ fuse_invalidate_attr(oldent->d_inode);
+
fuse_invalidate_attr(olddir);
if (olddir != newdir)
fuse_invalidate_attr(newdir);
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 3ea9a57..a43fc97 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -48,6 +48,9 @@
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
# define KERNEL_2_6_23_PLUS
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+# define KERNEL_2_6_24_PLUS
+#endif
#if defined(__arm__) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
#define DCACHE_BUG
@@ -647,3 +650,5 @@ int fuse_valid_type(int m);
* Is task allowed to perform filesystem operation?
*/
int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task);
+
+extern struct dentry_operations fuse_dentry_operations;
diff --git a/kernel/inode.c b/kernel/inode.c
index 8195f6e..0e5e213 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -520,21 +520,26 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
#ifdef HAVE_EXPORTFS_H
#include <linux/exportfs.h>
#endif
-static struct dentry *fuse_get_dentry(struct super_block *sb, void *vobjp)
+
+struct fuse_inode_handle
+{
+ u64 nodeid;
+ u32 generation;
+};
+
+static struct dentry *fuse_get_dentry(struct super_block *sb,
+ struct fuse_inode_handle *handle)
{
- __u32 *objp = vobjp;
- unsigned long nodeid = objp[0];
- __u32 generation = objp[1];
struct inode *inode;
struct dentry *entry;
- if (nodeid == 0)
+ if (handle->nodeid == 0)
return ERR_PTR(-ESTALE);
- inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid);
+ inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid);
if (!inode)
return ERR_PTR(-ESTALE);
- if (inode->i_generation != generation) {
+ if (inode->i_generation != handle->generation) {
iput(inode);
return ERR_PTR(-ESTALE);
}
@@ -544,43 +549,131 @@ static struct dentry *fuse_get_dentry(struct super_block *sb, void *vobjp)
iput(inode);
return ERR_PTR(-ENOMEM);
}
+ entry->d_op = &fuse_dentry_operations;
return entry;
}
-static int fuse_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
- int connectable)
+static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
+ int connectable)
{
struct inode *inode = dentry->d_inode;
int len = *max_len;
int type = 1;
+ u64 nodeid;
+ u32 generation;
+
+ if (len < 3 || (connectable && len < 6))
+ return 255;
+
+ nodeid = get_fuse_inode(inode)->nodeid;
+ generation = inode->i_generation;
- if (len < 2 || (connectable && len < 4))
- return 255;
+ len = 3;
+ fh[0] = (u32)(nodeid >> 32);
+ fh[1] = (u32)(nodeid & 0xffffffff);
+ fh[2] = generation;
- len = 2;
- fh[0] = get_fuse_inode(inode)->nodeid;
- fh[1] = inode->i_generation;
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
- fh[2] = get_fuse_inode(parent)->nodeid;
- fh[3] = parent->i_generation;
+ nodeid = get_fuse_inode(parent)->nodeid;
+ generation = parent->i_generation;
+
+ fh[3] = (u32)(nodeid >> 32);
+ fh[4] = (u32)(nodeid & 0xffffffff);
+ fh[5] = generation;
spin_unlock(&dentry->d_lock);
- len = 4;
+
+ len = 6;
type = 2;
}
+
*max_len = len;
return type;
}
+#ifdef KERNEL_2_6_24_PLUS
+static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
+{
+ struct fuse_inode_handle handle;
+
+ if (fh_len < 3 || fh_type > 2)
+ return NULL;
+
+ handle.nodeid = (u64) fid->raw[0] << 32;
+ handle.nodeid |= (u64) fid->raw[1];
+ handle.generation = fid->raw[2];
+ return fuse_get_dentry(sb, &handle);
+}
+
+static struct dentry *fuse_fh_to_parent(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type)
+{
+ struct fuse_inode_handle parent;
+
+ if (fh_type != 2 || fh_len < 6)
+ return NULL;
+
+ parent.nodeid = (u64) fid->raw[3] << 32;
+ parent.nodeid |= (u64) fid->raw[4];
+ parent.generation = fid->raw[5];
+ return fuse_get_dentry(sb, &parent);
+}
+
+
+static const struct export_operations fuse_export_operations = {
+ .fh_to_dentry = fuse_fh_to_dentry,
+ .fh_to_parent = fuse_fh_to_parent,
+ .encode_fh = fuse_encode_fh,
+};
+#else
+static struct dentry *fuse_get_dentry_old(struct super_block *sb, void *objp)
+{
+ return fuse_get_dentry(sb, objp);
+}
+
+static struct dentry *fuse_decode_fh(struct super_block *sb, u32 *fh,
+ int fh_len, int fileid_type,
+ int (*acceptable)(void *context, struct dentry *de),
+ void *context)
+{
+ struct fuse_inode_handle handle;
+ struct fuse_inode_handle parent;
+
+ if (fh_len < 3 || fileid_type > 2)
+ return NULL;
+
+ if (fileid_type == 2) {
+ if (fh_len < 6)
+ return NULL;
+
+ parent.nodeid = (u64) fh[3] << 32;
+ parent.nodeid |= (u64) fh[4];
+ parent.generation = fh[5];
+ } else {
+ parent.nodeid = 0;
+ parent.generation = 0;
+ }
+
+ handle.nodeid = (u64) fh[0] << 32;
+ handle.nodeid |= (u64) fh[1];
+ handle.generation = fh[2];
+
+ return ret = fuse_export_operations.
+ find_exported_dentry(sb, &handle, &parent, acceptable, context);
+}
+
static struct export_operations fuse_export_operations = {
- .get_dentry = fuse_get_dentry,
+ .get_dentry = fuse_get_dentry_old,
.encode_fh = fuse_encode_fh,
+ .decode_fh = fuse_decode_fh,
};
#endif
+#endif
static struct super_operations fuse_super_operations = {
.alloc_inode = fuse_alloc_inode,
@@ -845,8 +938,12 @@ static decl_subsys(fs, NULL, NULL);
static decl_subsys(fuse, NULL, NULL);
static decl_subsys(connections, NULL, NULL);
+#ifdef KERNEL_2_6_24_PLUS
+static void fuse_inode_init_once(struct kmem_cache *cachep, void *foo)
+#else
static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep,
unsigned long flags)
+#endif
{
struct inode * inode = foo;