From: viro@www.linux.org.uk

Similar fix for UFS; touching device node (and they have 32bit dev_t) ends
up killing upper 16 bits, which makes for very unhappy *BSD, since that
turns /dev/ad0s1 into alias of /dev/ad0.  Again, for now we store on-disk
value in private part of inode and use it instead of ->i_rdev in
->write_inode().



 fs/ufs/inode.c |   16 ++++++++--------
 fs/ufs/namei.c |    4 ++++
 2 files changed, 12 insertions(+), 8 deletions(-)

diff -puN fs/ufs/inode.c~large-dev_t-2nd-12 fs/ufs/inode.c
--- 25/fs/ufs/inode.c~large-dev_t-2nd-12	2003-09-05 00:50:10.000000000 -0700
+++ 25-akpm/fs/ufs/inode.c	2003-09-05 00:50:10.000000000 -0700
@@ -475,6 +475,7 @@ void ufs_read_inode (struct inode * inod
 	struct ufs_sb_private_info * uspi;
 	struct ufs_inode * ufs_inode;	
 	struct buffer_head * bh;
+	mode_t mode;
 	unsigned i;
 	unsigned flags;
 	
@@ -500,7 +501,7 @@ void ufs_read_inode (struct inode * inod
 	/*
 	 * Copy data to the in-core inode.
 	 */
-	inode->i_mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
+	inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
 	inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink);
 	if (inode->i_nlink == 0)
 		ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
@@ -527,9 +528,7 @@ void ufs_read_inode (struct inode * inod
 	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
 	ufsi->i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
 	
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		;
-	else if (inode->i_blocks) {
+	if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
 		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
 			ufsi->i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i];
 	}
@@ -555,7 +554,7 @@ void ufs_read_inode (struct inode * inod
 		}
 	} else
 		init_special_inode(inode, inode->i_mode,
-			fs32_to_cpu(sb, ufs_inode->ui_u2.ui_addr.ui_db[0]));
+			old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0])));
 
 	brelse (bh);
 
@@ -618,9 +617,10 @@ static int ufs_update_inode(struct inode
 		ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag);
 	}
 
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev);
-	else if (inode->i_blocks) {
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+		/* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */
+		ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0];
+	} else if (inode->i_blocks) {
 		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
 			ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.i_data[i];
 	}
diff -puN fs/ufs/namei.c~large-dev_t-2nd-12 fs/ufs/namei.c
--- 25/fs/ufs/namei.c~large-dev_t-2nd-12	2003-09-05 00:50:10.000000000 -0700
+++ 25-akpm/fs/ufs/namei.c	2003-09-05 00:50:10.000000000 -0700
@@ -29,6 +29,7 @@
 #include <linux/ufs_fs.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include "swab.h"	/* will go away - see comment in mknod() */
 
 #undef UFS_NAMEI_DEBUG
 
@@ -115,6 +116,9 @@ static int ufs_mknod (struct inode * dir
 	int err = PTR_ERR(inode);
 	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));
 		mark_inode_dirty(inode);
 		lock_kernel();
 		err = ufs_add_nondir(dentry, inode);

_