ufs: NFS support
[safe/jmp/linux-2.6] / fs / ufs / super.c
index 6560dda..143c20b 100644 (file)
@@ -66,6 +66,7 @@
  */
 
 
+#include <linux/exportfs.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
 
 #include "swab.h"
 #include "util.h"
 
+static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation)
+{
+       struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+       struct inode *inode;
+
+       if (ino < UFS_ROOTINO || ino > uspi->s_ncg * uspi->s_ipg)
+               return ERR_PTR(-ESTALE);
+
+       inode = ufs_iget(sb, ino);
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
+       if (generation && inode->i_generation != generation) {
+               iput(inode);
+               return ERR_PTR(-ESTALE);
+       }
+       return inode;
+}
+
+static struct dentry *ufs_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, ufs_nfs_get_inode);
+}
+
+static struct dentry *ufs_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, ufs_nfs_get_inode);
+}
+
+static struct dentry *ufs_get_parent(struct dentry *child)
+{
+       struct qstr dot_dot = {
+               .name   = "..",
+               .len    = 2,
+       };
+       ino_t ino;
+
+       ino = ufs_inode_by_name(child->d_inode, &dot_dot);
+       if (!ino)
+               return ERR_PTR(-ENOENT);
+       return d_obtain_alias(ufs_iget(child->d_inode->i_sb, ino));
+}
+
+static const struct export_operations ufs_export_ops = {
+       .fh_to_dentry   = ufs_fh_to_dentry,
+       .fh_to_parent   = ufs_fh_to_parent,
+       .get_parent     = ufs_get_parent,
+};
+
 #ifdef CONFIG_UFS_DEBUG
 /*
  * Print contents of ufs_super_block, useful for debugging
@@ -990,6 +1041,7 @@ magic_found:
         * Read ufs_super_block into internal data structures
         */
        sb->s_op = &ufs_super_ops;
+       sb->s_export_op = &ufs_export_ops;
        sb->dq_op = NULL; /***/
        sb->s_magic = fs32_to_cpu(sb, usb3->fs_magic);
 
@@ -1125,7 +1177,7 @@ failed_nomem:
        return -ENOMEM;
 }
 
-static void ufs_write_super(struct super_block *sb)
+static int ufs_sync_fs(struct super_block *sb, int wait)
 {
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
@@ -1134,25 +1186,36 @@ static void ufs_write_super(struct super_block *sb)
 
        lock_super(sb);
        lock_kernel();
+
        UFSD("ENTER\n");
+
        flags = UFS_SB(sb)->s_flags;
        uspi = UFS_SB(sb)->s_uspi;
        usb1 = ubh_get_usb_first(uspi);
        usb3 = ubh_get_usb_third(uspi);
 
-       if (!(sb->s_flags & MS_RDONLY)) {
-               usb1->fs_time = cpu_to_fs32(sb, get_seconds());
-               if ((flags & UFS_ST_MASK) == UFS_ST_SUN 
-                 || (flags & UFS_ST_MASK) == UFS_ST_SUNOS
-                 || (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
-                       ufs_set_fs_state(sb, usb1, usb3,
-                                       UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
-               ufs_put_cstotal(sb);
-       }
+       usb1->fs_time = cpu_to_fs32(sb, get_seconds());
+       if ((flags & UFS_ST_MASK) == UFS_ST_SUN  ||
+           (flags & UFS_ST_MASK) == UFS_ST_SUNOS ||
+           (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+               ufs_set_fs_state(sb, usb1, usb3,
+                               UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
+       ufs_put_cstotal(sb);
        sb->s_dirt = 0;
+
        UFSD("EXIT\n");
        unlock_kernel();
        unlock_super(sb);
+
+       return 0;
+}
+
+static void ufs_write_super(struct super_block *sb)
+{
+       if (!(sb->s_flags & MS_RDONLY))
+               ufs_sync_fs(sb, 1);
+       else
+               sb->s_dirt = 0;
 }
 
 static void ufs_put_super(struct super_block *sb)
@@ -1381,6 +1444,7 @@ static const struct super_operations ufs_super_ops = {
        .delete_inode   = ufs_delete_inode,
        .put_super      = ufs_put_super,
        .write_super    = ufs_write_super,
+       .sync_fs        = ufs_sync_fs,
        .statfs         = ufs_statfs,
        .remount_fs     = ufs_remount,
        .show_options   = ufs_show_options,