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); _