
From: Alex Kiernan <alex.kiernan@gmail.com>

Fix handling of device inodes on Solaris x86 filesystems, add support for
large dev_t against Solaris UFS filesystems.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/ufs/inode.c |    4 +--
 25-akpm/fs/ufs/namei.c |    4 +--
 25-akpm/fs/ufs/util.c  |   53 +++++++++++++++++++++++++++++++++++++++++++++++++
 25-akpm/fs/ufs/util.h  |    2 +
 4 files changed, 59 insertions(+), 4 deletions(-)

diff -puN fs/ufs/inode.c~solaris-ufs-fix fs/ufs/inode.c
--- 25/fs/ufs/inode.c~solaris-ufs-fix	Wed Oct 20 15:05:00 2004
+++ 25-akpm/fs/ufs/inode.c	Wed Oct 20 15:05:00 2004
@@ -629,7 +629,7 @@ void ufs_read_inode (struct inode * inod
 		}
 	} else
 		init_special_inode(inode, inode->i_mode,
-			old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0])));
+			ufs_get_inode_dev(sb, ufsi));
 
 	brelse (bh);
 
@@ -705,7 +705,7 @@ ufs2_inode :
 		}
 	} else   /* TODO  : here ...*/
 		init_special_inode(inode, inode->i_mode,
-			old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0])));
+			ufs_get_inode_dev(sb, ufsi));
 
 	brelse(bh);
 
diff -puN fs/ufs/namei.c~solaris-ufs-fix fs/ufs/namei.c
--- 25/fs/ufs/namei.c~solaris-ufs-fix	Wed Oct 20 15:05:00 2004
+++ 25-akpm/fs/ufs/namei.c	Wed Oct 20 15:05:00 2004
@@ -30,6 +30,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include "swab.h"	/* will go away - see comment in mknod() */
+#include "util.h"
 
 /*
 #undef UFS_NAMEI_DEBUG
@@ -125,8 +126,7 @@ static int ufs_mknod (struct inode * dir
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, mode, rdev);
 		/* NOTE: that'll go when we get wide dev_t */
-		UFS_I(inode)->i_u1.i_data[0] = cpu_to_fs32(inode->i_sb,
-							old_encode_dev(rdev));
+		ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
 		mark_inode_dirty(inode);
 		lock_kernel();
 		err = ufs_add_nondir(dentry, inode);
diff -puN fs/ufs/util.c~solaris-ufs-fix fs/ufs/util.c
--- 25/fs/ufs/util.c~solaris-ufs-fix	Wed Oct 20 15:05:00 2004
+++ 25-akpm/fs/ufs/util.c	Wed Oct 20 15:05:00 2004
@@ -202,3 +202,56 @@ void _ubh_memcpyubh_(struct ufs_sb_priva
 		bhno++;
 	}
 }
+
+dev_t
+ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi)
+{
+	__fs32 fs32;
+	dev_t dev;
+
+	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+		fs32 = ufsi->i_u1.i_data[1];
+	else
+		fs32 = ufsi->i_u1.i_data[0];
+	fs32 = fs32_to_cpu(sb, fs32);
+	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+	case UFS_ST_SUNx86:
+	case UFS_ST_SUN:
+		if ((fs32 & 0xffff0000) == 0 ||
+		    (fs32 & 0xffff0000) == 0xffff0000)
+			dev = old_decode_dev(fs32 & 0x7fff);
+		else
+			dev = MKDEV(sysv_major(fs32), sysv_minor(fs32));
+		break;
+
+	default:
+		dev = old_decode_dev(fs32);
+		break;
+	}
+	return dev;
+}
+
+void
+ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev)
+{
+	__fs32 fs32;
+
+	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+	case UFS_ST_SUNx86:
+	case UFS_ST_SUN:
+		fs32 = sysv_encode_dev(dev);
+		if ((fs32 & 0xffff8000) == 0) {
+			fs32 = old_encode_dev(dev);
+		}
+		break;
+
+	default:
+		fs32 = old_encode_dev(dev);
+		break;
+	}
+	fs32 = cpu_to_fs32(sb, fs32);
+	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+		ufsi->i_u1.i_data[1] = fs32;
+	else
+		ufsi->i_u1.i_data[0] = fs32;
+}
diff -puN fs/ufs/util.h~solaris-ufs-fix fs/ufs/util.h
--- 25/fs/ufs/util.h~solaris-ufs-fix	Wed Oct 20 15:05:00 2004
+++ 25-akpm/fs/ufs/util.h	Wed Oct 20 15:05:00 2004
@@ -223,6 +223,8 @@ ufs_set_inode_gid(struct super_block *sb
 	inode->ui_u1.oldids.ui_sgid =  cpu_to_fs16(sb, value);
 }
 
+extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *);
+extern void ufs_set_inode_dev(struct super_block *, struct ufs_inode_info *, dev_t);
 
 /*
  * These functions manipulate ufs buffers
_
