Fix kernel module compile for 2.6.24
authorMiklos Szeredi <miklos@szeredi.hu>
Wed, 12 Dec 2007 18:59:44 +0000 (18:59 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Wed, 12 Dec 2007 18:59:44 +0000 (18:59 +0000)
ChangeLog
kernel/dir.c
kernel/fuse_i.h
kernel/inode.c

index 3917511495adf1d53b112a04fcb2e1237b372981..ad4c8efe2ad721ca82f5b97cbf169fd5064adea5 100644 (file)
--- 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
index c5316d9c1f09f725b214461878539591bb349931..b1fe4c6e98a351c220118948ea2c73322396bb87 100644 (file)
@@ -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);
index 3ea9a57f94b15bb1192ebff5ad06f22633ec1de7..a43fc974b0d4304bf4ece18e5e4b0ee8219efaa5 100644 (file)
@@ -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;
index 8195f6e9e486617d90e877432212203506aefcfc..0e5e21316d160087f5d9c2f0d47f566ba26064bf 100644 (file)
@@ -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;