Commit 216114b9 authored by Theodore Y. Ts'o's avatar Theodore Y. Ts'o Committed by Linus Torvalds

Ext2/3 forward compatibility: inode size

This patch allows filesystems with expanded inodes to be mounted.
(compatibility feature flags will be used to control whether or not the
filesystem should be mounted in case the new inode fields will result in
compatibility issues).  This allows for future compatibility with newer
versions of ext2fs.
parent 1142d28b
...@@ -10,6 +10,7 @@ struct ext2_inode_info { ...@@ -10,6 +10,7 @@ struct ext2_inode_info {
__u32 i_faddr; __u32 i_faddr;
__u8 i_frag_no; __u8 i_frag_no;
__u8 i_frag_size; __u8 i_frag_size;
__u16 i_state;
__u32 i_file_acl; __u32 i_file_acl;
__u32 i_dir_acl; __u32 i_dir_acl;
__u32 i_dtime; __u32 i_dtime;
...@@ -23,6 +24,12 @@ struct ext2_inode_info { ...@@ -23,6 +24,12 @@ struct ext2_inode_info {
struct inode vfs_inode; struct inode vfs_inode;
}; };
/*
* Inode dynamic state flags
*/
#define EXT2_STATE_NEW 0x00000001 /* inode is newly created */
/* /*
* Function prototypes * Function prototypes
*/ */
......
...@@ -386,6 +386,7 @@ struct inode * ext2_new_inode(struct inode * dir, int mode) ...@@ -386,6 +386,7 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
ei->i_prealloc_block = 0; ei->i_prealloc_block = 0;
ei->i_prealloc_count = 0; ei->i_prealloc_count = 0;
ei->i_dir_start_lookup = 0; ei->i_dir_start_lookup = 0;
ei->i_state = EXT2_STATE_NEW;
if (ei->i_flags & EXT2_SYNC_FL) if (ei->i_flags & EXT2_SYNC_FL)
inode->i_flags |= S_SYNC; inode->i_flags |= S_SYNC;
if (ei->i_flags & EXT2_DIRSYNC_FL) if (ei->i_flags & EXT2_DIRSYNC_FL)
......
...@@ -1012,6 +1012,7 @@ void ext2_read_inode (struct inode * inode) ...@@ -1012,6 +1012,7 @@ void ext2_read_inode (struct inode * inode)
ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
ei->i_dtime = 0; ei->i_dtime = 0;
inode->i_generation = le32_to_cpu(raw_inode->i_generation); inode->i_generation = le32_to_cpu(raw_inode->i_generation);
ei->i_state = 0;
ei->i_next_alloc_block = 0; ei->i_next_alloc_block = 0;
ei->i_next_alloc_goal = 0; ei->i_next_alloc_goal = 0;
ei->i_prealloc_count = 0; ei->i_prealloc_count = 0;
...@@ -1076,6 +1077,11 @@ static int ext2_update_inode(struct inode * inode, int do_sync) ...@@ -1076,6 +1077,11 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
if (IS_ERR(raw_inode)) if (IS_ERR(raw_inode))
return -EIO; return -EIO;
/* For fields not not tracking in the in-memory inode,
* initialise them to zero for new inodes. */
if (ei->i_state & EXT2_STATE_NEW)
memset(raw_inode, 0, EXT2_SB(sb)->s_inode_size);
if (ino == EXT2_ACL_IDX_INO || ino == EXT2_ACL_DATA_INO) { if (ino == EXT2_ACL_IDX_INO || ino == EXT2_ACL_DATA_INO) {
ext2_error (sb, "ext2_write_inode", "bad inode number: %lu", ext2_error (sb, "ext2_write_inode", "bad inode number: %lu",
(unsigned long) ino); (unsigned long) ino);
...@@ -1152,6 +1158,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync) ...@@ -1152,6 +1158,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
err = -EIO; err = -EIO;
} }
} }
ei->i_state &= ~EXT2_STATE_NEW;
brelse (bh); brelse (bh);
return err; return err;
} }
......
...@@ -630,7 +630,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) ...@@ -630,7 +630,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
} else { } else {
sbi->s_inode_size = le16_to_cpu(es->s_inode_size); sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
sbi->s_first_ino = le32_to_cpu(es->s_first_ino); sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
if (sbi->s_inode_size != EXT2_GOOD_OLD_INODE_SIZE) { if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) ||
(sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
(sbi->s_inode_size > blocksize)) {
printk ("EXT2-fs: unsupported inode size: %d\n", printk ("EXT2-fs: unsupported inode size: %d\n",
sbi->s_inode_size); sbi->s_inode_size);
goto failed_mount; goto failed_mount;
......
...@@ -2325,6 +2325,11 @@ static int ext3_do_update_inode(handle_t *handle, ...@@ -2325,6 +2325,11 @@ static int ext3_do_update_inode(handle_t *handle,
if (err) if (err)
goto out_brelse; goto out_brelse;
} }
/* For fields not not tracking in the in-memory inode,
* initialise them to zero for new inodes. */
if (ei->i_state & EXT3_STATE_NEW)
memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size);
raw_inode->i_mode = cpu_to_le16(inode->i_mode); raw_inode->i_mode = cpu_to_le16(inode->i_mode);
if(!(test_opt(inode->i_sb, NO_UID32))) { if(!(test_opt(inode->i_sb, NO_UID32))) {
raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
...@@ -2362,15 +2367,6 @@ static int ext3_do_update_inode(handle_t *handle, ...@@ -2362,15 +2367,6 @@ static int ext3_do_update_inode(handle_t *handle,
raw_inode->i_faddr = cpu_to_le32(ei->i_faddr); raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);
raw_inode->i_frag = ei->i_frag_no; raw_inode->i_frag = ei->i_frag_no;
raw_inode->i_fsize = ei->i_frag_size; raw_inode->i_fsize = ei->i_frag_size;
#else
/* If we are not tracking these fields in the in-memory inode,
* then preserve them on disk, but still initialise them to zero
* for new inodes. */
if (ei->i_state & EXT3_STATE_NEW) {
raw_inode->i_faddr = 0;
raw_inode->i_frag = 0;
raw_inode->i_fsize = 0;
}
#endif #endif
raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl); raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);
if (!S_ISREG(inode->i_mode)) { if (!S_ISREG(inode->i_mode)) {
......
...@@ -1109,7 +1109,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -1109,7 +1109,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
} else { } else {
sbi->s_inode_size = le16_to_cpu(es->s_inode_size); sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
sbi->s_first_ino = le32_to_cpu(es->s_first_ino); sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) { if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
(sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
(sbi->s_inode_size > blocksize)) {
printk (KERN_ERR printk (KERN_ERR
"EXT3-fs: unsupported inode size: %d\n", "EXT3-fs: unsupported inode size: %d\n",
sbi->s_inode_size); sbi->s_inode_size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment