| From 0f0ff9a9f3fa2ec6f427603fd521d5f3a0b076d1 Mon Sep 17 00:00:00 2001 |
| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Wed, 1 Jul 2015 23:37:46 -0400 |
| Subject: ext4: fix fencepost error in lazytime optimization |
| |
| From: Theodore Ts'o <tytso@mit.edu> |
| |
| commit 0f0ff9a9f3fa2ec6f427603fd521d5f3a0b076d1 upstream. |
| |
| Commit 8f4d8558391: "ext4: fix lazytime optimization" was not a |
| complete fix. In the case where the inode number is a multiple of 16, |
| and we could still end up updating an inode with dirty timestamps |
| written to the wrong inode on disk. Oops. |
| |
| This can be easily reproduced by using generic/005 with a file system |
| with metadata_csum and lazytime enabled. |
| |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/ext4/inode.c | 7 ++++++- |
| 1 file changed, 6 insertions(+), 1 deletion(-) |
| |
| --- a/fs/ext4/inode.c |
| +++ b/fs/ext4/inode.c |
| @@ -4360,7 +4360,12 @@ static void ext4_update_other_inodes_tim |
| int inode_size = EXT4_INODE_SIZE(sb); |
| |
| oi.orig_ino = orig_ino; |
| - ino = (orig_ino & ~(inodes_per_block - 1)) + 1; |
| + /* |
| + * Calculate the first inode in the inode table block. Inode |
| + * numbers are one-based. That is, the first inode in a block |
| + * (assuming 4k blocks and 256 byte inodes) is (n*16 + 1). |
| + */ |
| + ino = ((orig_ino - 1) & ~(inodes_per_block - 1)) + 1; |
| for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) { |
| if (ino == orig_ino) |
| continue; |