[JFFS2] Reinstate NFS exportability
authorDavid Woodhouse <David.Woodhouse@intel.com>
Thu, 31 Jul 2008 19:39:25 +0000 (20:39 +0100)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 23 Oct 2008 09:13:07 +0000 (05:13 -0400)
Now that the readdir/lookup deadlock issues have been dealt with, we can
export JFFS2 file systems again.

(For now, you have to specify fsid manually; we should add a method to
the export_ops to handle that too.)

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/jffs2/super.c

index efd4012..4c4e18c 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/mtd/super.h>
 #include <linux/ctype.h>
 #include <linux/namei.h>
+#include <linux/exportfs.h>
 #include "compr.h"
 #include "nodelist.h"
 
@@ -62,6 +63,52 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
        return 0;
 }
 
+static struct inode *jffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
+                                        uint32_t generation)
+{
+       /* We don't care about i_generation. We'll destroy the flash
+          before we start re-using inode numbers anyway. And even
+          if that wasn't true, we'd have other problems...*/
+       return jffs2_iget(sb, ino);
+}
+
+static struct dentry *jffs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
+                                        int fh_len, int fh_type)
+{
+        return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+                                    jffs2_nfs_get_inode);
+}
+
+static struct dentry *jffs2_fh_to_parent(struct super_block *sb, struct fid *fid,
+                                        int fh_len, int fh_type)
+{
+        return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+                                    jffs2_nfs_get_inode);
+}
+
+static struct dentry *jffs2_get_parent(struct dentry *child)
+{
+       struct jffs2_inode_info *f;
+       uint32_t pino;
+
+       BUG_ON(!S_ISDIR(child->d_inode->i_mode));
+
+       f = JFFS2_INODE_INFO(child->d_inode);
+
+       pino = f->inocache->pino_nlink;
+
+       JFFS2_DEBUG("Parent of directory ino #%u is #%u\n",
+                   f->inocache->ino, pino);
+
+       return d_obtain_alias(jffs2_iget(child->d_inode->i_sb, pino));
+}
+
+static struct export_operations jffs2_export_ops = {
+       .get_parent = jffs2_get_parent,
+       .fh_to_dentry = jffs2_fh_to_dentry,
+       .fh_to_parent = jffs2_fh_to_parent,
+};
+
 static const struct super_operations jffs2_super_operations =
 {
        .alloc_inode =  jffs2_alloc_inode,
@@ -104,6 +151,7 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
        spin_lock_init(&c->inocache_lock);
 
        sb->s_op = &jffs2_super_operations;
+       sb->s_export_op = &jffs2_export_ops;
        sb->s_flags = sb->s_flags | MS_NOATIME;
        sb->s_xattr = jffs2_xattr_handlers;
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL