Skip to content

Commit

Permalink
ext2/xip: refuse to change xip flag during remount with busy inodes
Browse files Browse the repository at this point in the history
For a reason that I was unable to understand in three months of debugging,
mount ext2 -o remount stopped working properly when remounting from
regular operation to xip, or the other way around.  According to a git
bisect search, the problem was introduced with the VM_MIXEDMAP/PTE_SPECIAL
rework in the vm:

commit 70688e4
Author: Nick Piggin <[email protected]>
Date:   Mon Apr 28 02:13:02 2008 -0700

    xip: support non-struct page backed memory

In the failing scenario, the filesystem is mounted read only via root=
kernel parameter on s390x.  During remount (in rc.sysinit), the inodes of
the bash binary and its libraries are busy and cannot be invalidated (the
bash which is running rc.sysinit resides on subject filesystem).
Afterwards, another bash process (running ifup-eth) recurses into a
subshell, runs dup_mm (via fork).  Some of the mappings in this bash
process were created from inodes that could not be invalidated during
remount.

Both parent and child process crash some time later due to inconsistencies
in their address spaces.  The issue seems to be timing sensitive, various
attempts to recreate it have failed.

This patch refuses to change the xip flag during remount in case some
inodes cannot be invalidated.  This patch keeps users from running into
that issue.

[[email protected]: cleanup]
Signed-off-by: Carsten Otte <[email protected]>
Cc: Nick Piggin <[email protected]>
Cc: Jared Hulbert <[email protected]>
Cc: Martin Schwidefsky <[email protected]>
Cc: Heiko Carstens <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Carsten Otte authored and torvalds committed Feb 11, 2009
1 parent cfebe56 commit 0e4a9b5
Showing 1 changed file with 6 additions and 3 deletions.
9 changes: 6 additions & 3 deletions fs/ext2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1185,9 +1185,12 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
es = sbi->s_es;
if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
(old_mount_opt & EXT2_MOUNT_XIP)) &&
invalidate_inodes(sb))
ext2_warning(sb, __func__, "busy inodes while remounting "\
"xip remain in cache (no functional problem)");
invalidate_inodes(sb)) {
ext2_warning(sb, __func__, "refusing change of xip flag "
"with busy inodes while remounting");
sbi->s_mount_opt &= ~EXT2_MOUNT_XIP;
sbi->s_mount_opt |= old_mount_opt & EXT2_MOUNT_XIP;
}
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
if (*flags & MS_RDONLY) {
Expand Down

0 comments on commit 0e4a9b5

Please sign in to comment.