diff mbox

ext4: don't call ext4_should_journal_data() on the journal inode

Message ID 1467495762-25353-1-git-send-email-vegard.nossum@oracle.com
State Awaiting Upstream, archived
Headers show

Commit Message

Vegard Nossum July 2, 2016, 9:42 p.m. UTC
Certain combinations of mount options in the superblock will cause
set_journal_csum_feature_set() in ext4_fill_super() to fail after the
journal has been created. When iput() is called on the journal inode,
we will hit the BUG() in ext4_should_journal_data(). We can prevent
this by only calling ext4_should_journal_data() if we already know
that it's not the journal inode.

Fixes: 2d859db3e4 ("ext4: fix data corruption in inodes with journalled data")
Fixes: 2b405bfa84 ("ext4: fix data=journal fast mount/umount hang")
Cc: Jan Kara <jack@suse.cz>
Cc: stable@vger.kernel.org
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
---
 fs/ext4/inode.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Comments

Theodore Ts'o July 3, 2016, 5:15 a.m. UTC | #1
On Sat, Jul 02, 2016 at 11:42:42PM +0200, Vegard Nossum wrote:
> Certain combinations of mount options in the superblock will cause
> set_journal_csum_feature_set() in ext4_fill_super() to fail after the
> journal has been created. When iput() is called on the journal inode,
> we will hit the BUG() in ext4_should_journal_data(). We can prevent
> this by only calling ext4_should_journal_data() if we already know
> that it's not the journal inode.

Which mount options?  Can you please give a reproducer?

      	    	      	      	     - Ted
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vegard Nossum July 3, 2016, 7:05 a.m. UTC | #2
On 07/03/2016 07:15 AM, Theodore Ts'o wrote:
> On Sat, Jul 02, 2016 at 11:42:42PM +0200, Vegard Nossum wrote:
>> Certain combinations of mount options in the superblock will cause
>> set_journal_csum_feature_set() in ext4_fill_super() to fail after the
>> journal has been created. When iput() is called on the journal inode,
>> we will hit the BUG() in ext4_should_journal_data(). We can prevent
>> this by only calling ext4_should_journal_data() if we already know
>> that it's not the journal inode.
>
> Which mount options?  Can you please give a reproducer?

Unfortunately I can't share the reproducer, but...
s->mount_opt = 0xa882c020, which seems like it is:

EXT4_MOUNT_ERRORS_RO
EXT4_MOUNT_XATTR_USER
EXT4_MOUNT_POSIX_ACL
EXT4_MOUNT_BARRIER
EXT4_MOUNT_JOURNAL_CHECKSUM
EXT4_MOUNT_DELALLOC
EXT4_MOUNT_BLOCK_VALIDITY
EXT4_MOUNT_INIT_INODE_TABLE

At mount time, this ends up calling

jbd2_journal_clear_features(JBD2_FEATURE_COMPAT_CHECKSUM, 0, 
JBD2_FEATURE_INCOMPAT_CSUM_V3 | JBD2_FEATURE_INCOMPAT_CSUM_V2)
jbd2_journal_set_features(0, 0, JBD2_FEATURE_INCOMPAT_CSUM_V3) = 0 // fails
jbd2_journal_clear_features(0x0, 0x0, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)

The reason the set_features() call ends up calling is because
journal->j_format_version == 1.

Maybe the "mount options" thing was a bit misleading and we should
rather say "Certain combinations of mount options
(EXT4_MOUNT_JOURNAL_CHECKSUM), journal format (v1), and superblock
features (EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) [...]" in the changelog.

Does that make more sense?

Hope this helps,


Vegard
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jan Kara July 4, 2016, 8:08 a.m. UTC | #3
On Sat 02-07-16 23:42:42, Vegard Nossum wrote:
> Certain combinations of mount options in the superblock will cause
> set_journal_csum_feature_set() in ext4_fill_super() to fail after the
> journal has been created. When iput() is called on the journal inode,
> we will hit the BUG() in ext4_should_journal_data(). We can prevent
> this by only calling ext4_should_journal_data() if we already know
> that it's not the journal inode.
> 
> Fixes: 2d859db3e4 ("ext4: fix data corruption in inodes with journalled data")
> Fixes: 2b405bfa84 ("ext4: fix data=journal fast mount/umount hang")
> Cc: Jan Kara <jack@suse.cz>
> Cc: stable@vger.kernel.org
> Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>

The patch looks good. You can add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/ext4/inode.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 91b66db..2591236 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -207,9 +207,9 @@ void ext4_evict_inode(struct inode *inode)
>  		 * Note that directories do not have this problem because they
>  		 * don't use page cache.
>  		 */
> -		if (ext4_should_journal_data(inode) &&
> -		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode)) &&
> -		    inode->i_ino != EXT4_JOURNAL_INO) {
> +		if (inode->i_ino != EXT4_JOURNAL_INO &&
> +		    ext4_should_journal_data(inode) &&
> +		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
>  			journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
>  			tid_t commit_tid = EXT4_I(inode)->i_datasync_tid;
>  
> -- 
> 1.9.1
>
Theodore Ts'o July 4, 2016, 3:02 p.m. UTC | #4
Thanks, I've reworded the commit description as follows:

  ext4: don't call ext4_should_journal_data() on the journal inode
  
  If ext4_fill_super() fails early, it's possible for
  ext4_evict_inode() to call ext4_should_journal_data() before
  superblock options and flags are fully set up.  In that case, the
  iput() on the journal inode can end up causing a BUG().
  
  Work around this problem by reordering the tests so we only call
  ext4_should_journal_data() after we know it's not the journal inode.
  
  Fixes: 2d859db3e4 ("ext4: fix data corruption in inodes with journalled data")
  Fixes: 2b405bfa84 ("ext4: fix data=journal fast mount/umount hang")
  Cc: Jan Kara <jack@suse.cz>
  Cc: stable@vger.kernel.org
  Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
  Signed-off-by: Theodore Ts'o <tytso@mit.edu>
  Reviewed-by: Jan Kara <jack@suse.cz>


--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 91b66db..2591236 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -207,9 +207,9 @@  void ext4_evict_inode(struct inode *inode)
 		 * Note that directories do not have this problem because they
 		 * don't use page cache.
 		 */
-		if (ext4_should_journal_data(inode) &&
-		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode)) &&
-		    inode->i_ino != EXT4_JOURNAL_INO) {
+		if (inode->i_ino != EXT4_JOURNAL_INO &&
+		    ext4_should_journal_data(inode) &&
+		    (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
 			journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
 			tid_t commit_tid = EXT4_I(inode)->i_datasync_tid;