From: viro@www.linux.org.uk

Fix for JFS handling of device nodes; it has 32bit on-disk device numbers,
shoves them into 16bit (->i_rdev) when inode is read and writes them back
truncated when inode is written to disk.  For now (and 2.4 will have to do
the same permanently) we store the original value in private part of inode
and use it instead of ->i_rdev in ->write_inode(); mknod() sets it at the
same time as ->i_rdev.  It will become unnecessary when dev_t becomes wider
than 16 bits, but for now we need it.



 fs/jfs/jfs_imap.c   |    7 +++----
 fs/jfs/jfs_incore.h |    3 ++-
 fs/jfs/jfs_mount.c  |    2 +-
 fs/jfs/namei.c      |    3 +++
 4 files changed, 9 insertions(+), 6 deletions(-)

diff -puN fs/jfs/jfs_imap.c~large-dev_t-2nd-11 fs/jfs/jfs_imap.c
--- 25/fs/jfs/jfs_imap.c~large-dev_t-2nd-11	2003-09-05 00:50:09.000000000 -0700
+++ 25-akpm/fs/jfs/jfs_imap.c	2003-09-05 00:50:09.000000000 -0700
@@ -3041,9 +3041,10 @@ static int copy_from_dinode(struct dinod
 	jfs_ip->next_index = le32_to_cpu(dip->di_next_index);
 	jfs_ip->otime = le32_to_cpu(dip->di_otime.tv_sec);
 	jfs_ip->acltype = le32_to_cpu(dip->di_acltype);
+	jfs_ip->dev = le32_to_cpu(dip->di_rdev);
 
 	if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode))
-		ip->i_rdev = le32_to_cpu(dip->di_rdev);
+		ip->i_rdev = old_decode_dev(jfs_ip->dev);
 
 	if (S_ISDIR(ip->i_mode)) {
 		memcpy(&jfs_ip->i_dirtable, &dip->di_dirtable, 384);
@@ -3100,9 +3101,7 @@ static void copy_to_dinode(struct dinode
 	dip->di_otime.tv_sec = cpu_to_le32(jfs_ip->otime);
 	dip->di_otime.tv_nsec = 0;
 	dip->di_acltype = cpu_to_le32(jfs_ip->acltype);
-
-	if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode))
-		dip->di_rdev = cpu_to_le32(ip->i_rdev);
+	dip->di_rdev = cpu_to_le32(jfs_ip->dev);
 }
 
 #ifdef	_JFS_DEBUG_IMAP
diff -puN fs/jfs/jfs_incore.h~large-dev_t-2nd-11 fs/jfs/jfs_incore.h
--- 25/fs/jfs/jfs_incore.h~large-dev_t-2nd-11	2003-09-05 00:50:09.000000000 -0700
+++ 25-akpm/fs/jfs/jfs_incore.h	2003-09-05 00:50:09.000000000 -0700
@@ -93,6 +93,7 @@ struct jfs_inode_info {
 			unchar _inline_ea[128];	/* 128: inline extended attr */
 		} link;
 	} u;
+	u32 dev;	/* will die when we get wide dev_t */
 	struct inode	vfs_inode;
 };
 #define i_xtroot u.file._xtroot
@@ -143,7 +144,7 @@ struct jfs_sb_info {
 	short		nbperpage;	/* blocks per page		*/
 	short		l2nbperpage;	/* log2 blocks per page	*/
 	short		l2niperblk;	/* log2 inodes per page	*/
-	u32		logdev;		/* external log device	*/
+	dev_t		logdev;		/* external log device	*/
 	uint		aggregate;	/* volume identifier in log record */
 	pxd_t		logpxd;		/* pxd describing log	*/
 	pxd_t		fsckpxd;	/* pxd describing fsck wkspc */
diff -puN fs/jfs/jfs_mount.c~large-dev_t-2nd-11 fs/jfs/jfs_mount.c
--- 25/fs/jfs/jfs_mount.c~large-dev_t-2nd-11	2003-09-05 00:50:09.000000000 -0700
+++ 25-akpm/fs/jfs/jfs_mount.c	2003-09-05 00:50:09.000000000 -0700
@@ -395,7 +395,7 @@ static int chkSuper(struct super_block *
 	if (sbi->mntflag & JFS_INLINELOG)
 		sbi->logpxd = j_sb->s_logpxd;
 	else {
-		sbi->logdev = le32_to_cpu(j_sb->s_logdev);
+		sbi->logdev = old_decode_dev(le32_to_cpu(j_sb->s_logdev));
 		memcpy(sbi->uuid, j_sb->s_uuid, sizeof(sbi->uuid));
 		memcpy(sbi->loguuid, j_sb->s_loguuid, sizeof(sbi->uuid));
 	}
diff -puN fs/jfs/namei.c~large-dev_t-2nd-11 fs/jfs/namei.c
--- 25/fs/jfs/namei.c~large-dev_t-2nd-11	2003-09-05 00:50:09.000000000 -0700
+++ 25-akpm/fs/jfs/namei.c	2003-09-05 00:50:09.000000000 -0700
@@ -1302,6 +1302,7 @@ int jfs_rename(struct inode *old_dir, st
  */
 int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 {
+	struct jfs_inode_info *jfs_ip;
 	struct btstack btstack;
 	struct component_name dname;
 	ino_t ino;
@@ -1321,6 +1322,7 @@ int jfs_mknod(struct inode *dir, struct 
 		rc = -ENOSPC;
 		goto out1;
 	}
+	jfs_ip = JFS_IP(ip);
 
 	tid = txBegin(dir->i_sb, 0);
 
@@ -1339,6 +1341,7 @@ int jfs_mknod(struct inode *dir, struct 
 		goto out3;
 
 	ip->i_op = &jfs_file_inode_operations;
+	jfs_ip->dev = old_encode_dev(rdev);
 	init_special_inode(ip, ip->i_mode, rdev);
 
 	insert_inode_hash(ip);

_