aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/mdt.c
diff options
context:
space:
mode:
authorVyacheslav Dubeyko <slava@dubeyko.com>2013-04-30 18:27:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 20:04:04 -0400
commit8c26c4e2694a163d525976e804d81cd955bbb40c (patch)
treee3205cc7bd1be43d93e10475e5b5bc9483d41e1d /fs/nilfs2/mdt.c
parent9151b3982dafaa87bca3834c4d20db831ca98bcb (diff)
nilfs2: fix issue with flush kernel thread after remount in RO mode because of driver's internal error or metadata corruption
The NILFS2 driver remounts itself in RO mode in the case of discovering metadata corruption (for example, discovering a broken bmap). But usually, this takes place when there have been file system operations before remounting in RO mode. Thereby, NILFS2 driver can be in RO mode with presence of dirty pages in modified inodes' address spaces. It results in flush kernel thread's infinite trying to flush dirty pages in RO mode. As a result, it is possible to see such side effects as: (1) flush kernel thread occupies 50% - 99% of CPU time; (2) system can't be shutdowned without manual power switch off. SYMPTOMS: (1) System log contains error message: "Remounting filesystem read-only". (2) The flush kernel thread occupies 50% - 99% of CPU time. (3) The system can't be shutdowned without manual power switch off. REPRODUCTION PATH: (1) Create volume group with name "unencrypted" by means of vgcreate utility. (2) Run script (prepared by Anthony Doggett <Anthony2486@interfaces.org.uk>): ----------------[BEGIN SCRIPT]-------------------- #!/bin/bash VG=unencrypted #apt-get install nilfs-tools darcs lvcreate --size 2G --name ntest $VG mkfs.nilfs2 -b 1024 -B 8192 /dev/mapper/$VG-ntest mkdir /var/tmp/n mkdir /var/tmp/n/ntest mount /dev/mapper/$VG-ntest /var/tmp/n/ntest mkdir /var/tmp/n/ntest/thedir cd /var/tmp/n/ntest/thedir sleep 2 date darcs init sleep 2 dmesg|tail -n 5 date darcs whatsnew || true date sleep 2 dmesg|tail -n 5 ----------------[END SCRIPT]-------------------- (3) Try to shutdown the system. REPRODUCIBILITY: 100% FIX: This patch implements checking mount state of NILFS2 driver in nilfs_writepage(), nilfs_writepages() and nilfs_mdt_write_page() methods. If it is detected the RO mount state then all dirty pages are simply discarded with warning messages is written in system log. [akpm@linux-foundation.org: fix printk warning] Signed-off-by: Vyacheslav Dubeyko <slava@dubeyko.com> Acked-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Cc: Anthony Doggett <Anthony2486@interfaces.org.uk> Cc: ARAI Shun-ichi <hermes@ceres.dti.ne.jp> Cc: Piotr Szymaniak <szarpaj@grubelek.pl> Cc: Zahid Chowdhury <zahid.chowdhury@starsolutions.com> Cc: Elmer Zhang <freeboy6716@gmail.com> Cc: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nilfs2/mdt.c')
-rw-r--r--fs/nilfs2/mdt.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index f9897d09c693..c4dcd1db57ee 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -375,14 +375,25 @@ int nilfs_mdt_fetch_dirty(struct inode *inode)
375static int 375static int
376nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) 376nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)
377{ 377{
378 struct inode *inode; 378 struct inode *inode = page->mapping->host;
379 struct super_block *sb; 379 struct super_block *sb;
380 int err = 0; 380 int err = 0;
381 381
382 if (inode && (inode->i_sb->s_flags & MS_RDONLY)) {
383 /*
384 * It means that filesystem was remounted in read-only
385 * mode because of error or metadata corruption. But we
386 * have dirty pages that try to be flushed in background.
387 * So, here we simply discard this dirty page.
388 */
389 nilfs_clear_dirty_page(page, false);
390 unlock_page(page);
391 return -EROFS;
392 }
393
382 redirty_page_for_writepage(wbc, page); 394 redirty_page_for_writepage(wbc, page);
383 unlock_page(page); 395 unlock_page(page);
384 396
385 inode = page->mapping->host;
386 if (!inode) 397 if (!inode)
387 return 0; 398 return 0;
388 399
@@ -561,10 +572,10 @@ void nilfs_mdt_restore_from_shadow_map(struct inode *inode)
561 if (mi->mi_palloc_cache) 572 if (mi->mi_palloc_cache)
562 nilfs_palloc_clear_cache(inode); 573 nilfs_palloc_clear_cache(inode);
563 574
564 nilfs_clear_dirty_pages(inode->i_mapping); 575 nilfs_clear_dirty_pages(inode->i_mapping, true);
565 nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data); 576 nilfs_copy_back_pages(inode->i_mapping, &shadow->frozen_data);
566 577
567 nilfs_clear_dirty_pages(&ii->i_btnode_cache); 578 nilfs_clear_dirty_pages(&ii->i_btnode_cache, true);
568 nilfs_copy_back_pages(&ii->i_btnode_cache, &shadow->frozen_btnodes); 579 nilfs_copy_back_pages(&ii->i_btnode_cache, &shadow->frozen_btnodes);
569 580
570 nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store); 581 nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store);