Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
[safe/jmp/linux-2.6] / fs / ufs / super.c
index 6560dda..ad9bc1e 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
@@ -867,6 +918,7 @@ again:
        sbi->s_bytesex = BYTESEX_LE;
        switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
                case UFS_MAGIC:
+               case UFS_MAGIC_BW:
                case UFS2_MAGIC:
                case UFS_MAGIC_LFN:
                case UFS_MAGIC_FEA:
@@ -876,6 +928,7 @@ again:
        sbi->s_bytesex = BYTESEX_BE;
        switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
                case UFS_MAGIC:
+               case UFS_MAGIC_BW:
                case UFS2_MAGIC:
                case UFS_MAGIC_LFN:
                case UFS_MAGIC_FEA:
@@ -965,6 +1018,9 @@ magic_found:
                case UFS_FSSTABLE:
                        UFSD("fs is stable\n");
                        break;
+               case UFS_FSLOG:
+                       UFSD("fs is logging fs\n");
+                       break;
                case UFS_FSOSF1:
                        UFSD("fs is DEC OSF/1\n");
                        break;
@@ -990,6 +1046,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 +1182,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 +1191,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)
@@ -1369,6 +1437,11 @@ static void destroy_inodecache(void)
        kmem_cache_destroy(ufs_inode_cachep);
 }
 
+static void ufs_clear_inode(struct inode *inode)
+{
+       dquot_drop(inode);
+}
+
 #ifdef CONFIG_QUOTA
 static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t);
 static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t);
@@ -1379,8 +1452,10 @@ static const struct super_operations ufs_super_ops = {
        .destroy_inode  = ufs_destroy_inode,
        .write_inode    = ufs_write_inode,
        .delete_inode   = ufs_delete_inode,
+       .clear_inode    = ufs_clear_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,