linux/fs/f2fs
Chao Yu dc6febb6bc f2fs: make background threads of f2fs being aware of freezing
When ->freeze_fs is called from lvm for doing snapshot, it needs to
make sure there will be no more changes in filesystem's data, however,
previously, background threads like GC thread wasn't aware of freezing,
so in environment with active background threads, data of snapshot
becomes unstable.

This patch fixes this issue by adding sb_{start,end}_intwrite in
below background threads:
- GC thread
- flush thread
- discard thread

Note that, don't use sb_start_intwrite() in gc_thread_func() due to:

generic/241 reports below bug:

 ======================================================
 WARNING: possible circular locking dependency detected
 4.13.0-rc1+ #32 Tainted: G           O
 ------------------------------------------------------
 f2fs_gc-250:0/22186 is trying to acquire lock:
  (&sbi->gc_mutex){+.+...}, at: [<f8fa7f0b>] f2fs_sync_fs+0x7b/0x1b0 [f2fs]

 but task is already holding lock:
  (sb_internal#2){++++.-}, at: [<f8fb5609>] gc_thread_func+0x159/0x4a0 [f2fs]

 which lock already depends on the new lock.

 the existing dependency chain (in reverse order) is:

 -> #2 (sb_internal#2){++++.-}:
        __lock_acquire+0x405/0x7b0
        lock_acquire+0xae/0x220
        __sb_start_write+0x11d/0x1f0
        f2fs_evict_inode+0x2d6/0x4e0 [f2fs]
        evict+0xa8/0x170
        iput+0x1fb/0x2c0
        f2fs_sync_inode_meta+0x3f/0xf0 [f2fs]
        write_checkpoint+0x1b1/0x750 [f2fs]
        f2fs_sync_fs+0x85/0x1b0 [f2fs]
        f2fs_do_sync_file.isra.24+0x137/0xa30 [f2fs]
        f2fs_sync_file+0x34/0x40 [f2fs]
        vfs_fsync_range+0x4a/0xa0
        do_fsync+0x3c/0x60
        SyS_fdatasync+0x15/0x20
        do_fast_syscall_32+0xa1/0x1b0
        entry_SYSENTER_32+0x4c/0x7b

 -> #1 (&sbi->cp_mutex){+.+...}:
        __lock_acquire+0x405/0x7b0
        lock_acquire+0xae/0x220
        __mutex_lock+0x4f/0x830
        mutex_lock_nested+0x25/0x30
        write_checkpoint+0x2f/0x750 [f2fs]
        f2fs_sync_fs+0x85/0x1b0 [f2fs]
        sync_filesystem+0x67/0x80
        generic_shutdown_super+0x27/0x100
        kill_block_super+0x22/0x50
        kill_f2fs_super+0x3a/0x40 [f2fs]
        deactivate_locked_super+0x3d/0x70
        deactivate_super+0x40/0x60
        cleanup_mnt+0x39/0x70
        __cleanup_mnt+0x10/0x20
        task_work_run+0x69/0x80
        exit_to_usermode_loop+0x57/0x92
        do_fast_syscall_32+0x18c/0x1b0
        entry_SYSENTER_32+0x4c/0x7b

 -> #0 (&sbi->gc_mutex){+.+...}:
        validate_chain.isra.36+0xc50/0xdb0
        __lock_acquire+0x405/0x7b0
        lock_acquire+0xae/0x220
        __mutex_lock+0x4f/0x830
        mutex_lock_nested+0x25/0x30
        f2fs_sync_fs+0x7b/0x1b0 [f2fs]
        f2fs_balance_fs_bg+0xb9/0x200 [f2fs]
        gc_thread_func+0x302/0x4a0 [f2fs]
        kthread+0xe9/0x120
        ret_from_fork+0x19/0x24

 other info that might help us debug this:

 Chain exists of:
   &sbi->gc_mutex --> &sbi->cp_mutex --> sb_internal#2

  Possible unsafe locking scenario:

        CPU0                    CPU1
        ----                    ----
   lock(sb_internal#2);
                                lock(&sbi->cp_mutex);
                                lock(sb_internal#2);
   lock(&sbi->gc_mutex);

  *** DEADLOCK ***

 1 lock held by f2fs_gc-250:0/22186:
  #0:  (sb_internal#2){++++.-}, at: [<f8fb5609>] gc_thread_func+0x159/0x4a0 [f2fs]

 stack backtrace:
 CPU: 2 PID: 22186 Comm: f2fs_gc-250:0 Tainted: G           O    4.13.0-rc1+ #32
 Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
 Call Trace:
  dump_stack+0x5f/0x92
  print_circular_bug+0x1b3/0x1bd
  validate_chain.isra.36+0xc50/0xdb0
  ? __this_cpu_preempt_check+0xf/0x20
  __lock_acquire+0x405/0x7b0
  lock_acquire+0xae/0x220
  ? f2fs_sync_fs+0x7b/0x1b0 [f2fs]
  __mutex_lock+0x4f/0x830
  ? f2fs_sync_fs+0x7b/0x1b0 [f2fs]
  mutex_lock_nested+0x25/0x30
  ? f2fs_sync_fs+0x7b/0x1b0 [f2fs]
  f2fs_sync_fs+0x7b/0x1b0 [f2fs]
  f2fs_balance_fs_bg+0xb9/0x200 [f2fs]
  gc_thread_func+0x302/0x4a0 [f2fs]
  ? preempt_schedule_common+0x2f/0x4d
  ? f2fs_gc+0x540/0x540 [f2fs]
  kthread+0xe9/0x120
  ? f2fs_gc+0x540/0x540 [f2fs]
  ? kthread_create_on_node+0x30/0x30
  ret_from_fork+0x19/0x24

The deadlock occurs in below condition:
GC Thread			Thread B
- sb_start_intwrite
				- f2fs_sync_file
				 - f2fs_sync_fs
				  - mutex_lock(&sbi->gc_mutex)
				   - write_checkpoint
				    - block_operations
				     - f2fs_sync_inode_meta
				      - iput
				       - sb_start_intwrite
 - mutex_lock(&sbi->gc_mutex)

Fix this by altering sb_start_intwrite to sb_start_write_trylock.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2017-07-31 16:47:27 -07:00
..
acl.c f2fs: preserve i_mode if __f2fs_set_acl() fails 2017-07-28 17:48:54 -07:00
acl.h f2fs: remove dead code f2fs_check_acl 2016-09-14 16:52:36 -07:00
checkpoint.c f2fs: avoid cpu lockup 2017-07-17 19:23:18 -07:00
data.c for-f2fs-4.13 2017-07-10 14:29:45 -07:00
debug.c f2fs: show available_nids in f2fs/status 2017-05-03 10:04:57 -07:00
dir.c f2fs: do not set LOST_PINO for newly created dir 2017-07-07 10:34:45 -07:00
extent_cache.c f2fs: fix a bug caused by NULL extent tree 2017-05-23 21:07:18 -07:00
f2fs.h f2fs: don't give partially written atomic data from process crash 2017-07-28 17:49:01 -07:00
file.c f2fs: don't give partially written atomic data from process crash 2017-07-28 17:49:01 -07:00
gc.c f2fs: make background threads of f2fs being aware of freezing 2017-07-31 16:47:27 -07:00
gc.h f2fs: detect idle time depending on user behavior 2016-01-11 15:56:37 -08:00
hash.c f2fs: check entire encrypted bigname when finding a dentry 2017-05-04 11:44:35 -04:00
inline.c f2fs: spread struct f2fs_dentry_ptr for inline path 2017-07-26 19:34:30 -07:00
inode.c f2fs: support plain user/group quota 2017-07-08 23:12:27 -07:00
Kconfig f2fs: add mount option to select fault injection ratio 2016-05-07 10:32:22 -07:00
Makefile f2fs: move sysfs code from super.c to fs/f2fs/sysfs.c 2017-07-04 02:11:45 -07:00
namei.c f2fs: support plain user/group quota 2017-07-08 23:12:27 -07:00
node.c f2fs: alloc new nids for xattr block in recovery 2017-07-26 19:34:30 -07:00
node.h f2fs: simplify the way of calulating next nat address 2017-07-04 02:11:34 -07:00
recovery.c f2fs: avoid dirty node pages in check_only recovery 2017-04-18 13:37:49 -07:00
segment.c f2fs: make background threads of f2fs being aware of freezing 2017-07-31 16:47:27 -07:00
segment.h for-f2fs-4.13 2017-07-10 14:29:45 -07:00
shrinker.c f2fs: avoid casted negative value as shrink count 2016-11-23 12:11:03 -08:00
super.c for-f2fs-4.13 2017-07-10 14:29:45 -07:00
sysfs.c f2fs: include seq_file.h for sysfs.c 2017-07-17 19:23:12 -07:00
trace.c f2fs: use set_page_private marcro in f2fs_trace_pid 2017-03-24 15:10:49 -04:00
trace.h f2fs: add sbi and page pointer in f2fs_io_info 2015-05-28 15:41:32 -07:00
xattr.c f2fs: remove unused input parameter 2017-07-26 19:34:30 -07:00
xattr.h f2fs: guard macro variables with braces 2017-04-10 19:48:10 -07:00