diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-01-31 05:46:40 -0500 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-02-12 22:26:03 -0500 |
commit | fe5f171bb272946ce5fbf843ce2f8467d0d41b9a (patch) | |
tree | fc3917cd7b3fae605e464f94af815dc9d9cce36f /fs/nilfs2 | |
parent | 7512487e6d6459e4c3f9c7cedc53050a6c30e387 (diff) |
nilfs2: fix potential hang in nilfs_error on errors=remount-ro
nilfs_error() calls nilfs_detach_segment_constructor() if
errors=remount-ro option is specified, and this may lead to a hang due
to recursive locking of, for instance, nilfs->ns_segctor_sem and
others.
In this case, detaching segment constructor is not necessary because
read-only flag is set to the filesystem and further writes are
blocked.
This fixes the potential hang issue by removing the
nilfs_detach_segment_constructor() call from nilfs_error.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/segment.c | 11 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 3 |
2 files changed, 9 insertions, 5 deletions
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 9280b0f10792..ab439a7ef2d8 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -2875,8 +2875,15 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi) | |||
2875 | struct the_nilfs *nilfs = sbi->s_nilfs; | 2875 | struct the_nilfs *nilfs = sbi->s_nilfs; |
2876 | int err; | 2876 | int err; |
2877 | 2877 | ||
2878 | /* Each field of nilfs_segctor is cleared through the initialization | 2878 | if (NILFS_SC(sbi)) { |
2879 | of super-block info */ | 2879 | /* |
2880 | * This happens if the filesystem was remounted | ||
2881 | * read/write after nilfs_error degenerated it into a | ||
2882 | * read-only mount. | ||
2883 | */ | ||
2884 | nilfs_detach_segment_constructor(sbi); | ||
2885 | } | ||
2886 | |||
2880 | sbi->s_sc_info = nilfs_segctor_new(sbi); | 2887 | sbi->s_sc_info = nilfs_segctor_new(sbi); |
2881 | if (!sbi->s_sc_info) | 2888 | if (!sbi->s_sc_info) |
2882 | return -ENOMEM; | 2889 | return -ENOMEM; |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 3f88401a375b..f068270f6c75 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -96,9 +96,6 @@ void nilfs_error(struct super_block *sb, const char *function, | |||
96 | if (!(sb->s_flags & MS_RDONLY)) { | 96 | if (!(sb->s_flags & MS_RDONLY)) { |
97 | struct the_nilfs *nilfs = sbi->s_nilfs; | 97 | struct the_nilfs *nilfs = sbi->s_nilfs; |
98 | 98 | ||
99 | if (!nilfs_test_opt(sbi, ERRORS_CONT)) | ||
100 | nilfs_detach_segment_constructor(sbi); | ||
101 | |||
102 | down_write(&nilfs->ns_sem); | 99 | down_write(&nilfs->ns_sem); |
103 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { | 100 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { |
104 | nilfs->ns_mount_state |= NILFS_ERROR_FS; | 101 | nilfs->ns_mount_state |= NILFS_ERROR_FS; |