From: Tao Ma <boyu.mt@xxxxxxxxxx> In commit 353eb83c we removes i_state_flags with 64-bit longs, But in case we call EXT4_IOC_SETFLAGS, we fail to save the high 32-bit state flags and only stores the low 32-bit back to ei->i_flags. So the state flags are missing now in 64-bit long architecture. Cc: "Theodore Ts'o" <tytso@xxxxxxx> Cc: stable <stable@xxxxxxxxxxxxxxx> Signed-off-by: Tao Ma <boyu.mt@xxxxxxxxxx> --- fs/ext4/ext4.h | 21 +++++++++++++++++++++ fs/ext4/ioctl.c | 3 +++ 2 files changed, 24 insertions(+), 0 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ebec24a..855ddba 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1345,6 +1345,16 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) { (ei)->i_state_flags = 0; } + +static inline unsigned long ext4_save_state_flags(struct ext4_inode_info *ei) +{ + return (ei)->i_state_flags; +} + +static inline void ext4_restore_state_flags(struct ext4_inode_info *ei, + unsigned long state) +{ +} #else EXT4_INODE_BIT_FNS(state, flags, 32) @@ -1352,6 +1362,17 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) { /* We depend on the fact that callers will set i_flags */ } + +static inline unsigned long ext4_save_state_flags(struct ext4_inode_info *ei) +{ + return (ei)->i_flags >> 32; +} + +static inline void ext4_restore_state_flags(struct ext4_inode_info *ei, + unsigned long state) +{ + (ei)->i_flags |= state << 32; +} #endif #else /* Assume that user mode programs are passing in an ext4fs superblock, not diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 6eee255..a2cc254 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -40,6 +40,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct ext4_iloc iloc; unsigned int oldflags; unsigned int jflag; + unsigned long state_flags; if (!inode_owner_or_capable(inode)) return -EACCES; @@ -60,6 +61,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto flags_out; oldflags = ei->i_flags; + state_flags = ext4_save_state_flags(ei); /* The JOURNAL_DATA flag is modifiable only by root */ jflag = flags & EXT4_JOURNAL_DATA_FL; @@ -118,6 +120,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) flags = flags & EXT4_FL_USER_MODIFIABLE; flags |= oldflags & ~EXT4_FL_USER_MODIFIABLE; ei->i_flags = flags; + ext4_restore_state_flags(ei, state_flags); ext4_set_inode_flags(inode); inode->i_ctime = ext4_current_time(inode); -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html