From: Andries.Brouwer@cwi.nl

A not unreasonable construction is that where we use i_block[0] when it is
nonzero and i_block[1], i_block[2] when i_block[0] is zero.  (Or, more
generally, use i_block[0] unless it has a bit pattern, e.g.  -1, that says
i_block[1], i_block[2] must be used.)

This is stable for going back and forth between old and new kernels as long
as we agree that 0,0 (the agreed bit pattern) is no device.  It makes no
assumptions on old kernels.  I have not checked how e2fsck would react.  The
only incompatibility would be device nodes that used to have 0,0 and now have
undefined value.



 25-akpm/fs/ext2/inode.c |   31 +++++++++++++++++++++++++------
 1 files changed, 25 insertions(+), 6 deletions(-)

diff -puN fs/ext2/inode.c~ext2-64-bit-special-inodes fs/ext2/inode.c
--- 25/fs/ext2/inode.c~ext2-64-bit-special-inodes	Thu Apr 17 15:44:33 2003
+++ 25-akpm/fs/ext2/inode.c	Thu Apr 17 15:53:25 2003
@@ -1125,9 +1125,16 @@ void ext2_read_inode (struct inode * ino
 				inode->i_mapping->a_ops = &ext2_aops;
 		}
 	} else {
+		dev_t devno = le32_to_cpu(raw_inode->i_block[0]);
+
+		if (devno == 0) {
+			unsigned int lo = le32_to_cpu(raw_inode->i_block[1]);
+			unsigned int hi = le32_to_cpu(raw_inode->i_block[2]);
+
+			devno = ((unsigned long long) hi << 32) | lo;
+		}
 		inode->i_op = &ext2_special_inode_operations;
-		init_special_inode(inode, inode->i_mode,
-				   le32_to_cpu(raw_inode->i_block[0]));
+		init_special_inode(inode, inode->i_mode, devno);
 	}
 	brelse (bh);
 	ext2_set_inode_flags(inode);
@@ -1215,10 +1222,22 @@ static int ext2_update_inode(struct inod
 	}
 	
 	raw_inode->i_generation = cpu_to_le32(inode->i_generation);
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
-	else for (n = 0; n < EXT2_N_BLOCKS; n++)
-		raw_inode->i_block[n] = ei->i_data[n];
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+		dev_t devno = kdev_t_to_nr(inode->i_rdev);
+		unsigned int hi = (sizeof(dev_t) > 4) ? (devno >> 32) : 0;
+		unsigned int lo = (devno & 0xffffffff);
+
+		if (hi == 0 && lo != 0) {
+			raw_inode->i_block[0] = cpu_to_le32(lo);
+		} else {
+			raw_inode->i_block[0] = 0;
+			raw_inode->i_block[1] = cpu_to_le32(lo);
+			raw_inode->i_block[2] = cpu_to_le32(hi);
+		}
+	} else {
+		for (n = 0; n < EXT2_N_BLOCKS; n++)
+			raw_inode->i_block[n] = ei->i_data[n];
+	}
 	mark_buffer_dirty(bh);
 	if (do_sync) {
 		sync_dirty_buffer(bh);

_