ext4: avoid updating the superblock on a r/o mount if not needed
This was noticed by a user who noticied that the mtime of a file backing a loopback device was getting bumped when the loopback device is mounted read/only. Note: This doesn't show up when doing a loopback mount of a file directly, via "mount -o ro /tmp/foo.img /mnt", since the loop device is set read-only when mount automatically creates loop device. However, this is noticeable for a LUKS loop device like this: % cryptsetup luksOpen /tmp/foo.img test % mount -o ro /dev/loop0 /mnt ; umount /mnt or, if LUKS is not in use, if the user manually creates the loop device like this: % losetup /dev/loop0 /tmp/foo.img % mount -o ro /dev/loop0 /mnt ; umount /mnt The modified mtime causes rsync to do a rolling checksum scan of the file on the local and remote side, incrementally increasing the time to rsync the not-modified-but-touched image file. Fixes: eee00237fa5e ("ext4: commit super block if fs record error when journal record without error") Cc: stable@kernel.org Link: https://lore.kernel.org/r/ZIauBR7YiV3rVAHL@glitch Reported-by: Sean Greenslade <sean@seangreenslade.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
31464ab01f
commit
2ef6c32a91
@ -5997,19 +5997,27 @@ static int ext4_load_journal(struct super_block *sb,
|
||||
err = jbd2_journal_wipe(journal, !really_read_only);
|
||||
if (!err) {
|
||||
char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL);
|
||||
__le16 orig_state;
|
||||
bool changed = false;
|
||||
|
||||
if (save)
|
||||
memcpy(save, ((char *) es) +
|
||||
EXT4_S_ERR_START, EXT4_S_ERR_LEN);
|
||||
err = jbd2_journal_load(journal);
|
||||
if (save)
|
||||
if (save && memcmp(((char *) es) + EXT4_S_ERR_START,
|
||||
save, EXT4_S_ERR_LEN)) {
|
||||
memcpy(((char *) es) + EXT4_S_ERR_START,
|
||||
save, EXT4_S_ERR_LEN);
|
||||
changed = true;
|
||||
}
|
||||
kfree(save);
|
||||
orig_state = es->s_state;
|
||||
es->s_state |= cpu_to_le16(EXT4_SB(sb)->s_mount_state &
|
||||
EXT4_ERROR_FS);
|
||||
if (orig_state != es->s_state)
|
||||
changed = true;
|
||||
/* Write out restored error information to the superblock */
|
||||
if (!bdev_read_only(sb->s_bdev)) {
|
||||
if (changed && !really_read_only) {
|
||||
int err2;
|
||||
err2 = ext4_commit_super(sb);
|
||||
err = err ? : err2;
|
||||
|
Loading…
x
Reference in New Issue
Block a user