nilfs2: fix potential hang in nilfs_error on errors=remount-ro
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Sun, 31 Jan 2010 10:46:40 +0000 (19:46 +0900)
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Sat, 13 Feb 2010 03:26:03 +0000 (12:26 +0900)
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>
fs/nilfs2/segment.c
fs/nilfs2/super.c

index 9280b0f..ab439a7 100644 (file)
@@ -2875,8 +2875,15 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi)
        struct the_nilfs *nilfs = sbi->s_nilfs;
        int err;
 
-       /* Each field of nilfs_segctor is cleared through the initialization
-          of super-block info */
+       if (NILFS_SC(sbi)) {
+               /*
+                * This happens if the filesystem was remounted
+                * read/write after nilfs_error degenerated it into a
+                * read-only mount.
+                */
+               nilfs_detach_segment_constructor(sbi);
+       }
+
        sbi->s_sc_info = nilfs_segctor_new(sbi);
        if (!sbi->s_sc_info)
                return -ENOMEM;
index 3f88401..f068270 100644 (file)
@@ -96,9 +96,6 @@ void nilfs_error(struct super_block *sb, const char *function,
        if (!(sb->s_flags & MS_RDONLY)) {
                struct the_nilfs *nilfs = sbi->s_nilfs;
 
-               if (!nilfs_test_opt(sbi, ERRORS_CONT))
-                       nilfs_detach_segment_constructor(sbi);
-
                down_write(&nilfs->ns_sem);
                if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) {
                        nilfs->ns_mount_state |= NILFS_ERROR_FS;