Skip to contentSkip to conversation

PM / hibernate xfs lock up / xfs_reclaim_inodes_ag

RFC PATCH In review Christoph 7 participants 40 messages Jul 12, 2011 – Nov 16, 2011

Subsystems (4)
lore
Share & tools
lore

Christoph

author
#0 lore raw

Hi!

I'd like you to have a look into this issue:

pm-hibernate locks up when using xfs while "Preallocating image memory".

https://bugzilla.kernel.org/show_bug.cgi?id=33622

I got at least this backtrace (2.6.39.3)

tia

chris

SysRq : Show Blocked State

pm-hibernate D 0000000000000000 0 3638 3637 0x00000000
ffff8800017bf918 0000000000000082 ffff8800017be010 ffff880000000000 ffff8800017be010 ffff88000b8a6170 0000000000013900 ffff8800017bffd8 ffff8800017bffd8 0000000000013900 ffffffff8148b020 ffff88000b8a6170

Call Trace:
 [<ffffffff81344ce2>] schedule_timeout+0x22/0xbb
 [<ffffffff81344b64>] wait_for_common+0xcb/0x148
 [<ffffffff810408ea>] ? try_to_wake_up+0x18c/0x18c
 [<ffffffff81345527>] ? down_write+0x2d/0x31
 [<ffffffff81344c7b>] wait_for_completion+0x18/0x1a
 [<ffffffffa02374da>] xfs_reclaim_inode+0x74/0x258 [xfs]
 [<ffffffffa0237853>] xfs_reclaim_inodes_ag+0x195/0x264 [xfs]
 [<ffffffffa0237974>] xfs_reclaim_inode_shrink+0x52/0x90 [xfs]
 [<ffffffff810c4e21>] shrink_slab+0xdb/0x151
 [<ffffffff810c625a>] do_try_to_free_pages+0x204/0x39a
 [<ffffffff8134ce4e>] ? apic_timer_interrupt+0xe/0x20
 [<ffffffff810c647f>] shrink_all_memory+0x8f/0xa8
 [<ffffffff810cc41a>] ? next_online_pgdat+0x20/0x41
 [<ffffffff8107937d>] hibernate_preallocate_memory+0x1c4/0x30f
 [<ffffffff811a8fa2>] ? kobject_put+0x47/0x4b
 [<ffffffff81077eb2>] hibernation_snapshot+0x45/0x281
 [<ffffffff810781bf>] hibernate+0xd1/0x1b8
 [<ffffffff81076c58>] state_store+0x57/0xce
 [<ffffffff811a8d0b>] kobj_attr_store+0x17/0x19
 [<ffffffff81152bda>] sysfs_write_file+0xfc/0x138
 [<ffffffff810fca74>] vfs_write+0xa9/0x105
 [<ffffffff810fcb89>] sys_write+0x45/0x6c
 [<ffffffff8134c492>] system_call_fastpath+0x16/0x1b

kworker/0:2 D 0000000000000000 0 379 2 0x00000000
ffff88000ea99b90 0000000000000046 ffff88000b8ff840 0000000000000000 ffff88000ea98010 ffff88000c319ac0 0000000000013900 ffff88000ea99fd8 ffff88000ea99fd8 0000000000013900 ffffffff8148b020 ffff88000c319ac0

Call Trace:
 [<ffffffff8134515f>] __mutex_lock_common+0x12e/0x195
 [<ffffffff813451da>] __mutex_lock_slowpath+0x14/0x16
 [<ffffffff813452a8>] mutex_lock+0x1e/0x38
 [<ffffffffa0237738>] xfs_reclaim_inodes_ag+0x7a/0x264 [xfs]
 [<ffffffffa02379cc>] ? xfs_reclaim_inodes+0x1a/0x1a [xfs]
 [<ffffffffa02379ca>] xfs_reclaim_inodes+0x18/0x1a [xfs]
 [<ffffffffa02379e9>] xfs_reclaim_worker+0x1d/0x29 [xfs]
 [<ffffffff81059ec4>] process_one_work+0x1de/0x2ec
 [<ffffffff8105bf60>] worker_thread+0x13d/0x262
 [<ffffffff8105be23>] ? manage_workers+0x194/0x194
 [<ffffffff8105f25a>] kthread+0x7d/0x85
 [<ffffffff8134d5a4>] kernel_thread_helper+0x4/0x10
 [<ffffffff8105f1dd>] ? kthread_worker_fn+0x148/0x148
 [<ffffffff8134d5a0>] ? gs_change+0x13/0x13

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#1 lore raw
Quoted 38 lines · Christoph

Hi!

I'd like you to have a look into this issue:

pm-hibernate locks up when using xfs while "Preallocating image memory".

https://bugzilla.kernel.org/show_bug.cgi?id=33622

I got at least this backtrace (2.6.39.3)

tia

chris

SysRq : Show Blocked State

pm-hibernate D 0000000000000000 0 3638 3637 0x00000000
ffff8800017bf918 0000000000000082 ffff8800017be010 ffff880000000000 ffff8800017be010 ffff88000b8a6170 0000000000013900 ffff8800017bffd8 ffff8800017bffd8 0000000000013900 ffffffff8148b020 ffff88000b8a6170

Call Trace:
 [<ffffffff81344ce2>] schedule_timeout+0x22/0xbb
 [<ffffffff81344b64>] wait_for_common+0xcb/0x148
 [<ffffffff810408ea>] ? try_to_wake_up+0x18c/0x18c
 [<ffffffff81345527>] ? down_write+0x2d/0x31
 [<ffffffff81344c7b>] wait_for_completion+0x18/0x1a
 [<ffffffffa02374da>] xfs_reclaim_inode+0x74/0x258 [xfs]
 [<ffffffffa0237853>] xfs_reclaim_inodes_ag+0x195/0x264 [xfs]
 [<ffffffffa0237974>] xfs_reclaim_inode_shrink+0x52/0x90 [xfs]
 [<ffffffff810c4e21>] shrink_slab+0xdb/0x151
 [<ffffffff810c625a>] do_try_to_free_pages+0x204/0x39a
 [<ffffffff8134ce4e>] ? apic_timer_interrupt+0xe/0x20
 [<ffffffff810c647f>] shrink_all_memory+0x8f/0xa8
 [<ffffffff810cc41a>] ? next_online_pgdat+0x20/0x41
 [<ffffffff8107937d>] hibernate_preallocate_memory+0x1c4/0x30f
 [<ffffffff811a8fa2>] ? kobject_put+0x47/0x4b
Quoted 8 lines
 [<ffffffff81077eb2>] hibernation_snapshot+0x45/0x281
 [<ffffffff810781bf>] hibernate+0xd1/0x1b8
 [<ffffffff81076c58>] state_store+0x57/0xce
 [<ffffffff811a8d0b>] kobj_attr_store+0x17/0x19
 [<ffffffff81152bda>] sysfs_write_file+0xfc/0x138
 [<ffffffff810fca74>] vfs_write+0xa9/0x105
 [<ffffffff810fcb89>] sys_write+0x45/0x6c
 [<ffffffff8134c492>] system_call_fastpath+0x16/0x1b

It's waiting for IO completion, and holding an AG scan lock.

And IO completion requires a workqueue to run. Just FYI, this process of inode reclaim can dirty the filesystem, long after hibernate have assumed that it is clean due to the sys_sync() call you do after freezing the processes. I pointed out this flaw in using sync to write dirty data prior to hibernate a couple of years ago.

Anyway, it's a good thing that XFS doesn't use freezable work queues, otherwise it would hang on every hibernate. Perhaps I should do that to force hibernate to do things properly in filesystems land.

However, it is entirely possible that something else that XFS relies on for IO completion has been put to sleep by this point.

/me finds the smoking cannon:

[  648.794455] xfsbufd/sda3    D 0000000000000000     0   192      2 0x00000000
[  648.794455]  ffff88003720be00 0000000000000046 ffff88003720bd90 ffffffff00000000
[  648.794455]  ffff88003720a010 ffff880056bc3580 0000000000013900 ffff88003720bfd8
[  648.794455]  ffff88003720bfd8 0000000000013900 ffffffff8148b020 ffff880056bc3580
[  648.794455] Call Trace:
[  648.794455]  [<ffffffff81065c0a>] refrigerator+0xbd/0xd3
[  648.794455]  [<ffffffffa022d072>] xfsbufd+0x93/0x14d [xfs]
[  648.794455]  [<ffffffffa022cfdf>] ? xfs_free_buftarg+0x4c/0x4c [xfs]
[  648.794455]  [<ffffffff8105f25a>] kthread+0x7d/0x85
[  648.794455]  [<ffffffff8134d6e4>] kernel_thread_helper+0x4/0x10
[  648.794455]  [<ffffffff8105f1dd>] ? kthread_worker_fn+0x148/0x148
[  648.794455]  [<ffffffff8134d6e0>] ? gs_change+0x13/0x13

The xfsbufd, responsible for pushing out dirty metadata, has been been frozen. sys_sync() does not push out dirty metadata because it is already on stable storage in the journal. If the flush lock is already held on the inode, then inode reclaim will wait for the xfsbufd to flush the backing buffer because reclaim can't do it directly. And hibernate has already frozen the xfsbufd.

IOWs, what hibernate does is:

	freeze_processes()
	sys_sync()
	allocate a large amount of memory

Freezing the processes causes parts of filesystems to be put in the fridge, which means there is no guarantee that sys_sync() actually does what it is supposed to. As it is, sys_sync() really only guarantees file data is clean in memory - metadata does not need to be clean as long s it has been journalled and the journal is safe on disk.

Further, allocating memory can cause memory reclaim to enter the filesystem and try to free memory held by the filesystem. In XFS (at least) this can cause the filesystem to issue tranactions and metadata IO to clean the dirty metadata to enable it to be reclaimed. So hibernate is effectively guaranteed to dirty the filesystem after it has frozen all the worker threads the filesystem might rely on.

Also, by this point kswapd has already been frozen, so hibernate is relying totally on direct memory reclaim to free up the memory it requires. I'm not sure that's a good idea.

IOWs, hibernate is still broken by design - and broken in exactly the way that was pointed out a couple of years ago by myself and others in the filesystem world: sys_sync() does not quiesce or guarantee a clean filesystem in memory after it completes.

There is a solution to this, and it already exists - it's called freezing the filesystem. Effectively hibernate needs to allocate memory before it freezes kernel/filesystem worker threads:

	freeze_userspace_processes()

	// just to clean the page cache quickly
	sys_sync()

	// optionally to free page/inode/dentry caches:
		iterate_supers(drop_pagecache_sb, NULL);
		drop_slab()

	allocate a large amount of memory

	// Now quiesce the filesystems and clean remaining metadata
	iterate_supers(freeze_super, NULL);

	freeze_remaining_processes()

This guarantees that filesystems are still working when memory reclaim comes along to free memory for the hibernate image, and that once it is allocated that filesystems will not be changed until thawed on the hibernate wakeup.

So, like I said a couple of years ago: fix hibernate to quiesce filesystems properly, and the hibernate will be much more reliable and robust and less likely to break randomly in the future.

Cheers,

Dave.

Signature · 7 lines
Dave Chinner
[email protected]

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
#2 lore raw
Quoted 48 lines · Dave Chinner
Quoted 38 lines · Christoph

Hi!

I'd like you to have a look into this issue:

pm-hibernate locks up when using xfs while "Preallocating image memory".

https://bugzilla.kernel.org/show_bug.cgi?id=33622

I got at least this backtrace (2.6.39.3)

tia

chris

SysRq : Show Blocked State

pm-hibernate D 0000000000000000 0 3638 3637 0x00000000
ffff8800017bf918 0000000000000082 ffff8800017be010 ffff880000000000 ffff8800017be010 ffff88000b8a6170 0000000000013900 ffff8800017bffd8 ffff8800017bffd8 0000000000013900 ffffffff8148b020 ffff88000b8a6170

Call Trace:
 [<ffffffff81344ce2>] schedule_timeout+0x22/0xbb
 [<ffffffff81344b64>] wait_for_common+0xcb/0x148
 [<ffffffff810408ea>] ? try_to_wake_up+0x18c/0x18c
 [<ffffffff81345527>] ? down_write+0x2d/0x31
 [<ffffffff81344c7b>] wait_for_completion+0x18/0x1a
 [<ffffffffa02374da>] xfs_reclaim_inode+0x74/0x258 [xfs]
 [<ffffffffa0237853>] xfs_reclaim_inodes_ag+0x195/0x264 [xfs]
 [<ffffffffa0237974>] xfs_reclaim_inode_shrink+0x52/0x90 [xfs]
 [<ffffffff810c4e21>] shrink_slab+0xdb/0x151
 [<ffffffff810c625a>] do_try_to_free_pages+0x204/0x39a
 [<ffffffff8134ce4e>] ? apic_timer_interrupt+0xe/0x20
 [<ffffffff810c647f>] shrink_all_memory+0x8f/0xa8
 [<ffffffff810cc41a>] ? next_online_pgdat+0x20/0x41
 [<ffffffff8107937d>] hibernate_preallocate_memory+0x1c4/0x30f
 [<ffffffff811a8fa2>] ? kobject_put+0x47/0x4b
Quoted 8 lines
 [<ffffffff81077eb2>] hibernation_snapshot+0x45/0x281
 [<ffffffff810781bf>] hibernate+0xd1/0x1b8
 [<ffffffff81076c58>] state_store+0x57/0xce
 [<ffffffff811a8d0b>] kobj_attr_store+0x17/0x19
 [<ffffffff81152bda>] sysfs_write_file+0xfc/0x138
 [<ffffffff810fca74>] vfs_write+0xa9/0x105
 [<ffffffff810fcb89>] sys_write+0x45/0x6c
 [<ffffffff8134c492>] system_call_fastpath+0x16/0x1b
Quoted 8 lines

It's waiting for IO completion, and holding an AG scan lock.

And IO completion requires a workqueue to run. Just FYI, this process of inode reclaim can dirty the filesystem, long after hibernate have assumed that it is clean due to the sys_sync() call you do after freezing the processes. I pointed out this flaw in using sync to write dirty data prior to hibernate a couple of years ago.

However, attempts to remove the sys_sync() from the hibernate code were objected to by some developers, since they believe it will increase the probability of data loss in case of a failing hibernation in general.

Quoted 4 lines

Anyway, it's a good thing that XFS doesn't use freezable work queues, otherwise it would hang on every hibernate. Perhaps I should do that to force hibernate to do things properly in filesystems land.

Well, I'd say it's a very well known fact that filesystems are not handled in any special way during hibernation, which is not a good thing. Nevertheless, I've never seen anyone from the filesystems land pay any kind of attention to this issue.

Quoted 75 lines

However, it is entirely possible that something else that XFS relies on for IO completion has been put to sleep by this point.

/me finds the smoking cannon:

[  648.794455] xfsbufd/sda3    D 0000000000000000     0   192      2 0x00000000
[  648.794455]  ffff88003720be00 0000000000000046 ffff88003720bd90 ffffffff00000000
[  648.794455]  ffff88003720a010 ffff880056bc3580 0000000000013900 ffff88003720bfd8
[  648.794455]  ffff88003720bfd8 0000000000013900 ffffffff8148b020 ffff880056bc3580
[  648.794455] Call Trace:
[  648.794455]  [<ffffffff81065c0a>] refrigerator+0xbd/0xd3
[  648.794455]  [<ffffffffa022d072>] xfsbufd+0x93/0x14d [xfs]
[  648.794455]  [<ffffffffa022cfdf>] ? xfs_free_buftarg+0x4c/0x4c [xfs]
[  648.794455]  [<ffffffff8105f25a>] kthread+0x7d/0x85
[  648.794455]  [<ffffffff8134d6e4>] kernel_thread_helper+0x4/0x10
[  648.794455]  [<ffffffff8105f1dd>] ? kthread_worker_fn+0x148/0x148
[  648.794455]  [<ffffffff8134d6e0>] ? gs_change+0x13/0x13

The xfsbufd, responsible for pushing out dirty metadata, has been been frozen. sys_sync() does not push out dirty metadata because it is already on stable storage in the journal. If the flush lock is already held on the inode, then inode reclaim will wait for the xfsbufd to flush the backing buffer because reclaim can't do it directly. And hibernate has already frozen the xfsbufd.

IOWs, what hibernate does is:

	freeze_processes()
	sys_sync()
	allocate a large amount of memory

Freezing the processes causes parts of filesystems to be put in the fridge, which means there is no guarantee that sys_sync() actually does what it is supposed to. As it is, sys_sync() really only guarantees file data is clean in memory - metadata does not need to be clean as long s it has been journalled and the journal is safe on disk.

Further, allocating memory can cause memory reclaim to enter the filesystem and try to free memory held by the filesystem. In XFS (at least) this can cause the filesystem to issue tranactions and metadata IO to clean the dirty metadata to enable it to be reclaimed. So hibernate is effectively guaranteed to dirty the filesystem after it has frozen all the worker threads the filesystem might rely on.

Also, by this point kswapd has already been frozen, so hibernate is relying totally on direct memory reclaim to free up the memory it requires. I'm not sure that's a good idea.

IOWs, hibernate is still broken by design - and broken in exactly the way that was pointed out a couple of years ago by myself and others in the filesystem world: sys_sync() does not quiesce or guarantee a clean filesystem in memory after it completes.

There is a solution to this, and it already exists - it's called freezing the filesystem. Effectively hibernate needs to allocate memory before it freezes kernel/filesystem worker threads:

	freeze_userspace_processes()

	// just to clean the page cache quickly
	sys_sync()

	// optionally to free page/inode/dentry caches:
		iterate_supers(drop_pagecache_sb, NULL);
		drop_slab()

	allocate a large amount of memory

	// Now quiesce the filesystems and clean remaining metadata
	iterate_supers(freeze_super, NULL);

	freeze_remaining_processes()
Quoted 8 lines

This guarantees that filesystems are still working when memory reclaim comes along to free memory for the hibernate image, and that once it is allocated that filesystems will not be changed until thawed on the hibernate wakeup.

So, like I said a couple of years ago: fix hibernate to quiesce filesystems properly, and the hibernate will be much more reliable and robust and less likely to break randomly in the future.

Why don't you simply submit a patch to do that?

Rafael

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#3 lore raw
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Dave Chinner

On Tue, Jul 12, 2011 at 06:05:01PM +0200, Christoph wrote:

.....

Quoted 40 lines
Quoted 31 lines
Quoted 22 lines

SysRq : Show Blocked State

pm-hibernate D 0000000000000000 0 3638 3637 0x00000000
ffff8800017bf918 0000000000000082 ffff8800017be010 ffff880000000000 ffff8800017be010 ffff88000b8a6170 0000000000013900 ffff8800017bffd8 ffff8800017bffd8 0000000000013900 ffffffff8148b020 ffff88000b8a6170

Call Trace:
 [<ffffffff81344ce2>] schedule_timeout+0x22/0xbb
 [<ffffffff81344b64>] wait_for_common+0xcb/0x148
 [<ffffffff810408ea>] ? try_to_wake_up+0x18c/0x18c
 [<ffffffff81345527>] ? down_write+0x2d/0x31
 [<ffffffff81344c7b>] wait_for_completion+0x18/0x1a
 [<ffffffffa02374da>] xfs_reclaim_inode+0x74/0x258 [xfs]
 [<ffffffffa0237853>] xfs_reclaim_inodes_ag+0x195/0x264 [xfs]
 [<ffffffffa0237974>] xfs_reclaim_inode_shrink+0x52/0x90 [xfs]
 [<ffffffff810c4e21>] shrink_slab+0xdb/0x151
 [<ffffffff810c625a>] do_try_to_free_pages+0x204/0x39a
 [<ffffffff8134ce4e>] ? apic_timer_interrupt+0xe/0x20
 [<ffffffff810c647f>] shrink_all_memory+0x8f/0xa8
 [<ffffffff810cc41a>] ? next_online_pgdat+0x20/0x41
 [<ffffffff8107937d>] hibernate_preallocate_memory+0x1c4/0x30f
 [<ffffffff811a8fa2>] ? kobject_put+0x47/0x4b
Quoted 8 lines
 [<ffffffff81077eb2>] hibernation_snapshot+0x45/0x281
 [<ffffffff810781bf>] hibernate+0xd1/0x1b8
 [<ffffffff81076c58>] state_store+0x57/0xce
 [<ffffffff811a8d0b>] kobj_attr_store+0x17/0x19
 [<ffffffff81152bda>] sysfs_write_file+0xfc/0x138
 [<ffffffff810fca74>] vfs_write+0xa9/0x105
 [<ffffffff810fcb89>] sys_write+0x45/0x6c
 [<ffffffff8134c492>] system_call_fastpath+0x16/0x1b
Quoted 8 lines

It's waiting for IO completion, and holding an AG scan lock.

And IO completion requires a workqueue to run. Just FYI, this process of inode reclaim can dirty the filesystem, long after hibernate have assumed that it is clean due to the sys_sync() call you do after freezing the processes. I pointed out this flaw in using sync to write dirty data prior to hibernate a couple of years ago.

Quoted 3 lines

However, attempts to remove the sys_sync() from the hibernate code were objected to by some developers, since they believe it will increase the probability of data loss in case of a failing hibernation in general.

I'm not suggesting it gets removed, I'm suggesting it gets replaced because it doesn't give the guarantees that you want or need.

Quoted 9 lines
Quoted 4 lines

Anyway, it's a good thing that XFS doesn't use freezable work queues, otherwise it would hang on every hibernate. Perhaps I should do that to force hibernate to do things properly in filesystems land.

Well, I'd say it's a very well known fact that filesystems are not handled in any special way during hibernation, which is not a good thing. Nevertheless, I've never seen anyone from the filesystems land pay any kind of attention to this issue.

I beg to differ. We went through this exact clas of bugs with swsusp back in 2006:

https://lkml.org/lkml/2006/11/12/144

And this patch:

https://lkml.org/lkml/2006/11/1/155

([PATCH -mm] swsusp: Freeze filesystems during suspend)

"This is needed by swsusp, because some filesystems (eg. XFS) use work queues and worker_threads run with PF_NOFREEZE set, so they can cause some writes to be performed after the suspend image has been created which may corrupt the filesystem. The additional benefit of it is that if the resume fails, the filesystems will be in a consistent state and there won't be any journal replays needed."

--

And the patch essentially does:

- sys_sync();
+ freeze_filesystems();

But, Pavel didn't like freezing filesystems to quiesce them correctly, so the sys_sync() and all it's problems have remained until this day, where we still have users tripping over the same "filesystem not idle" problems.

[....]

Quoted 55 lines
Quoted 55 lines

IOWs, what hibernate does is:

	freeze_processes()
	sys_sync()
	allocate a large amount of memory

Freezing the processes causes parts of filesystems to be put in the fridge, which means there is no guarantee that sys_sync() actually does what it is supposed to. As it is, sys_sync() really only guarantees file data is clean in memory - metadata does not need to be clean as long s it has been journalled and the journal is safe on disk.

Further, allocating memory can cause memory reclaim to enter the filesystem and try to free memory held by the filesystem. In XFS (at least) this can cause the filesystem to issue tranactions and metadata IO to clean the dirty metadata to enable it to be reclaimed. So hibernate is effectively guaranteed to dirty the filesystem after it has frozen all the worker threads the filesystem might rely on.

Also, by this point kswapd has already been frozen, so hibernate is relying totally on direct memory reclaim to free up the memory it requires. I'm not sure that's a good idea.

IOWs, hibernate is still broken by design - and broken in exactly the way that was pointed out a couple of years ago by myself and others in the filesystem world: sys_sync() does not quiesce or guarantee a clean filesystem in memory after it completes.

There is a solution to this, and it already exists - it's called freezing the filesystem. Effectively hibernate needs to allocate memory before it freezes kernel/filesystem worker threads:

	freeze_userspace_processes()

	// just to clean the page cache quickly
	sys_sync()

	// optionally to free page/inode/dentry caches:
		iterate_supers(drop_pagecache_sb, NULL);
		drop_slab()

	allocate a large amount of memory

	// Now quiesce the filesystems and clean remaining metadata
	iterate_supers(freeze_super, NULL);

	freeze_remaining_processes()

This guarantees that filesystems are still working when memory reclaim comes along to free memory for the hibernate image, and that once it is allocated that filesystems will not be changed until thawed on the hibernate wakeup.

Quoted 5 lines
Quoted 3 lines

So, like I said a couple of years ago: fix hibernate to quiesce filesystems properly, and the hibernate will be much more reliable and robust and less likely to break randomly in the future.

Why don't you simply submit a patch to do that?

a) I don't know how to test suspend/hibernate
b) I don't have any hardware I can test it on.
c) I don't scale to solving every problem Linux has
d) you guys need to decide how you're going to fix this because the problem has already been solved once before and it didn't get merged because nobody in the swsusp/hibernate world could agree on anything at the time.

Cheers,

Dave.

Signature · 2 lines
Dave Chinner
[email protected]
#4 lore raw
Quoted 61 lines · Dave Chinner
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Dave Chinner

On Tue, Jul 12, 2011 at 06:05:01PM +0200, Christoph wrote:

.....

Quoted 40 lines
Quoted 31 lines
Quoted 22 lines

SysRq : Show Blocked State

pm-hibernate D 0000000000000000 0 3638 3637 0x00000000
ffff8800017bf918 0000000000000082 ffff8800017be010 ffff880000000000 ffff8800017be010 ffff88000b8a6170 0000000000013900 ffff8800017bffd8 ffff8800017bffd8 0000000000013900 ffffffff8148b020 ffff88000b8a6170

Call Trace:
 [<ffffffff81344ce2>] schedule_timeout+0x22/0xbb
 [<ffffffff81344b64>] wait_for_common+0xcb/0x148
 [<ffffffff810408ea>] ? try_to_wake_up+0x18c/0x18c
 [<ffffffff81345527>] ? down_write+0x2d/0x31
 [<ffffffff81344c7b>] wait_for_completion+0x18/0x1a
 [<ffffffffa02374da>] xfs_reclaim_inode+0x74/0x258 [xfs]
 [<ffffffffa0237853>] xfs_reclaim_inodes_ag+0x195/0x264 [xfs]
 [<ffffffffa0237974>] xfs_reclaim_inode_shrink+0x52/0x90 [xfs]
 [<ffffffff810c4e21>] shrink_slab+0xdb/0x151
 [<ffffffff810c625a>] do_try_to_free_pages+0x204/0x39a
 [<ffffffff8134ce4e>] ? apic_timer_interrupt+0xe/0x20
 [<ffffffff810c647f>] shrink_all_memory+0x8f/0xa8
 [<ffffffff810cc41a>] ? next_online_pgdat+0x20/0x41
 [<ffffffff8107937d>] hibernate_preallocate_memory+0x1c4/0x30f
 [<ffffffff811a8fa2>] ? kobject_put+0x47/0x4b
Quoted 8 lines
 [<ffffffff81077eb2>] hibernation_snapshot+0x45/0x281
 [<ffffffff810781bf>] hibernate+0xd1/0x1b8
 [<ffffffff81076c58>] state_store+0x57/0xce
 [<ffffffff811a8d0b>] kobj_attr_store+0x17/0x19
 [<ffffffff81152bda>] sysfs_write_file+0xfc/0x138
 [<ffffffff810fca74>] vfs_write+0xa9/0x105
 [<ffffffff810fcb89>] sys_write+0x45/0x6c
 [<ffffffff8134c492>] system_call_fastpath+0x16/0x1b
Quoted 8 lines

It's waiting for IO completion, and holding an AG scan lock.

And IO completion requires a workqueue to run. Just FYI, this process of inode reclaim can dirty the filesystem, long after hibernate have assumed that it is clean due to the sys_sync() call you do after freezing the processes. I pointed out this flaw in using sync to write dirty data prior to hibernate a couple of years ago.

Quoted 3 lines

However, attempts to remove the sys_sync() from the hibernate code were objected to by some developers, since they believe it will increase the probability of data loss in case of a failing hibernation in general.

I'm not suggesting it gets removed, I'm suggesting it gets replaced because it doesn't give the guarantees that you want or need.

Quoted 9 lines
Quoted 4 lines

Anyway, it's a good thing that XFS doesn't use freezable work queues, otherwise it would hang on every hibernate. Perhaps I should do that to force hibernate to do things properly in filesystems land.

Well, I'd say it's a very well known fact that filesystems are not handled in any special way during hibernation, which is not a good thing. Nevertheless, I've never seen anyone from the filesystems land pay any kind of attention to this issue.

Quoted 4 lines

I beg to differ. We went through this exact clas of bugs with swsusp back in 2006:

https://lkml.org/lkml/2006/11/12/144

You're right, sorry. We discussed this 5 years ago, but the context was a bit different (the hibernation code was using a different mechanism for freeing memory).

Quoted 17 lines

And this patch:

https://lkml.org/lkml/2006/11/1/155

([PATCH -mm] swsusp: Freeze filesystems during suspend)

"This is needed by swsusp, because some filesystems (eg. XFS) use work queues and worker_threads run with PF_NOFREEZE set, so they can cause some writes to be performed after the suspend image has been created which may corrupt the filesystem. The additional benefit of it is that if the resume fails, the filesystems will be in a consistent state and there won't be any journal replays needed."

--

And the patch essentially does:

Review

Quoted 2 lines
(quoted diff) +1 -1
-			sys_sync();
+			freeze_filesystems();

Well, if you still think the patch does the right thing, I can rebase it on top of the current freezer code and resubmit.

Quoted 4 lines

But, Pavel didn't like freezing filesystems to quiesce them correctly, so the sys_sync() and all it's problems have remained until this day, where we still have users tripping over the same "filesystem not idle" problems.

The problem seems to be quite specific to XFS, though.

The Pavel's objection, if I remember it correctly, was that some (or the majority of?) filesystems didn't implement the freezing operation, so they would be more vulnerable to data loss in case of a failing hibernation after this change. However, that's better than actively causing pain to XFS users.

Quoted 64 lines

[....]

Quoted 55 lines
Quoted 55 lines

IOWs, what hibernate does is:

	freeze_processes()
	sys_sync()
	allocate a large amount of memory

Freezing the processes causes parts of filesystems to be put in the fridge, which means there is no guarantee that sys_sync() actually does what it is supposed to. As it is, sys_sync() really only guarantees file data is clean in memory - metadata does not need to be clean as long s it has been journalled and the journal is safe on disk.

Further, allocating memory can cause memory reclaim to enter the filesystem and try to free memory held by the filesystem. In XFS (at least) this can cause the filesystem to issue tranactions and metadata IO to clean the dirty metadata to enable it to be reclaimed. So hibernate is effectively guaranteed to dirty the filesystem after it has frozen all the worker threads the filesystem might rely on.

Also, by this point kswapd has already been frozen, so hibernate is relying totally on direct memory reclaim to free up the memory it requires. I'm not sure that's a good idea.

IOWs, hibernate is still broken by design - and broken in exactly the way that was pointed out a couple of years ago by myself and others in the filesystem world: sys_sync() does not quiesce or guarantee a clean filesystem in memory after it completes.

There is a solution to this, and it already exists - it's called freezing the filesystem. Effectively hibernate needs to allocate memory before it freezes kernel/filesystem worker threads:

	freeze_userspace_processes()

	// just to clean the page cache quickly
	sys_sync()

	// optionally to free page/inode/dentry caches:
		iterate_supers(drop_pagecache_sb, NULL);
		drop_slab()

	allocate a large amount of memory

	// Now quiesce the filesystems and clean remaining metadata
	iterate_supers(freeze_super, NULL);

	freeze_remaining_processes()

This guarantees that filesystems are still working when memory reclaim comes along to free memory for the hibernate image, and that once it is allocated that filesystems will not be changed until thawed on the hibernate wakeup.

Quoted 5 lines
Quoted 3 lines

So, like I said a couple of years ago: fix hibernate to quiesce filesystems properly, and the hibernate will be much more reliable and robust and less likely to break randomly in the future.

Why don't you simply submit a patch to do that?

Quoted 7 lines

a) I don't know how to test suspend/hibernate
b) I don't have any hardware I can test it on.
c) I don't scale to solving every problem Linux has
d) you guys need to decide how you're going to fix this because the problem has already been solved once before and it didn't get merged because nobody in the swsusp/hibernate world could agree on anything at the time.

OK, I'm not a filesystem expert in turn.

As I said, I can revive the Nigel's patch if you think it's better than the code we have, but I'm afraid that's all I can do without any help from the filesystems people.

Thanks,
Rafael

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#5 lore raw
Quoted 5 lines · Rafael J. Wysocki

The Pavel's objection, if I remember it correctly, was that some (or the majority of?) filesystems didn't implement the freezing operation, so they would be more vulnerable to data loss in case of a failing hibernation after this change. However, that's better than actively causing pain to XFS users.

The objection never made sense and only means he never read the code. freeze_super (or freeze_bdev back then) always does a sync_filesystem before even checking if we have a freeze method, and sync_filesystem is what we iterate over for each superblock in sync().

#6 lore raw

Hi.

Quoted 11 lines · Christoph Hellwig
Quoted 5 lines · Rafael J. Wysocki

The Pavel's objection, if I remember it correctly, was that some (or the majority of?) filesystems didn't implement the freezing operation, so they would be more vulnerable to data loss in case of a failing hibernation after this change. However, that's better than actively causing pain to XFS users.

The objection never made sense and only means he never read the code. freeze_super (or freeze_bdev back then) always does a sync_filesystem before even checking if we have a freeze method, and sync_filesystem is what we iterate over for each superblock in sync().

I've had freezing supers in TOI for a couple of years now and it has only ever helped. To be honest, if you have a ton of dirty pages, it does result in a big delay, but that's the worst of it.

Regards,

Nigel

Signature · 3 lines
Evolution (n): A hypothetical process whereby improbable
events occur with alarming frequency, order arises from chaos, and
no one is given credit.
#7 lore raw

RFC PATCH 1/1 PM / Freezer: Freeze filesystems along with freezing processes (was: Re: PM / hibernate xfs lock up / xfs_reclaim_inodes_ag)

Quoted 10 lines · Nigel Cunningham

Hi.

Quoted 7 lines · Christoph Hellwig
Quoted 5 lines · Rafael J. Wysocki

The Pavel's objection, if I remember it correctly, was that some (or the majority of?) filesystems didn't implement the freezing operation, so they would be more vulnerable to data loss in case of a failing hibernation after this change. However, that's better than actively causing pain to XFS users.

Quoted 8 lines
Quoted 4 lines

The objection never made sense and only means he never read the code. freeze_super (or freeze_bdev back then) always does a sync_filesystem before even checking if we have a freeze method, and sync_filesystem is what we iterate over for each superblock in sync().

I've had freezing supers in TOI for a couple of years now and it has only ever helped. To be honest, if you have a ton of dirty pages, it does result in a big delay, but that's the worst of it.

OK, so below is the revived patch.

To be precise, we don't call sys_sync() from the freezer an more (evidently, I'd removed in myself, but later forgot about that), so it only adds freeze_filesystems() and thaw_filesystems().

Comments welcome.

Thanks,
Rafael

---

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---
 fs/block_dev.c         |   43 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    6 ++++++
 kernel/power/process.c |    7 ++++++-
 3 files changed, 55 insertions(+), 1 deletion(-)
include/linux/fs.h +6 -0
Index: linux-2.6/include/linux/fs.h
===================================================================
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* bdev has been frozen */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2047,6 +2048,8 @@ extern struct super_block *freeze_bdev(s
 extern void emergency_thaw_all(void);
 extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
 extern int fsync_bdev(struct block_device *);
+extern void freeze_filesystems(void);
+extern void thaw_filesystems(void);
 #else
 static inline void bd_forget(struct inode *inode) {}
 static inline int sync_blockdev(struct block_device *bdev) { return 0; }
@@ -2061,6 +2064,9 @@ static inline int thaw_bdev(struct block
 {
 	return 0;
 }
+
+static inline void freeze_filesystems(void) {}
+static inline void thaw_filesystems(void) {}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;
fs/block_dev.c +43 -0

49 lines not on this page · raw message

kernel/power/process.c +6 -1
Index: linux-2.6/kernel/power/process.c
===================================================================
@@ -12,10 +12,10 @@
 #include <linux/oom.h>
 #include <linux/suspend.h>
 #include <linux/module.h>
-#include <linux/syscalls.h>
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/fs.h>
 
 /* 
  * Timeout for stopping processes
@@ -147,6 +147,10 @@ int freeze_processes(void)
 		goto Exit;
 	printk("done.\n");
 
+	pr_info("Freezing filesystems ... ");
+	freeze_filesystems();
+	pr_info("done.\n");
+
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
 	if (error)
@@ -188,6 +192,7 @@ void thaw_processes(void)
 	printk("Restarting tasks ... ");
 	thaw_workqueues();
 	thaw_tasks(true);
+	thaw_filesystems();
 	thaw_tasks(false);
 	schedule();
 	printk("done.\n");
#8 lore raw

Re: [RFC][PATCH] PM / Freezer: Freeze filesystems along with freezing processes (was: Re: PM / hibernate xfs lock up / xfs_reclaim_inodes_ag)

Hi!

Quoted 18 lines

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

fs/block_dev.c out: · line 324

Quoted 8 lines
fs/block_dev.c +8 -0
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;
+
+	lockdep_off();

Ouch. So... why do we need to silence this?

fs/block_dev.c out: · line 334

Quoted 10 lines
fs/block_dev.c +10 -0
+	/*
+	 * Freeze in reverse order so filesystems dependant upon others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY) ||
+		    (sb->s_flags & MS_FROZEN))
+			continue;

Should we stop NFS from modifying remote server, too?

Plus... ext3 writes to read-only filesystems on mount; not sure if it does it later. But RDONLY means 'user cant write to it' not 'bdev will not be modified'. Should we freeze all?

How can 'already frozen' happen?

fs/block_dev.c out: · line 355

Quoted 5 lines
fs/block_dev.c +5 -0
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

...because we'll unfreeze it even if we did not freeze it...

Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#9 lore raw

Re: [RFC][PATCH] PM / Freezer: Freeze filesystems along with freezing processes (was: Re: PM / hibernate xfs lock up / xfs_reclaim_inodes_ag)

In reply to Rafael J. Wysocki

Hi!

Quoted 18 lines

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

fs/block_dev.c out: · line 324

Quoted 8 lines
fs/block_dev.c +8 -0
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;
+
+	lockdep_off();

Ouch. So... why do we need to silence this?

fs/block_dev.c out: · line 334

Quoted 10 lines
fs/block_dev.c +10 -0
+	/*
+	 * Freeze in reverse order so filesystems dependant upon others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY) ||
+		    (sb->s_flags & MS_FROZEN))
+			continue;

Should we stop NFS from modifying remote server, too?

Plus... ext3 writes to read-only filesystems on mount; not sure if it does it later. But RDONLY means 'user cant write to it' not 'bdev will not be modified'. Should we freeze all?

How can 'already frozen' happen?

fs/block_dev.c out: · line 355

Quoted 5 lines
fs/block_dev.c +5 -0
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

...because we'll unfreeze it even if we did not freeze it...

Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#10 lore raw

Re: [RFC][PATCH] PM / Freezer: Freeze filesystems along with freezing processes (was: Re: PM / hibernate xfs lock up / xfs_reclaim_inodes_ag)

Quoted 20 lines · Pavel Machek

Hi!

Quoted 17 lines

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

Quoted 10 lines

fs/block_dev.c out: · line 324

Quoted 8 lines
fs/block_dev.c +8 -0
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;
+
+	lockdep_off();

Ouch. So... why do we need to silence this?

So that it doesn't complain? :-)

I'll need some time to get the exact details here.

Quoted 4 lines
Quoted 4 lines
fs/block_dev.c +4 -0
+	/*
+	 * Freeze in reverse order so filesystems dependant upon others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
Quoted 8 lines

fs/block_dev.c out: · line 334

Quoted 6 lines
fs/block_dev.c +6 -0
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY) ||
+		    (sb->s_flags & MS_FROZEN))
+			continue;

Should we stop NFS from modifying remote server, too?

What do you mean exactly?

Quoted 6 lines

Plus... ext3 writes to read-only filesystems on mount; not sure if it does it later. But RDONLY means 'user cant write to it' not 'bdev will not be modified'. Should we freeze all?

How can 'already frozen' happen?

Quoted 7 lines

fs/block_dev.c out: · line 355

Quoted 5 lines
fs/block_dev.c +5 -0
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

...because we'll unfreeze it even if we did not freeze it...

So we need not check MS_FROZEN in freeze_filesystems(). OK

Thanks,
Rafael

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#11 lore raw

Re: [RFC][PATCH] PM / Freezer: Freeze filesystems along with freezing processes (was: Re: PM / hibernate xfs lock up / xfs_reclaim_inodes_ag)

Quoted 32 lines · Rafael J. Wysocki
Quoted 20 lines · Pavel Machek

Hi!

Quoted 17 lines

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

Quoted 10 lines

fs/block_dev.c out: · line 324

Quoted 8 lines
fs/block_dev.c +8 -0
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;
+
+	lockdep_off();

Ouch. So... why do we need to silence this?

Quoted 3 lines

So that it doesn't complain? :-)

I'll need some time to get the exact details here.

So, this is because ext3_freeze() that doesn't call journal_unlock_updates() on success, which quite frankly looks like a bug in ext3 to me. At least that's different from what ext4 does in exactly the same situation (which looks correct).

If ext3_freeze() called journal_unlock_updates() on success too and the call to journal_unlock_updates() is removed from ext3_unfreeze(), we wouldn't need that lockdep_off()/lockdep_on() around the loop.

I need someone with ext3/ext4 knowledge to comment here, though.

Moreover, I'm not sure if other filesystems don't do such things.

Anyway, this is just a false-positive, even with the ext3 code as is.

Quoted 29 lines
Quoted 4 lines
Quoted 4 lines
fs/block_dev.c +4 -0
+	/*
+	 * Freeze in reverse order so filesystems dependant upon others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
Quoted 8 lines

fs/block_dev.c out: · line 334

Quoted 6 lines
fs/block_dev.c +6 -0
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY) ||
+		    (sb->s_flags & MS_FROZEN))
+			continue;

Should we stop NFS from modifying remote server, too?

What do you mean exactly?

Quoted 6 lines

Plus... ext3 writes to read-only filesystems on mount; not sure if it does it later. But RDONLY means 'user cant write to it' not 'bdev will not be modified'. Should we freeze all?

How can 'already frozen' happen?

Quoted 7 lines

fs/block_dev.c out: · line 355

Quoted 5 lines
fs/block_dev.c +5 -0
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

...because we'll unfreeze it even if we did not freeze it...

Quoted 1 line

So we need not check MS_FROZEN in freeze_filesystems(). OK

Thanks,
Rafael

#12 lore raw

PATCH 1/1 PM / Freezer: Freeze filesystems while freezing processes (v2)

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---

OK, so nobody except for Pavel appears to have any comments, so I assume that everyone except for Pavel is fine with the approach, interestingly enough.

I've removed the MS_FROZEN Pavel complained about from freeze_filesystems() and added comments explaining why lockdep_off/on() are used.

Thanks,
Rafael

---
 fs/block_dev.c         |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    6 +++++
 kernel/power/process.c |    7 +++++-
 3 files changed, 68 insertions(+), 1 deletion(-)
include/linux/fs.h +6 -0
Index: linux-2.6/include/linux/fs.h
===================================================================
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* bdev has been frozen */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2047,6 +2048,8 @@ extern struct super_block *freeze_bdev(s
 extern void emergency_thaw_all(void);
 extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
 extern int fsync_bdev(struct block_device *);
+extern void freeze_filesystems(void);
+extern void thaw_filesystems(void);
 #else
 static inline void bd_forget(struct inode *inode) {}
 static inline int sync_blockdev(struct block_device *bdev) { return 0; }
@@ -2061,6 +2064,9 @@ static inline int thaw_bdev(struct block
 {
 	return 0;
 }
+
+static inline void freeze_filesystems(void) {}
+static inline void thaw_filesystems(void) {}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;
fs/block_dev.c +56 -0

62 lines not on this page · raw message

kernel/power/process.c +6 -1
Index: linux-2.6/kernel/power/process.c
===================================================================
@@ -12,10 +12,10 @@
 #include <linux/oom.h>
 #include <linux/suspend.h>
 #include <linux/module.h>
-#include <linux/syscalls.h>
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/fs.h>
 
 /* 
  * Timeout for stopping processes
@@ -147,6 +147,10 @@ int freeze_processes(void)
 		goto Exit;
 	printk("done.\n");
 
+	pr_info("Freezing filesystems ... ");
+	freeze_filesystems();
+	pr_info("done.\n");
+
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
 	if (error)
@@ -188,6 +192,7 @@ void thaw_processes(void)
 	printk("Restarting tasks ... ");
 	thaw_workqueues();
 	thaw_tasks(true);
+	thaw_filesystems();
 	thaw_tasks(false);
 	schedule();
 	printk("done.\n");
#13 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 85 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---

OK, so nobody except for Pavel appears to have any comments, so I assume that everyone except for Pavel is fine with the approach, interestingly enough.

I've removed the MS_FROZEN Pavel complained about from freeze_filesystems() and added comments explaining why lockdep_off/on() are used.

Thanks,
Rafael

---
 fs/block_dev.c         |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    6 +++++
 kernel/power/process.c |    7 +++++-
 3 files changed, 68 insertions(+), 1 deletion(-)

Index: linux-2.6/include/linux/fs.h
===================================================================

include/linux/fs.h +6 -0
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* bdev has been frozen */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2047,6 +2048,8 @@ extern struct super_block *freeze_bdev(s
 extern void emergency_thaw_all(void);
 extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
 extern int fsync_bdev(struct block_device *);
+extern void freeze_filesystems(void);
+extern void thaw_filesystems(void);
 #else
 static inline void bd_forget(struct inode *inode) {}
 static inline int sync_blockdev(struct block_device *bdev) { return 0; }
@@ -2061,6 +2064,9 @@ static inline int thaw_bdev(struct block
 {
 	return 0;
 }
+
+static inline void freeze_filesystems(void) {}
+static inline void thaw_filesystems(void) {}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;

Index: linux-2.6/fs/block_dev.c
===================================================================

fs/block_dev.c +6 -0
@@ -314,6 +314,62 @@ out:
 }
 EXPORT_SYMBOL(thaw_bdev);
 
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;

fs/block_dev.c out: · line 332

Quoted 10 lines
fs/block_dev.c +10 -0
+
+	/*
+	 * This is necessary, because some filesystems (e.g. ext3) lock
+	 * mutexes in their .freeze_fs() callbacks and leave them locked for
+	 * their .unfreeze_fs() callbacks to unlock.  This is done under
+	 * bdev->bd_fsfreeze_mutex, which is then released, but it makes
+	 * lockdep think something may be wrong when freeze_bdev() attempts
+	 * to acquire bdev->bd_fsfreeze_mutex for the next filesystem.
+	 */
+	lockdep_off();

I thought those problems were fixed. If they aren't, then they most certainly need to be because holding mutexes over system calls is a bug.

Well, well:

[252182.603134] ================================================
[252182.604832] [ BUG: lock held when returning to user space! ]
[252182.606086] ------------------------------------------------
[252182.607400] xfs_io/4917 is leaving the kernel with locks still held!
[252182.608905] 1 lock held by xfs_io/4917:
[252182.609739]  #0:  (&journal->j_barrier){+.+...}, at: [<ffffffff812a2aaf>] journal_lock_updates+0xef/0x100

<sigh>

Looks like the problem was fixed for ext4, but not ext3. Please report this to the ext3/4 list and get it fixed, don't work around it here.

fs/block_dev.c out: · line 346

Quoted 13 lines
fs/block_dev.c +13 -0
+	/*
+	 * Freeze in reverse order so filesystems depending on others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY))
+			continue;
+
+		freeze_bdev(sb->s_bdev);
+		sb->s_flags |= MS_FROZEN;
+	}

AFAIK, that won't work for btrfs - you have to call freeze_super() directly for btrfs because it has a special relationship with sb->s_bdev. And besides, all freeze_bdev does is get an active reference on the superblock and call freeze_super().

Also, that's traversing the list of superblock with locking and dereferencing the superblock without properly checking that the superblock is not being torn down. You should probably use iterate_supers (or at least copy the code), with a function that drops the s_umount read lock befor calling freeze_super() and then picks it back up afterwards.

Quoted 12 lines
fs/block_dev.c +12 -0
+
+	lockdep_on();
+}
+
+/**
+ * thaw_filesystems - Make all filesystems active again.
+ */
+void thaw_filesystems(void)
+{
+	struct super_block *sb;
+
+	/*

fs/block_dev.c out: · line 368

Quoted 10 lines
fs/block_dev.c +10 -0
+	 * This is necessary for the same reason as in freeze_filesystems()
+	 * above.
+	 */
+	lockdep_off();
+
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

And once again, iterate_supers() is what you want here. And you should only call thaw_bdev() as it needs to do checks other than checking MS_FROZEN e.g. the above will unfreeze filesystems that were already frozen at the time a suspend occurs, and that could lead to corruption depending on why the filesystem was frozen...

Also, you still need to check for a valid sb->s_bdev here, otherwise <splat>.

Cheers,

Dave.

Signature · 2 lines
Dave Chinner
[email protected]
#14 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 110 lines · Dave Chinner
Quoted 85 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---

OK, so nobody except for Pavel appears to have any comments, so I assume that everyone except for Pavel is fine with the approach, interestingly enough.

I've removed the MS_FROZEN Pavel complained about from freeze_filesystems() and added comments explaining why lockdep_off/on() are used.

Thanks,
Rafael

---
 fs/block_dev.c         |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    6 +++++
 kernel/power/process.c |    7 +++++-
 3 files changed, 68 insertions(+), 1 deletion(-)

Index: linux-2.6/include/linux/fs.h
===================================================================

include/linux/fs.h +6 -0
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* bdev has been frozen */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2047,6 +2048,8 @@ extern struct super_block *freeze_bdev(s
 extern void emergency_thaw_all(void);
 extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
 extern int fsync_bdev(struct block_device *);
+extern void freeze_filesystems(void);
+extern void thaw_filesystems(void);
 #else
 static inline void bd_forget(struct inode *inode) {}
 static inline int sync_blockdev(struct block_device *bdev) { return 0; }
@@ -2061,6 +2064,9 @@ static inline int thaw_bdev(struct block
 {
 	return 0;
 }
+
+static inline void freeze_filesystems(void) {}
+static inline void thaw_filesystems(void) {}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;

Index: linux-2.6/fs/block_dev.c
===================================================================

fs/block_dev.c +6 -0
@@ -314,6 +314,62 @@ out:
 }
 EXPORT_SYMBOL(thaw_bdev);
 
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;

fs/block_dev.c out: · line 332

Quoted 10 lines
fs/block_dev.c +10 -0
+
+	/*
+	 * This is necessary, because some filesystems (e.g. ext3) lock
+	 * mutexes in their .freeze_fs() callbacks and leave them locked for
+	 * their .unfreeze_fs() callbacks to unlock.  This is done under
+	 * bdev->bd_fsfreeze_mutex, which is then released, but it makes
+	 * lockdep think something may be wrong when freeze_bdev() attempts
+	 * to acquire bdev->bd_fsfreeze_mutex for the next filesystem.
+	 */
+	lockdep_off();

I thought those problems were fixed. If they aren't, then they most certainly need to be because holding mutexes over system calls is a bug.

Well, well:

[252182.603134] ================================================
[252182.604832] [ BUG: lock held when returning to user space! ]
[252182.606086] ------------------------------------------------
[252182.607400] xfs_io/4917 is leaving the kernel with locks still held!
[252182.608905] 1 lock held by xfs_io/4917:
[252182.609739]  #0:  (&journal->j_barrier){+.+...}, at: [<ffffffff812a2aaf>] journal_lock_updates+0xef/0x100
Quoted 5 lines

<sigh>

Looks like the problem was fixed for ext4, but not ext3. Please report this to the ext3/4 list and get it fixed, don't work around it here.

OK, but I guess I'll have to post a patch to fix this myself so that anyone notices. :-)

Quoted 10 lines
Quoted 10 lines
fs/block_dev.c +10 -0
+	/*
+	 * Freeze in reverse order so filesystems depending on others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY))
+			continue;
+
Quoted 8 lines

fs/block_dev.c out: · line 346

Quoted 3 lines
fs/block_dev.c +3 -0
+		freeze_bdev(sb->s_bdev);
+		sb->s_flags |= MS_FROZEN;
+	}

AFAIK, that won't work for btrfs - you have to call freeze_super() directly for btrfs because it has a special relationship with sb->s_bdev. And besides, all freeze_bdev does is get an active reference on the superblock and call freeze_super().

OK, so do you mean I should call freeze_super() rather than freeze_bdev()?

Quoted 6 lines

Also, that's traversing the list of superblock with locking and dereferencing the superblock without properly checking that the superblock is not being torn down. You should probably use iterate_supers (or at least copy the code), with a function that drops the s_umount read lock befor calling freeze_super() and then picks it back up afterwards.

Hmm, I'll try that, but I doubt I'll get it right first time. :-)

Quoted 16 lines
Quoted 16 lines
fs/block_dev.c +16 -0
+
+	lockdep_on();
+}
+
+/**
+ * thaw_filesystems - Make all filesystems active again.
+ */
+void thaw_filesystems(void)
+{
+	struct super_block *sb;
+
+	/*
+	 * This is necessary for the same reason as in freeze_filesystems()
+	 * above.
+	 */
+	lockdep_off();
Quoted 8 lines

fs/block_dev.c out: · line 368

Quoted 6 lines
fs/block_dev.c +6 -0
+
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

And once again, iterate_supers() is what you want here.

OK

Quoted 2 lines

And you should only call thaw_bdev() as it needs to do checks other than checking MS_FROZEN

Hmm, I'm not really sure what you mean?

Quoted 6 lines

e.g. the above will unfreeze filesystems that
were already frozen at the time a suspend occurs, and that could lead to corruption depending on why the filesystem was frozen...

Also, you still need to check for a valid sb->s_bdev here, otherwise <splat>.

I see.

Thanks,
Rafael

#15 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

In reply to Dave Chinner
Quoted 110 lines · Dave Chinner
Quoted 85 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---

OK, so nobody except for Pavel appears to have any comments, so I assume that everyone except for Pavel is fine with the approach, interestingly enough.

I've removed the MS_FROZEN Pavel complained about from freeze_filesystems() and added comments explaining why lockdep_off/on() are used.

Thanks,
Rafael

---
 fs/block_dev.c         |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    6 +++++
 kernel/power/process.c |    7 +++++-
 3 files changed, 68 insertions(+), 1 deletion(-)

Index: linux-2.6/include/linux/fs.h
===================================================================

include/linux/fs.h +6 -0
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* bdev has been frozen */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2047,6 +2048,8 @@ extern struct super_block *freeze_bdev(s
 extern void emergency_thaw_all(void);
 extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
 extern int fsync_bdev(struct block_device *);
+extern void freeze_filesystems(void);
+extern void thaw_filesystems(void);
 #else
 static inline void bd_forget(struct inode *inode) {}
 static inline int sync_blockdev(struct block_device *bdev) { return 0; }
@@ -2061,6 +2064,9 @@ static inline int thaw_bdev(struct block
 {
 	return 0;
 }
+
+static inline void freeze_filesystems(void) {}
+static inline void thaw_filesystems(void) {}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;

Index: linux-2.6/fs/block_dev.c
===================================================================

fs/block_dev.c +6 -0
@@ -314,6 +314,62 @@ out:
 }
 EXPORT_SYMBOL(thaw_bdev);
 
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;

fs/block_dev.c out: · line 332

Quoted 10 lines
fs/block_dev.c +10 -0
+
+	/*
+	 * This is necessary, because some filesystems (e.g. ext3) lock
+	 * mutexes in their .freeze_fs() callbacks and leave them locked for
+	 * their .unfreeze_fs() callbacks to unlock.  This is done under
+	 * bdev->bd_fsfreeze_mutex, which is then released, but it makes
+	 * lockdep think something may be wrong when freeze_bdev() attempts
+	 * to acquire bdev->bd_fsfreeze_mutex for the next filesystem.
+	 */
+	lockdep_off();

I thought those problems were fixed. If they aren't, then they most certainly need to be because holding mutexes over system calls is a bug.

Well, well:

[252182.603134] ================================================
[252182.604832] [ BUG: lock held when returning to user space! ]
[252182.606086] ------------------------------------------------
[252182.607400] xfs_io/4917 is leaving the kernel with locks still held!
[252182.608905] 1 lock held by xfs_io/4917:
[252182.609739]  #0:  (&journal->j_barrier){+.+...}, at: [<ffffffff812a2aaf>] journal_lock_updates+0xef/0x100
Quoted 5 lines

<sigh>

Looks like the problem was fixed for ext4, but not ext3. Please report this to the ext3/4 list and get it fixed, don't work around it here.

OK, but I guess I'll have to post a patch to fix this myself so that anyone notices. :-)

Quoted 10 lines
Quoted 10 lines
fs/block_dev.c +10 -0
+	/*
+	 * Freeze in reverse order so filesystems depending on others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY))
+			continue;
+
Quoted 8 lines

fs/block_dev.c out: · line 346

Quoted 3 lines
fs/block_dev.c +3 -0
+		freeze_bdev(sb->s_bdev);
+		sb->s_flags |= MS_FROZEN;
+	}

AFAIK, that won't work for btrfs - you have to call freeze_super() directly for btrfs because it has a special relationship with sb->s_bdev. And besides, all freeze_bdev does is get an active reference on the superblock and call freeze_super().

OK, so do you mean I should call freeze_super() rather than freeze_bdev()?

Quoted 6 lines

Also, that's traversing the list of superblock with locking and dereferencing the superblock without properly checking that the superblock is not being torn down. You should probably use iterate_supers (or at least copy the code), with a function that drops the s_umount read lock befor calling freeze_super() and then picks it back up afterwards.

Hmm, I'll try that, but I doubt I'll get it right first time. :-)

Quoted 16 lines
Quoted 16 lines
fs/block_dev.c +16 -0
+
+	lockdep_on();
+}
+
+/**
+ * thaw_filesystems - Make all filesystems active again.
+ */
+void thaw_filesystems(void)
+{
+	struct super_block *sb;
+
+	/*
+	 * This is necessary for the same reason as in freeze_filesystems()
+	 * above.
+	 */
+	lockdep_off();
Quoted 8 lines

fs/block_dev.c out: · line 368

Quoted 6 lines
fs/block_dev.c +6 -0
+
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

And once again, iterate_supers() is what you want here.

OK

Quoted 2 lines

And you should only call thaw_bdev() as it needs to do checks other than checking MS_FROZEN

Hmm, I'm not really sure what you mean?

Quoted 6 lines

e.g. the above will unfreeze filesystems that
were already frozen at the time a suspend occurs, and that could lead to corruption depending on why the filesystem was frozen...

Also, you still need to check for a valid sb->s_bdev here, otherwise <splat>.

I see.

Thanks,
Rafael

#16 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

In reply to Dave Chinner
Quoted 2 lines · Dave Chinner
Quoted 1 line · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

...

Quoted 19 lines

Review

Quoted 13 lines
(quoted diff) +13 -0
+	/*
+	 * Freeze in reverse order so filesystems depending on others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY))
+			continue;
+
+		freeze_bdev(sb->s_bdev);
+		sb->s_flags |= MS_FROZEN;
+	}

AFAIK, that won't work for btrfs - you have to call freeze_super() directly for btrfs because it has a special relationship with sb->s_bdev. And besides, all freeze_bdev does is get an active reference on the superblock and call freeze_super().

Quoted 6 lines

Also, that's traversing the list of superblock with locking and dereferencing the superblock without properly checking that the superblock is not being torn down. You should probably use iterate_supers (or at least copy the code), with a function that drops the s_umount read lock befor calling freeze_super() and then picks it back up afterwards.

So, what about the patch below? It appears to work on my test boxes.

Thanks,
Rafael

---
From: Rafael J. Wysocki <[email protected]>
Subject: PM / Freezer: Freeze filesystems while freezing processes (v3)

Freeze all filesystems during the freezing of tasks by calling freeze_super() for all superblocks and thaw them during the thawing of tasks with the help of thaw_super().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---
 fs/super.c             |   70 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    3 ++
 kernel/power/process.c |    9 +++++-
 3 files changed, 81 insertions(+), 1 deletion(-)
include/linux/fs.h +3 -0
Index: linux/include/linux/fs.h
===================================================================
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* Frozen filesystem */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2497,6 +2498,8 @@ extern void drop_super(struct super_bloc
 extern void iterate_supers(void (*)(struct super_block *, void *), void *);
 extern void iterate_supers_type(struct file_system_type *,
 			        void (*)(struct super_block *, void *), void *);
+extern int freeze_supers(void);
+extern void thaw_supers(void);
 
 extern int dcache_dir_open(struct inode *, struct file *);
 extern int dcache_dir_close(struct inode *, struct file *);
kernel/power/process.c +8 -1
Index: linux/kernel/power/process.c
===================================================================
@@ -12,10 +12,10 @@
 #include <linux/oom.h>
 #include <linux/suspend.h>
 #include <linux/module.h>
-#include <linux/syscalls.h>
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/fs.h>
 
 /* 
  * Timeout for stopping processes
@@ -147,6 +147,12 @@ int freeze_processes(void)
 		goto Exit;
 	printk("done.\n");
 
+	printk("Freezing filesystems ... ");
+	error = freeze_supers();
+	if (error)
+		goto Exit;
+	printk("done.\n");
+
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
 	if (error)
@@ -188,6 +194,7 @@ void thaw_processes(void)
 	printk("Restarting tasks ... ");
 	thaw_workqueues();
 	thaw_tasks(true);
+	thaw_supers();
 	thaw_tasks(false);
 	schedule();
 	printk("done.\n");
fs/super.c +70 -0

76 lines not on this page · raw message

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#17 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

In reply to Dave Chinner
Quoted 2 lines · Dave Chinner
Quoted 1 line · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

...

Quoted 19 lines

Review

Quoted 13 lines
(quoted diff) +13 -0
+	/*
+	 * Freeze in reverse order so filesystems depending on others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY))
+			continue;
+
+		freeze_bdev(sb->s_bdev);
+		sb->s_flags |= MS_FROZEN;
+	}

AFAIK, that won't work for btrfs - you have to call freeze_super() directly for btrfs because it has a special relationship with sb->s_bdev. And besides, all freeze_bdev does is get an active reference on the superblock and call freeze_super().

Quoted 6 lines

Also, that's traversing the list of superblock with locking and dereferencing the superblock without properly checking that the superblock is not being torn down. You should probably use iterate_supers (or at least copy the code), with a function that drops the s_umount read lock befor calling freeze_super() and then picks it back up afterwards.

So, what about the patch below? It appears to work on my test boxes.

Thanks,
Rafael

---
From: Rafael J. Wysocki <[email protected]>
Subject: PM / Freezer: Freeze filesystems while freezing processes (v3)

Freeze all filesystems during the freezing of tasks by calling freeze_super() for all superblocks and thaw them during the thawing of tasks with the help of thaw_super().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---
 fs/super.c             |   70 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    3 ++
 kernel/power/process.c |    9 +++++-
 3 files changed, 81 insertions(+), 1 deletion(-)
include/linux/fs.h +3 -0
Index: linux/include/linux/fs.h
===================================================================
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* Frozen filesystem */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2497,6 +2498,8 @@ extern void drop_super(struct super_bloc
 extern void iterate_supers(void (*)(struct super_block *, void *), void *);
 extern void iterate_supers_type(struct file_system_type *,
 			        void (*)(struct super_block *, void *), void *);
+extern int freeze_supers(void);
+extern void thaw_supers(void);
 
 extern int dcache_dir_open(struct inode *, struct file *);
 extern int dcache_dir_close(struct inode *, struct file *);
kernel/power/process.c +8 -1
Index: linux/kernel/power/process.c
===================================================================
@@ -12,10 +12,10 @@
 #include <linux/oom.h>
 #include <linux/suspend.h>
 #include <linux/module.h>
-#include <linux/syscalls.h>
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/fs.h>
 
 /* 
  * Timeout for stopping processes
@@ -147,6 +147,12 @@ int freeze_processes(void)
 		goto Exit;
 	printk("done.\n");
 
+	printk("Freezing filesystems ... ");
+	error = freeze_supers();
+	if (error)
+		goto Exit;
+	printk("done.\n");
+
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
 	if (error)
@@ -188,6 +194,7 @@ void thaw_processes(void)
 	printk("Restarting tasks ... ");
 	thaw_workqueues();
 	thaw_tasks(true);
+	thaw_supers();
 	thaw_tasks(false);
 	schedule();
 	printk("done.\n");
fs/super.c +70 -0

76 lines not on this page · raw message

#18 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

In reply to Dave Chinner
Quoted 21 lines · Dave Chinner
Quoted 20 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

Quoted 4 lines
Quoted 4 lines

This change is based on earlier work by Nigel Cunningham.

---

Below is an alternative fix, the changelog pretty much explains the idea.

I've tested it on Toshiba Portege R500, but I don't have an XFS partition to verify that it really helps, so I'd appreciate it if someone able to reproduce the original issue could test it and report back.

Thanks,
Rafael

---
From: Rafael J. Wysocki <[email protected]>
Subject: PM / Hibernate: Freeze kernel threads after preallocating memory

There is a problem with the current ordering of hibernate code which leads to deadlocks in some filesystems' memory shrinkers. Namely, some filesystems use freezable kernel threads that are inactive when the hibernate memory preallocation is carried out. Those same filesystems use memory shrinkers that may be triggered by the hibernate memory preallocation. If those memory shrinkers wait for the frozen kernel threads, the hibernate process deadlocks (this happens with XFS, for one example).

Apparently, it is not technically viable to redesign the filesystems in question to avoid the situation described above, so the only possible solution of this issue is to defer the freezing of kernel threads until the hibernate memory preallocation is done, which is implemented by this change.

---
 include/linux/freezer.h  |    4 +++-
 kernel/power/hibernate.c |   12 ++++++++----
 kernel/power/power.h     |    3 ++-
 kernel/power/process.c   |   30 ++++++++++++++++++++----------
 4 files changed, 33 insertions(+), 16 deletions(-)
kernel/power/process.c +20 -10
Index: linux/kernel/power/process.c
===================================================================
@@ -135,7 +135,7 @@ static int try_to_freeze_tasks(bool sig_
 }
 
 /**
- *	freeze_processes - tell processes to enter the refrigerator
+ * freeze_processes - Signal user space processes to enter the refrigerator.
  */
 int freeze_processes(void)
 {
@@ -143,20 +143,30 @@ int freeze_processes(void)
 
 	printk("Freezing user space processes ... ");
 	error = try_to_freeze_tasks(true);
-	if (error)
-		goto Exit;
-	printk("done.\n");
+	if (!error) {
+		printk("done.");
+		oom_killer_disable();
+	}
+	printk("\n");
+	BUG_ON(in_atomic());
+
+	return error;
+}
+
+/**
+ * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
+ */
+int freeze_kernel_threads(void)
+{
+	int error;
 
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
-	if (error)
-		goto Exit;
-	printk("done.");
+	if (!error)
+		printk("done.");
 
-	oom_killer_disable();
- Exit:
-	BUG_ON(in_atomic());
 	printk("\n");
+	BUG_ON(in_atomic());
 
 	return error;
 }
include/linux/freezer.h +3 -1
Index: linux/include/linux/freezer.h
===================================================================
@@ -49,6 +49,7 @@ extern int thaw_process(struct task_stru
 
 extern void refrigerator(void);
 extern int freeze_processes(void);
+extern int freeze_kernel_threads(void);
 extern void thaw_processes(void);
 
 static inline int try_to_freeze(void)
@@ -171,7 +172,8 @@ static inline void clear_freeze_flag(str
 static inline int thaw_process(struct task_struct *p) { return 1; }
 
 static inline void refrigerator(void) {}
-static inline int freeze_processes(void) { BUG(); return 0; }
+static inline int freeze_processes(void) { return -ENOSYS; }
+static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 static inline void thaw_processes(void) {}
 
 static inline int try_to_freeze(void) { return 0; }
kernel/power/power.h +2 -1
Index: linux/kernel/power/power.h
===================================================================
@@ -228,7 +228,8 @@ extern int pm_test_level;
 #ifdef CONFIG_SUSPEND_FREEZER
 static inline int suspend_freeze_processes(void)
 {
-	return freeze_processes();
+	int error = freeze_processes();
+	return error ? : freeze_kernel_threads();
 }
 
 static inline void suspend_thaw_processes(void)
kernel/power/hibernate.c +0 -3
Index: linux/kernel/power/hibernate.c
===================================================================
@@ -334,13 +334,17 @@ int hibernation_snapshot(int platform_mo
 	if (error)
 		goto Close;
 
-	error = dpm_prepare(PMSG_FREEZE);
-	if (error)
-		goto Complete_devices;
#19 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Hi.

Quoted 49 lines · Rafael J. Wysocki
Quoted 21 lines · Dave Chinner
Quoted 20 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

Quoted 4 lines
Quoted 4 lines

This change is based on earlier work by Nigel Cunningham.

---

Below is an alternative fix, the changelog pretty much explains the idea.

I've tested it on Toshiba Portege R500, but I don't have an XFS partition to verify that it really helps, so I'd appreciate it if someone able to reproduce the original issue could test it and report back.

Thanks,
Rafael

---
From: Rafael J. Wysocki <[email protected]>
Subject: PM / Hibernate: Freeze kernel threads after preallocating memory

There is a problem with the current ordering of hibernate code which leads to deadlocks in some filesystems' memory shrinkers. Namely, some filesystems use freezable kernel threads that are inactive when the hibernate memory preallocation is carried out. Those same filesystems use memory shrinkers that may be triggered by the hibernate memory preallocation. If those memory shrinkers wait for the frozen kernel threads, the hibernate process deadlocks (this happens with XFS, for one example).

Quoted 7 lines

Apparently, it is not technically viable to redesign the filesystems in question to avoid the situation described above, so the only possible solution of this issue is to defer the freezing of kernel threads until the hibernate memory preallocation is done, which is implemented by this change.

TuxOnIce has the following logic at the moment: Freeze all threads. Calculate whether we have enough memory for the image, thaw kernel threads only, free memory and try again if it looks like we don't have enough. I've never heard of a deadlock, though I suppose one would be possible if you had the added complication of userspace drivers/filesystems - it would be good to be able to distinguish and thaw them.

It does this prior to the atomic copy, using a user-supplied estimate of the amount of memory drivers will need - the actual amount used is show in debugging info at the end of the cycle. Apart from that, if you have everything else frozen, everything else is pretty deterministic (assuming you don't have any memory leaks in your image-writing code).

Regards,

Nigel

Signature · 3 lines
Evolution (n): A hypothetical process whereby improbable
events occur with alarming frequency, order arises from chaos, and
no one is given credit.
#20 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 58 lines · Nigel Cunningham

Hi.

Quoted 55 lines · Rafael J. Wysocki
Quoted 21 lines · Dave Chinner
Quoted 20 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

Quoted 4 lines
Quoted 4 lines

This change is based on earlier work by Nigel Cunningham.

---

Below is an alternative fix, the changelog pretty much explains the idea.

I've tested it on Toshiba Portege R500, but I don't have an XFS partition to verify that it really helps, so I'd appreciate it if someone able to reproduce the original issue could test it and report back.

Thanks,
Rafael

---
From: Rafael J. Wysocki <[email protected]>
Subject: PM / Hibernate: Freeze kernel threads after preallocating memory

There is a problem with the current ordering of hibernate code which leads to deadlocks in some filesystems' memory shrinkers. Namely, some filesystems use freezable kernel threads that are inactive when the hibernate memory preallocation is carried out. Those same filesystems use memory shrinkers that may be triggered by the hibernate memory preallocation. If those memory shrinkers wait for the frozen kernel threads, the hibernate process deadlocks (this happens with XFS, for one example).

Apparently, it is not technically viable to redesign the filesystems in question to avoid the situation described above, so the only possible solution of this issue is to defer the freezing of kernel threads until the hibernate memory preallocation is done, which is implemented by this change.

Quoted 6 lines
Quoted 1 line

TuxOnIce has the following logic at the moment: Freeze all threads. Calculate whether we have enough memory for the image, thaw kernel threads only, free memory and try again if it looks like we don't have enough.

Well, it seems that the freezing of kernel threads in the first step is not necessary. You can do (1) freeze user space, (2) check if there's enough free memory, (3) free memory if necessary, (4) freeze kernel threads instead. Which is what my patch does, actually. :-)

Quoted 4 lines

I've never heard of a deadlock, though I suppose one would be possible if you had the added complication of userspace drivers/filesystems - it would be good to be able to distinguish and thaw them.

Yes, there is a known problem with FUSE in that area.

Quoted 5 lines

It does this prior to the atomic copy, using a user-supplied estimate of the amount of memory drivers will need - the actual amount used is show in debugging info at the end of the cycle. Apart from that, if you have everything else frozen, everything else is pretty deterministic (assuming you don't have any memory leaks in your image-writing code).

Thanks,
Rafael

author
#21 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

In reply to Rafael J. Wysocki

test results of the patch below:

1. real machine

suspends fine but on wakeup, after loading image: hard reset. nvidia gpu => disabled compitz => wakeup worked two times.

2. virtualbox / stress test / xfs and ext4

on 3rd resume, it booted up "normal" like this:

[    3.351813] Freeing unused kernel memory: 568k freed
[    3.460973] Freeing unused kernel memory: 284k freed
[   17.328356] PM: Preparing processes for restore.
[   17.328357] Freezing user space processes ...
[   37.345414] Freezing of tasks failed after 20.01 seconds (1 tasks
refusing to freeze, wq_busy=0):
[   37.475244]  ffff88001f06fd68 0000000000000086 0000000000000000
0000000000000000
[   37.526163]  ffff88001f06e010 ffff88001f4c4410 0000000000012ec0
ffff88001f06ffd8
[   37.580110]  ffff88001f06ffd8 0000000000012ec0 ffffffff8160d020
ffff88001f4c4410
[   37.626167] Call Trace:
[   37.626769]  [<ffffffff81049944>] schedule+0x55/0x57
[   37.674925]  [<ffffffff81360dbe>] __mutex_lock_common+0x117/0x178
[   37.792559]  [<ffffffff81113ef2>] ? user_path_at+0x61/0x90
[   37.888501]  [<ffffffff81360e35>] __mutex_lock_slowpath+0x16/0x18
[   37.986966]  [<ffffffff81360efb>] mutex_lock+0x1e/0x32
[   38.086931]  [<ffffffffa00a4d43>] show_manufacturer+0x23/0x51 [usbcore]
[   38.212500]  [<ffffffff8125cd44>] dev_attr_show+0x22/0x49
[   38.282319]  [<ffffffff810c6f8c>] ? __get_free_pages+0x9/0x38
[   38.397449]  [<ffffffff8115febb>] sysfs_read_file+0xa9/0x12b
[   38.491607]  [<ffffffff81107ff6>] vfs_read+0xa6/0x102
[   38.541994]  [<ffffffff81105ebf>] ? do_sys_open+0xee/0x100
[   38.564907]  [<ffffffff8110810b>] sys_read+0x45/0x6c
[   38.578397]  [<ffffffff81368412>] system_call_fastpath+0x16/0x1b
[   38.590083]
[   38.598046] Restarting tasks ... done.
[   38.660448] XFS (sda3): Mounting Filesystem

restarted the test runs, increased delay between awake and sleep from 20 to 25 sec:

36 time successful hibernate+resume so far.

chris

Quoted 168 lines · Rafael J. Wysocki
Quoted 21 lines · Dave Chinner
Quoted 20 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

Quoted 4 lines
Quoted 4 lines

This change is based on earlier work by Nigel Cunningham.

---

Below is an alternative fix, the changelog pretty much explains the idea.

I've tested it on Toshiba Portege R500, but I don't have an XFS partition to verify that it really helps, so I'd appreciate it if someone able to reproduce the original issue could test it and report back.

Thanks,
Rafael

---
From: Rafael J. Wysocki <[email protected]>
Subject: PM / Hibernate: Freeze kernel threads after preallocating memory

There is a problem with the current ordering of hibernate code which leads to deadlocks in some filesystems' memory shrinkers. Namely, some filesystems use freezable kernel threads that are inactive when the hibernate memory preallocation is carried out. Those same filesystems use memory shrinkers that may be triggered by the hibernate memory preallocation. If those memory shrinkers wait for the frozen kernel threads, the hibernate process deadlocks (this happens with XFS, for one example).

Apparently, it is not technically viable to redesign the filesystems in question to avoid the situation described above, so the only possible solution of this issue is to defer the freezing of kernel threads until the hibernate memory preallocation is done, which is implemented by this change.

---
 include/linux/freezer.h  |    4 +++-
 kernel/power/hibernate.c |   12 ++++++++----
 kernel/power/power.h     |    3 ++-
 kernel/power/process.c   |   30 ++++++++++++++++++++----------
 4 files changed, 33 insertions(+), 16 deletions(-)

Index: linux/kernel/power/process.c
===================================================================

kernel/power/process.c +20 -10
@@ -135,7 +135,7 @@ static int try_to_freeze_tasks(bool sig_
 }
 
 /**
- *	freeze_processes - tell processes to enter the refrigerator
+ * freeze_processes - Signal user space processes to enter the refrigerator.
  */
 int freeze_processes(void)
 {
@@ -143,20 +143,30 @@ int freeze_processes(void)
 
 	printk("Freezing user space processes ... ");
 	error = try_to_freeze_tasks(true);
-	if (error)
-		goto Exit;
-	printk("done.\n");
+	if (!error) {
+		printk("done.");
+		oom_killer_disable();
+	}
+	printk("\n");
+	BUG_ON(in_atomic());
+
+	return error;
+}
+
+/**
+ * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
+ */
+int freeze_kernel_threads(void)
+{
+	int error;
 
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
-	if (error)
-		goto Exit;
-	printk("done.");
+	if (!error)
+		printk("done.");
 
-	oom_killer_disable();
- Exit:
-	BUG_ON(in_atomic());
 	printk("\n");
+	BUG_ON(in_atomic());
 
 	return error;
 }

Index: linux/include/linux/freezer.h
===================================================================

include/linux/freezer.h +3 -1
@@ -49,6 +49,7 @@ extern int thaw_process(struct task_stru
 
 extern void refrigerator(void);
 extern int freeze_processes(void);
+extern int freeze_kernel_threads(void);
 extern void thaw_processes(void);
 
 static inline int try_to_freeze(void)
@@ -171,7 +172,8 @@ static inline void clear_freeze_flag(str
 static inline int thaw_process(struct task_struct *p) { return 1; }
 
 static inline void refrigerator(void) {}
-static inline int freeze_processes(void) { BUG(); return 0; }
+static inline int freeze_processes(void) { return -ENOSYS; }
+static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 static inline void thaw_processes(void) {}
 
 static inline int try_to_freeze(void) { return 0; }

Index: linux/kernel/power/power.h
===================================================================

kernel/power/power.h +2 -1
@@ -228,7 +228,8 @@ extern int pm_test_level;
 #ifdef CONFIG_SUSPEND_FREEZER
 static inline int suspend_freeze_processes(void)
 {
-	return freeze_processes();
+	int error = freeze_processes();
+	return error ? : freeze_kernel_threads();
 }
 
 static inline void suspend_thaw_processes(void)

Index: linux/kernel/power/hibernate.c
===================================================================

kernel/power/hibernate.c +1 -4
@@ -334,13 +334,17 @@ int hibernation_snapshot(int platform_mo
 	if (error)
 		goto Close;
 
-	error = dpm_prepare(PMSG_FREEZE);
-	if (error)
-		goto Complete_devices;
-
 	/* Preallocate image memory before shutting down devices. */
 	error = hibernate_preallocate_memory();
 	if (error)
+		goto Close;

kernel/power/hibernate.c int hibernation_snapshot(int platform_mo · line 350

Quoted 10 lines
kernel/power/hibernate.c +7 -0
+
+	error = freeze_kernel_threads();
+	if (error)
+		goto Close;
+
+	error = dpm_prepare(PMSG_FREEZE);
+	if (error)
 		goto Complete_devices;
 
 	suspend_console();

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#22 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 6 lines · Christoph

test results of the patch below:

1. real machine

suspends fine but on wakeup, after loading image: hard reset. nvidia gpu => disabled compitz => wakeup worked two times.

Hmm, so there's a separate bug related to NVidia I guess.

Quoted 36 lines

2. virtualbox / stress test / xfs and ext4

on 3rd resume, it booted up "normal" like this:

[    3.351813] Freeing unused kernel memory: 568k freed
[    3.460973] Freeing unused kernel memory: 284k freed
[   17.328356] PM: Preparing processes for restore.
[   17.328357] Freezing user space processes ...
[   37.345414] Freezing of tasks failed after 20.01 seconds (1 tasks
refusing to freeze, wq_busy=0):
[   37.475244]  ffff88001f06fd68 0000000000000086 0000000000000000
0000000000000000
[   37.526163]  ffff88001f06e010 ffff88001f4c4410 0000000000012ec0
ffff88001f06ffd8
[   37.580110]  ffff88001f06ffd8 0000000000012ec0 ffffffff8160d020
ffff88001f4c4410
[   37.626167] Call Trace:
[   37.626769]  [<ffffffff81049944>] schedule+0x55/0x57
[   37.674925]  [<ffffffff81360dbe>] __mutex_lock_common+0x117/0x178
[   37.792559]  [<ffffffff81113ef2>] ? user_path_at+0x61/0x90
[   37.888501]  [<ffffffff81360e35>] __mutex_lock_slowpath+0x16/0x18
[   37.986966]  [<ffffffff81360efb>] mutex_lock+0x1e/0x32
[   38.086931]  [<ffffffffa00a4d43>] show_manufacturer+0x23/0x51 [usbcore]
[   38.212500]  [<ffffffff8125cd44>] dev_attr_show+0x22/0x49
[   38.282319]  [<ffffffff810c6f8c>] ? __get_free_pages+0x9/0x38
[   38.397449]  [<ffffffff8115febb>] sysfs_read_file+0xa9/0x12b
[   38.491607]  [<ffffffff81107ff6>] vfs_read+0xa6/0x102
[   38.541994]  [<ffffffff81105ebf>] ? do_sys_open+0xee/0x100
[   38.564907]  [<ffffffff8110810b>] sys_read+0x45/0x6c
[   38.578397]  [<ffffffff81368412>] system_call_fastpath+0x16/0x1b
[   38.590083]
[   38.598046] Restarting tasks ... done.
[   38.660448] XFS (sda3): Mounting Filesystem
Quoted 4 lines

restarted the test runs, increased delay between awake and sleep from 20 to 25 sec:

36 time successful hibernate+resume so far.

OK, cool. Thanks for testing!

Rafael

Quoted 180 lines · Rafael J. Wysocki
Quoted 178 lines · Dave Chinner
Quoted 21 lines · Rafael J. Wysocki
Quoted 20 lines

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

Quoted 4 lines
Quoted 4 lines

This change is based on earlier work by Nigel Cunningham.

---

Below is an alternative fix, the changelog pretty much explains the idea.

I've tested it on Toshiba Portege R500, but I don't have an XFS partition to verify that it really helps, so I'd appreciate it if someone able to reproduce the original issue could test it and report back.

Thanks,
Rafael

---
From: Rafael J. Wysocki <[email protected]>
Subject: PM / Hibernate: Freeze kernel threads after preallocating memory

There is a problem with the current ordering of hibernate code which leads to deadlocks in some filesystems' memory shrinkers. Namely, some filesystems use freezable kernel threads that are inactive when the hibernate memory preallocation is carried out. Those same filesystems use memory shrinkers that may be triggered by the hibernate memory preallocation. If those memory shrinkers wait for the frozen kernel threads, the hibernate process deadlocks (this happens with XFS, for one example).

Apparently, it is not technically viable to redesign the filesystems in question to avoid the situation described above, so the only possible solution of this issue is to defer the freezing of kernel threads until the hibernate memory preallocation is done, which is implemented by this change.

---
 include/linux/freezer.h  |    4 +++-
 kernel/power/hibernate.c |   12 ++++++++----
 kernel/power/power.h     |    3 ++-
 kernel/power/process.c   |   30 ++++++++++++++++++++----------
 4 files changed, 33 insertions(+), 16 deletions(-)

Index: linux/kernel/power/process.c
===================================================================

kernel/power/process.c +20 -10
@@ -135,7 +135,7 @@ static int try_to_freeze_tasks(bool sig_
 }
 
 /**
- *	freeze_processes - tell processes to enter the refrigerator
+ * freeze_processes - Signal user space processes to enter the refrigerator.
  */
 int freeze_processes(void)
 {
@@ -143,20 +143,30 @@ int freeze_processes(void)
 
 	printk("Freezing user space processes ... ");
 	error = try_to_freeze_tasks(true);
-	if (error)
-		goto Exit;
-	printk("done.\n");
+	if (!error) {
+		printk("done.");
+		oom_killer_disable();
+	}
+	printk("\n");
+	BUG_ON(in_atomic());
+
+	return error;
+}
+
+/**
+ * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
+ */
+int freeze_kernel_threads(void)
+{
+	int error;
 
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
-	if (error)
-		goto Exit;
-	printk("done.");
+	if (!error)
+		printk("done.");
 
-	oom_killer_disable();
- Exit:
-	BUG_ON(in_atomic());
 	printk("\n");
+	BUG_ON(in_atomic());
 
 	return error;
 }

Index: linux/include/linux/freezer.h
===================================================================

include/linux/freezer.h +3 -1
@@ -49,6 +49,7 @@ extern int thaw_process(struct task_stru
 
 extern void refrigerator(void);
 extern int freeze_processes(void);
+extern int freeze_kernel_threads(void);
 extern void thaw_processes(void);
 
 static inline int try_to_freeze(void)
@@ -171,7 +172,8 @@ static inline void clear_freeze_flag(str
 static inline int thaw_process(struct task_struct *p) { return 1; }
 
 static inline void refrigerator(void) {}
-static inline int freeze_processes(void) { BUG(); return 0; }
+static inline int freeze_processes(void) { return -ENOSYS; }
+static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 static inline void thaw_processes(void) {}
 
 static inline int try_to_freeze(void) { return 0; }

Index: linux/kernel/power/power.h
===================================================================

kernel/power/power.h +2 -1
@@ -228,7 +228,8 @@ extern int pm_test_level;
 #ifdef CONFIG_SUSPEND_FREEZER
 static inline int suspend_freeze_processes(void)
 {
-	return freeze_processes();
+	int error = freeze_processes();
+	return error ? : freeze_kernel_threads();
 }
 
 static inline void suspend_thaw_processes(void)

Index: linux/kernel/power/hibernate.c
===================================================================

kernel/power/hibernate.c +8 -4
@@ -334,13 +334,17 @@ int hibernation_snapshot(int platform_mo
 	if (error)
 		goto Close;
 
-	error = dpm_prepare(PMSG_FREEZE);
-	if (error)
-		goto Complete_devices;
-
 	/* Preallocate image memory before shutting down devices. */
 	error = hibernate_preallocate_memory();
 	if (error)
+		goto Close;
+
+	error = freeze_kernel_threads();
+	if (error)
+		goto Close;
+
+	error = dpm_prepare(PMSG_FREEZE);
+	if (error)
 		goto Complete_devices;
 
 	suspend_console();
author
#23 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 9 lines · Rafael J. Wysocki
Quoted 6 lines · Christoph

test results of the patch below:

1. real machine

suspends fine but on wakeup, after loading image: hard reset. nvidia gpu => disabled compitz => wakeup worked two times.

Hmm, so there's a separate bug related to NVidia I guess.

Maybe.

Just made another test: the machine (macbook) woke up, loaded image, thaw. It got stuck at vt#1, displaying console with login. Cursor blinking, but no (usb) keyboard or network enabled. Bricked?!!

On the other hand I've got another box with nvidia gpu:

debian5 32bit
2.6.38.2+ #3 SMP Fri Apr 1
nvidia 260.19.36

It's up since I compiled the kernel: I use it twice a week and I kept it freezed all the time. It was solid rock until today: hard reset on resume. WTF? (I remember this version combo was stable on the macbook but the kernel lacks a solid wireless driver).

There are a stupid situation where you can't debug. What else can go wrong? This is off topic but it's a cute kernel crash while I gave the nouveau driver a chance:

http://events.ccc.de/camp/2011/wiki/File:Dome22.jpg

chris

http://events.ccc.de/camp/2011/wiki/DomeTent

Quoted 10 lines
Quoted 10 lines

2. virtualbox / stress test / xfs and ext4

on 3rd resume, it booted up "normal" like this:

[    3.351813] Freeing unused kernel memory: 568k freed [

3.460973] Freeing unused kernel memory: 284k freed

[   17.328356] PM: Preparing processes for restore.

...

#24 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 20 lines · Christoph
Quoted 9 lines · Rafael J. Wysocki
Quoted 6 lines · Christoph

test results of the patch below:

1. real machine

suspends fine but on wakeup, after loading image: hard reset. nvidia gpu => disabled compitz => wakeup worked two times.

Hmm, so there's a separate bug related to NVidia I guess.

Maybe.

Just made another test: the machine (macbook) woke up, loaded image, thaw. It got stuck at vt#1, displaying console with login. Cursor blinking, but no (usb) keyboard or network enabled. Bricked?!!

On the other hand I've got another box with nvidia gpu:

Quoted 8 lines

debian5 32bit
2.6.38.2+ #3 SMP Fri Apr 1
nvidia 260.19.36

It's up since I compiled the kernel: I use it twice a week and I kept it freezed all the time. It was solid rock until today: hard reset on resume. WTF? (I remember this version combo was stable on the macbook but the kernel lacks a solid wireless driver).

If that's an x86_64 system, there is a known bug causing problems like this to happen. There's a patch fixing it, but not conclusive:
http://marc.info/?l=linux-kernel&m=131653513414314&w=2

Thanks,
Rafael

author
#25 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 25 lines · Rafael J. Wysocki
Quoted 24 lines · Christoph
Quoted 9 lines · Rafael J. Wysocki
Quoted 6 lines · Christoph

test results of the patch below:

1. real machine

suspends fine but on wakeup, after loading image: hard reset. nvidia gpu => disabled compitz => wakeup worked two times.

Hmm, so there's a separate bug related to NVidia I guess.

Maybe.

Just made another test: the machine (macbook) woke up, loaded image, thaw. It got stuck at vt#1, displaying console with login. Cursor blinking, but no (usb) keyboard or network enabled. Bricked?!!

On the other hand I've got another box with nvidia gpu:

debian5 32bit
2.6.38.2+ #3 SMP Fri Apr 1
nvidia 260.19.36

Quoted 8 lines
Quoted 4 lines

It's up since I compiled the kernel: I use it twice a week and I kept it freezed all the time. It was solid rock until today: hard reset on resume. WTF? (I remember this version combo was stable on the macbook but the kernel lacks a solid wireless driver).

If that's an x86_64 system, there is a known bug causing problems like this to happen. There's a patch fixing it, but not conclusive:
http://marc.info/?l=linux-kernel&m=131653513414314&w=2

very good. seems to fix resume, at least the 2 times I tested so far.

tx! :)

chris

Quoted 8 lines

Thanks,
Rafael

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

author
#26 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

In reply to Rafael J. Wysocki
Quoted 14 lines

PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 11 lines · Dave Chinner
Quoted 10 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

...

Quoted 8 lines

Below is an alternative fix, the changelog pretty much explains the idea.

I've tested it on Toshiba Portege R500, but I don't have an XFS partition to verify that it really helps, so I'd appreciate it if someone able to reproduce the original issue could test it and report back.

Hi Rafael!

Well, the kernel bugtracker is still down and I just like to post my experience with kernel (x64) v3.1-rc8/9 + patches. My machine is a MacBookPro, doomed with 4GB RAM running debian.

Bug #1

on the way to hibernate, machine hangs on

"PM: Preallocating image memory..."

this patch worked for me now for weeks:
"[PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)"
https://lkml.org/lkml/2011/9/24/77

I was able to reproduce this bug with virtualbox and tested the patch ~40 cycles.

Bug#2

on resume from hibernate, hard reset (x64 only):
http://marc.info/?l=linux-kernel&m=131653513414314&w=2

With this patch I haven't got this issue again the last weeks.

I wasn't able to reproduce this bug with virtualbox.

I only got one pm-hibernate issue. Last line:

Disabling non-boot CPUs ...

This time I've enabled debug hung task :)

schedule_timeout
...
workqueue_cpu_callback
notifier_call_chain
...
__cpu_notify
_cpu_down
printk
disable_nonboot_cpus
hibernation_snapshot
hibernate
...

Any other idea besides the possibility it's caused by evil earth radiation, isn't it?

Gruss,
chris

Quoted 41 lines · Rafael J. Wysocki
Quoted 20 lines · Christoph
Quoted 9 lines · Rafael J. Wysocki
Quoted 6 lines · Christoph

test results of the patch below:

1. real machine

suspends fine but on wakeup, after loading image: hard reset. nvidia gpu => disabled compitz => wakeup worked two times.

Hmm, so there's a separate bug related to NVidia I guess.

Maybe.

Just made another test: the machine (macbook) woke up, loaded image, thaw. It got stuck at vt#1, displaying console with login. Cursor blinking, but no (usb) keyboard or network enabled. Bricked?!!

On the other hand I've got another box with nvidia gpu:

Quoted 8 lines

debian5 32bit
2.6.38.2+ #3 SMP Fri Apr 1
nvidia 260.19.36

It's up since I compiled the kernel: I use it twice a week and I kept it freezed all the time. It was solid rock until today: hard reset on resume. WTF? (I remember this version combo was stable on the macbook but the kernel lacks a solid wireless driver).

If that's an x86_64 system, there is a known bug causing problems like this to happen. There's a patch fixing it, but not conclusive:
http://marc.info/?l=linux-kernel&m=131653513414314&w=2

Thanks,
Rafael

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#27 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 32 lines · Christoph
Quoted 14 lines

PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 11 lines · Dave Chinner
Quoted 10 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

...

Quoted 8 lines

Below is an alternative fix, the changelog pretty much explains the idea.

I've tested it on Toshiba Portege R500, but I don't have an XFS partition to verify that it really helps, so I'd appreciate it if someone able to reproduce the original issue could test it and report back.

Hi Rafael!

Well, the kernel bugtracker is still down and I just like to post my experience with kernel (x64) v3.1-rc8/9 + patches. My machine is a MacBookPro, doomed with 4GB RAM running debian.

Bug #1

Quoted 7 lines

on the way to hibernate, machine hangs on

"PM: Preallocating image memory..."

this patch worked for me now for weeks:
"[PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)"
https://lkml.org/lkml/2011/9/24/77

This patch is going to be merged into 3.2.

Quoted 9 lines

I was able to reproduce this bug with virtualbox and tested the patch ~40 cycles.

Bug#2

on resume from hibernate, hard reset (x64 only):
http://marc.info/?l=linux-kernel&m=131653513414314&w=2

With this patch I haven't got this issue again the last weeks.

Hmm. This issue appears to be still under investigation to me, but perhaps that's taken too much already.

Takashi, perhaps you can repost the patch as a proper submission? It would be good to have this regression fixed even if we don't know the real source of it.

Quoted 25 lines

I wasn't able to reproduce this bug with virtualbox.

I only got one pm-hibernate issue. Last line:

Disabling non-boot CPUs ...

This time I've enabled debug hung task :)

schedule_timeout
...
workqueue_cpu_callback
notifier_call_chain
...
__cpu_notify
_cpu_down
printk
disable_nonboot_cpus
hibernation_snapshot
hibernate
...

Quoted 2 lines

Any other idea besides the possibility it's caused by evil earth radiation, isn't it?

I'm not exactly sure what happened from your description, care to explain?

Rafael

#28 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 34 lines · Rafael J. Wysocki
Quoted 32 lines · Christoph
Quoted 16 lines

PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 11 lines · Dave Chinner
Quoted 9 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

Quoted 7 lines

Below is an alternative fix, the changelog pretty much explains the idea.

I've tested it on Toshiba Portege R500, but I don't have an XFS partition to verify that it really helps, so I'd appreciate it if someone able to reproduce the original issue could test it and report back.

Well, the kernel bugtracker is still down and I just like to post my experience with kernel (x64) v3.1-rc8/9 + patches. My machine is a MacBookPro, doomed with 4GB RAM running debian.

Bug #1

on the way to hibernate, machine hangs on

Quoted 7 lines
Quoted 5 lines

"PM: Preallocating image memory..."

this patch worked for me now for weeks:
"[PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)"
https://lkml.org/lkml/2011/9/24/77

This patch is going to be merged into 3.2.

Hi,

I was the original reporter of the Bugzilla issue, just didn't know about this thread until recently. Anyway, I'm running 3.2-rc1 now, which contains the alternative fix, and I can confirm that it indeed
works: hibernation does not deadlock on my XFS rooted system anymore during memory preallocation. Thanks everybody for his or her work on the issue!

To add something still, preallocation now ends with a couple of seconds of heavy disk activity, but with several seconds of total inactivity beforehand. Is this warranted by some CPU intensive task at that stage?

Signature · 2 lines
Thanks,
Feri.
#29 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 53 lines · Ferenc Wagner
Quoted 34 lines · Rafael J. Wysocki
Quoted 32 lines · Christoph
Quoted 16 lines

PM / Freezer: Freeze filesystems while freezing processes (v2)

Quoted 11 lines · Dave Chinner
Quoted 9 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

Quoted 7 lines

Below is an alternative fix, the changelog pretty much explains the idea.

I've tested it on Toshiba Portege R500, but I don't have an XFS partition to verify that it really helps, so I'd appreciate it if someone able to reproduce the original issue could test it and report back.

Well, the kernel bugtracker is still down and I just like to post my experience with kernel (x64) v3.1-rc8/9 + patches. My machine is a MacBookPro, doomed with 4GB RAM running debian.

Bug #1

on the way to hibernate, machine hangs on

Quoted 7 lines
Quoted 5 lines

"PM: Preallocating image memory..."

this patch worked for me now for weeks:
"[PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)"
https://lkml.org/lkml/2011/9/24/77

This patch is going to be merged into 3.2.

Hi,

I was the original reporter of the Bugzilla issue, just didn't know about this thread until recently. Anyway, I'm running 3.2-rc1 now, which contains the alternative fix, and I can confirm that it indeed
works: hibernation does not deadlock on my XFS rooted system anymore during memory preallocation. Thanks everybody for his or her work on the issue!

Quoted 3 lines

To add something still, preallocation now ends with a couple of seconds of heavy disk activity, but with several seconds of total inactivity beforehand. Is this warranted by some CPU intensive task at that stage?

Quilte frankly, I have no idea.

Thanks,
Rafael

#30 lore raw

PATCH 1/1 PM / Hibernate: Freeze kernel threads after preallocating memory

In reply to Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

There is a problem with the current ordering of hibernate code which leads to deadlocks in some filesystems' memory shrinkers. Namely, some filesystems use freezable kernel threads that are inactive when the hibernate memory preallocation is carried out. Those same filesystems use memory shrinkers that may be triggered by the hibernate memory preallocation. If those memory shrinkers wait for the frozen kernel threads, the hibernate process deadlocks (this happens with XFS, for one example).

Apparently, it is not technically viable to redesign the filesystems in question to avoid the situation described above, so the only possible solution of this issue is to defer the freezing of kernel threads until the hibernate memory preallocation is done, which is implemented by this change.

Unfortunately, this requires the memory preallocation to be done before the "prepare" stage of device freeze, so after this change the only way drivers can allocate additional memory for their freeze routines in a clean way is to use PM notifiers.

---
 Documentation/power/devices.txt |    4 ----
 include/linux/freezer.h         |    4 +++-
 kernel/power/hibernate.c        |   12 ++++++++----
 kernel/power/power.h            |    3 ++-
 kernel/power/process.c          |   30 ++++++++++++++++++++----------
 5 files changed, 33 insertions(+), 20 deletions(-)
kernel/power/process.c +20 -10
Index: linux/kernel/power/process.c
===================================================================
@@ -135,7 +135,7 @@ static int try_to_freeze_tasks(bool sig_
 }
 
 /**
- *	freeze_processes - tell processes to enter the refrigerator
+ * freeze_processes - Signal user space processes to enter the refrigerator.
  */
 int freeze_processes(void)
 {
@@ -143,20 +143,30 @@ int freeze_processes(void)
 
 	printk("Freezing user space processes ... ");
 	error = try_to_freeze_tasks(true);
-	if (error)
-		goto Exit;
-	printk("done.\n");
+	if (!error) {
+		printk("done.");
+		oom_killer_disable();
+	}
+	printk("\n");
+	BUG_ON(in_atomic());
+
+	return error;
+}
+
+/**
+ * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
+ */
+int freeze_kernel_threads(void)
+{
+	int error;
 
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
-	if (error)
-		goto Exit;
-	printk("done.");
+	if (!error)
+		printk("done.");
 
-	oom_killer_disable();
- Exit:
-	BUG_ON(in_atomic());
 	printk("\n");
+	BUG_ON(in_atomic());
 
 	return error;
 }
include/linux/freezer.h +3 -1
Index: linux/include/linux/freezer.h
===================================================================
@@ -49,6 +49,7 @@ extern int thaw_process(struct task_stru
 
 extern void refrigerator(void);
 extern int freeze_processes(void);
+extern int freeze_kernel_threads(void);
 extern void thaw_processes(void);
 
 static inline int try_to_freeze(void)
@@ -171,7 +172,8 @@ static inline void clear_freeze_flag(str
 static inline int thaw_process(struct task_struct *p) { return 1; }
 
 static inline void refrigerator(void) {}
-static inline int freeze_processes(void) { BUG(); return 0; }
+static inline int freeze_processes(void) { return -ENOSYS; }
+static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 static inline void thaw_processes(void) {}
 
 static inline int try_to_freeze(void) { return 0; }
kernel/power/power.h +2 -1
Index: linux/kernel/power/power.h
===================================================================
@@ -228,7 +228,8 @@ extern int pm_test_level;
 #ifdef CONFIG_SUSPEND_FREEZER
 static inline int suspend_freeze_processes(void)
 {
-	return freeze_processes();
+	int error = freeze_processes();
+	return error ? : freeze_kernel_threads();
 }
 
 static inline void suspend_thaw_processes(void)
kernel/power/hibernate.c +8 -4
Index: linux/kernel/power/hibernate.c
===================================================================
@@ -334,13 +334,17 @@ int hibernation_snapshot(int platform_mo
 	if (error)
 		goto Close;
 
-	error = dpm_prepare(PMSG_FREEZE);
-	if (error)
-		goto Complete_devices;
-
 	/* Preallocate image memory before shutting down devices. */
 	error = hibernate_preallocate_memory();
 	if (error)
+		goto Close;
+
+	error = freeze_kernel_threads();
+	if (error)
+		goto Close;
+
+	error = dpm_prepare(PMSG_FREEZE);
+	if (error)
 		goto Complete_devices;
 
 	suspend_console();
Documentation/power/devices.txt +0 -4
Index: linux/Documentation/power/devices.txt
===================================================================
@@ -279,10 +279,6 @@ When the system goes into the standby or
 	time.)  Unlike the other suspend-related phases, during the prepare
 	phase the device tree is traversed top-down.
 
-	In addition to that, if device drivers need to allocate additional
-	memory to be able to hadle device suspend correctly, that should be
-	done in the prepare phase.
-
 	After the prepare callback method returns, no new children may be
 	registered below the device.  The method may also prepare the device or
 	driver in some way for the upcoming system power transition (for

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#31 lore raw

Re: [PATCH] PM / Freezer: Freeze filesystems while freezing processes (v2)

In reply to Rafael J. Wysocki
Quoted 85 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---

OK, so nobody except for Pavel appears to have any comments, so I assume that everyone except for Pavel is fine with the approach, interestingly enough.

I've removed the MS_FROZEN Pavel complained about from freeze_filesystems() and added comments explaining why lockdep_off/on() are used.

Thanks,
Rafael

---
 fs/block_dev.c         |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    6 +++++
 kernel/power/process.c |    7 +++++-
 3 files changed, 68 insertions(+), 1 deletion(-)

Index: linux-2.6/include/linux/fs.h
===================================================================

include/linux/fs.h +6 -0
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* bdev has been frozen */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2047,6 +2048,8 @@ extern struct super_block *freeze_bdev(s
 extern void emergency_thaw_all(void);
 extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
 extern int fsync_bdev(struct block_device *);
+extern void freeze_filesystems(void);
+extern void thaw_filesystems(void);
 #else
 static inline void bd_forget(struct inode *inode) {}
 static inline int sync_blockdev(struct block_device *bdev) { return 0; }
@@ -2061,6 +2064,9 @@ static inline int thaw_bdev(struct block
 {
 	return 0;
 }
+
+static inline void freeze_filesystems(void) {}
+static inline void thaw_filesystems(void) {}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;

Index: linux-2.6/fs/block_dev.c
===================================================================

fs/block_dev.c +6 -0
@@ -314,6 +314,62 @@ out:
 }
 EXPORT_SYMBOL(thaw_bdev);
 
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;

fs/block_dev.c out: · line 332

Quoted 10 lines
fs/block_dev.c +10 -0
+
+	/*
+	 * This is necessary, because some filesystems (e.g. ext3) lock
+	 * mutexes in their .freeze_fs() callbacks and leave them locked for
+	 * their .unfreeze_fs() callbacks to unlock.  This is done under
+	 * bdev->bd_fsfreeze_mutex, which is then released, but it makes
+	 * lockdep think something may be wrong when freeze_bdev() attempts
+	 * to acquire bdev->bd_fsfreeze_mutex for the next filesystem.
+	 */
+	lockdep_off();

I thought those problems were fixed. If they aren't, then they most certainly need to be because holding mutexes over system calls is a bug.

Well, well:

[252182.603134] ================================================
[252182.604832] [ BUG: lock held when returning to user space! ]
[252182.606086] ------------------------------------------------
[252182.607400] xfs_io/4917 is leaving the kernel with locks still held!
[252182.608905] 1 lock held by xfs_io/4917:
[252182.609739]  #0:  (&journal->j_barrier){+.+...}, at: [<ffffffff812a2aaf>] journal_lock_updates+0xef/0x100

<sigh>

Looks like the problem was fixed for ext4, but not ext3. Please report this to the ext3/4 list and get it fixed, don't work around it here.

fs/block_dev.c out: · line 346

Quoted 13 lines
fs/block_dev.c +13 -0
+	/*
+	 * Freeze in reverse order so filesystems depending on others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY))
+			continue;
+
+		freeze_bdev(sb->s_bdev);
+		sb->s_flags |= MS_FROZEN;
+	}

AFAIK, that won't work for btrfs - you have to call freeze_super() directly for btrfs because it has a special relationship with sb->s_bdev. And besides, all freeze_bdev does is get an active reference on the superblock and call freeze_super().

Also, that's traversing the list of superblock with locking and dereferencing the superblock without properly checking that the superblock is not being torn down. You should probably use iterate_supers (or at least copy the code), with a function that drops the s_umount read lock befor calling freeze_super() and then picks it back up afterwards.

Quoted 12 lines
fs/block_dev.c +12 -0
+
+	lockdep_on();
+}
+
+/**
+ * thaw_filesystems - Make all filesystems active again.
+ */
+void thaw_filesystems(void)
+{
+	struct super_block *sb;
+
+	/*

fs/block_dev.c out: · line 368

Quoted 10 lines
fs/block_dev.c +10 -0
+	 * This is necessary for the same reason as in freeze_filesystems()
+	 * above.
+	 */
+	lockdep_off();
+
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

And once again, iterate_supers() is what you want here. And you should only call thaw_bdev() as it needs to do checks other than checking MS_FROZEN e.g. the above will unfreeze filesystems that were already frozen at the time a suspend occurs, and that could lead to corruption depending on why the filesystem was frozen...

Also, you still need to check for a valid sb->s_bdev here, otherwise <splat>.

Cheers,

Dave.

Signature · 2 lines
Dave Chinner
[email protected]
#32 lore raw

PATCH 1/1 PM / Freezer: Freeze filesystems while freezing processes (v2)

In reply to Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---

OK, so nobody except for Pavel appears to have any comments, so I assume that everyone except for Pavel is fine with the approach, interestingly enough.

I've removed the MS_FROZEN Pavel complained about from freeze_filesystems() and added comments explaining why lockdep_off/on() are used.

Thanks,
Rafael

---
 fs/block_dev.c         |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    6 +++++
 kernel/power/process.c |    7 +++++-
 3 files changed, 68 insertions(+), 1 deletion(-)
include/linux/fs.h +6 -0
Index: linux-2.6/include/linux/fs.h
===================================================================
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* bdev has been frozen */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2047,6 +2048,8 @@ extern struct super_block *freeze_bdev(s
 extern void emergency_thaw_all(void);
 extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
 extern int fsync_bdev(struct block_device *);
+extern void freeze_filesystems(void);
+extern void thaw_filesystems(void);
 #else
 static inline void bd_forget(struct inode *inode) {}
 static inline int sync_blockdev(struct block_device *bdev) { return 0; }
@@ -2061,6 +2064,9 @@ static inline int thaw_bdev(struct block
 {
 	return 0;
 }
+
+static inline void freeze_filesystems(void) {}
+static inline void thaw_filesystems(void) {}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;
fs/block_dev.c +56 -0

62 lines not on this page · raw message

kernel/power/process.c +6 -1
Index: linux-2.6/kernel/power/process.c
===================================================================
@@ -12,10 +12,10 @@
 #include <linux/oom.h>
 #include <linux/suspend.h>
 #include <linux/module.h>
-#include <linux/syscalls.h>
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/fs.h>
 
 /* 
  * Timeout for stopping processes
@@ -147,6 +147,10 @@ int freeze_processes(void)
 		goto Exit;
 	printk("done.\n");
 
+	pr_info("Freezing filesystems ... ");
+	freeze_filesystems();
+	pr_info("done.\n");
+
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
 	if (error)
@@ -188,6 +192,7 @@ void thaw_processes(void)
 	printk("Restarting tasks ... ");
 	thaw_workqueues();
 	thaw_tasks(true);
+	thaw_filesystems();
 	thaw_tasks(false);
 	schedule();
 	printk("done.\n");
#33 lore raw

Re: [RFC][PATCH] PM / Freezer: Freeze filesystems along with freezing processes (was: Re: PM / hibernate xfs lock up / xfs_reclaim_inodes_ag)

In reply to Rafael J. Wysocki
Quoted 32 lines · Rafael J. Wysocki
Quoted 20 lines · Pavel Machek

Hi!

Quoted 17 lines

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

Quoted 10 lines

fs/block_dev.c out: · line 324

Quoted 8 lines
fs/block_dev.c +8 -0
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;
+
+	lockdep_off();

Ouch. So... why do we need to silence this?

Quoted 3 lines

So that it doesn't complain? :-)

I'll need some time to get the exact details here.

So, this is because ext3_freeze() that doesn't call journal_unlock_updates() on success, which quite frankly looks like a bug in ext3 to me. At least that's different from what ext4 does in exactly the same situation (which looks correct).

If ext3_freeze() called journal_unlock_updates() on success too and the call to journal_unlock_updates() is removed from ext3_unfreeze(), we wouldn't need that lockdep_off()/lockdep_on() around the loop.

I need someone with ext3/ext4 knowledge to comment here, though.

Moreover, I'm not sure if other filesystems don't do such things.

Anyway, this is just a false-positive, even with the ext3 code as is.

Quoted 29 lines
Quoted 4 lines
Quoted 4 lines
fs/block_dev.c +4 -0
+	/*
+	 * Freeze in reverse order so filesystems dependant upon others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
Quoted 8 lines

fs/block_dev.c out: · line 334

Quoted 6 lines
fs/block_dev.c +6 -0
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY) ||
+		    (sb->s_flags & MS_FROZEN))
+			continue;

Should we stop NFS from modifying remote server, too?

What do you mean exactly?

Quoted 6 lines

Plus... ext3 writes to read-only filesystems on mount; not sure if it does it later. But RDONLY means 'user cant write to it' not 'bdev will not be modified'. Should we freeze all?

How can 'already frozen' happen?

Quoted 7 lines

fs/block_dev.c out: · line 355

Quoted 5 lines
fs/block_dev.c +5 -0
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

...because we'll unfreeze it even if we did not freeze it...

Quoted 1 line

So we need not check MS_FROZEN in freeze_filesystems(). OK

Thanks,
Rafael

#34 lore raw

Re: [RFC][PATCH] PM / Freezer: Freeze filesystems along with freezing processes (was: Re: PM / hibernate xfs lock up / xfs_reclaim_inodes_ag)

In reply to Pavel Machek
Quoted 20 lines · Pavel Machek

Hi!

Quoted 17 lines

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

Quoted 10 lines

fs/block_dev.c out: · line 324

Quoted 8 lines
fs/block_dev.c +8 -0
+/**
+ * freeze_filesystems - Force all filesystems into a consistent state.
+ */
+void freeze_filesystems(void)
+{
+	struct super_block *sb;
+
+	lockdep_off();

Ouch. So... why do we need to silence this?

So that it doesn't complain? :-)

I'll need some time to get the exact details here.

Quoted 4 lines
Quoted 4 lines
fs/block_dev.c +4 -0
+	/*
+	 * Freeze in reverse order so filesystems dependant upon others are
+	 * frozen in the right order (eg. loopback on ext3).
+	 */
Quoted 8 lines

fs/block_dev.c out: · line 334

Quoted 6 lines
fs/block_dev.c +6 -0
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
+		if (!sb->s_root || !sb->s_bdev ||
+		    (sb->s_frozen == SB_FREEZE_TRANS) ||
+		    (sb->s_flags & MS_RDONLY) ||
+		    (sb->s_flags & MS_FROZEN))
+			continue;

Should we stop NFS from modifying remote server, too?

What do you mean exactly?

Quoted 6 lines

Plus... ext3 writes to read-only filesystems on mount; not sure if it does it later. But RDONLY means 'user cant write to it' not 'bdev will not be modified'. Should we freeze all?

How can 'already frozen' happen?

Quoted 7 lines

fs/block_dev.c out: · line 355

Quoted 5 lines
fs/block_dev.c +5 -0
+	list_for_each_entry(sb, &super_blocks, s_list)
+		if (sb->s_flags & MS_FROZEN) {
+			sb->s_flags &= ~MS_FROZEN;
+			thaw_bdev(sb->s_bdev, sb);
+		}

...because we'll unfreeze it even if we did not freeze it...

So we need not check MS_FROZEN in freeze_filesystems(). OK

Thanks,
Rafael

#35 lore raw

RFC PATCH 1/1 PM / Freezer: Freeze filesystems along with freezing processes (was: Re: PM / hibernate xfs lock up / xfs_reclaim_inodes_ag)

In reply to Nigel Cunningham
Quoted 10 lines · Nigel Cunningham

Hi.

Quoted 7 lines · Christoph Hellwig
Quoted 5 lines · Rafael J. Wysocki

The Pavel's objection, if I remember it correctly, was that some (or the majority of?) filesystems didn't implement the freezing operation, so they would be more vulnerable to data loss in case of a failing hibernation after this change. However, that's better than actively causing pain to XFS users.

Quoted 8 lines
Quoted 4 lines

The objection never made sense and only means he never read the code. freeze_super (or freeze_bdev back then) always does a sync_filesystem before even checking if we have a freeze method, and sync_filesystem is what we iterate over for each superblock in sync().

I've had freezing supers in TOI for a couple of years now and it has only ever helped. To be honest, if you have a ton of dirty pages, it does result in a big delay, but that's the worst of it.

OK, so below is the revived patch.

To be precise, we don't call sys_sync() from the freezer an more (evidently, I'd removed in myself, but later forgot about that), so it only adds freeze_filesystems() and thaw_filesystems().

Comments welcome.

Thanks,
Rafael

---

Freeze all filesystems during the freezing of tasks by calling freeze_bdev() for each of them and thaw them during the thawing of tasks with the help of thaw_bdev().

This is needed by hibernation, because some filesystems (e.g. XFS) deadlock with the preallocation of memory used by it if the memory pressure caused by it is too heavy.

The additional benefit of this change is that, if something goes wrong after filesystems have been frozen, they will stay in a consistent state and journal replays won't be necessary (e.g. after a failing suspend or resume). In particular, this should help to solve a long-standing issue that in some cases during resume from hibernation the boot loader causes the journal to be replied for the filesystem containing the kernel image and initrd causing it to become inconsistent with the information stored in the hibernation image.

This change is based on earlier work by Nigel Cunningham.

---
 fs/block_dev.c         |   43 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/fs.h     |    6 ++++++
 kernel/power/process.c |    7 ++++++-
 3 files changed, 55 insertions(+), 1 deletion(-)
include/linux/fs.h +6 -0
Index: linux-2.6/include/linux/fs.h
===================================================================
@@ -211,6 +211,7 @@ struct inodes_stat_t {
 #define MS_KERNMOUNT	(1<<22) /* this is a kern_mount call */
 #define MS_I_VERSION	(1<<23) /* Update inode I_version field */
 #define MS_STRICTATIME	(1<<24) /* Always perform atime updates */
+#define MS_FROZEN	(1<<25) /* bdev has been frozen */
 #define MS_NOSEC	(1<<28)
 #define MS_BORN		(1<<29)
 #define MS_ACTIVE	(1<<30)
@@ -2047,6 +2048,8 @@ extern struct super_block *freeze_bdev(s
 extern void emergency_thaw_all(void);
 extern int thaw_bdev(struct block_device *bdev, struct super_block *sb);
 extern int fsync_bdev(struct block_device *);
+extern void freeze_filesystems(void);
+extern void thaw_filesystems(void);
 #else
 static inline void bd_forget(struct inode *inode) {}
 static inline int sync_blockdev(struct block_device *bdev) { return 0; }
@@ -2061,6 +2064,9 @@ static inline int thaw_bdev(struct block
 {
 	return 0;
 }
+
+static inline void freeze_filesystems(void) {}
+static inline void thaw_filesystems(void) {}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;
fs/block_dev.c +43 -0

49 lines not on this page · raw message

kernel/power/process.c +6 -1
Index: linux-2.6/kernel/power/process.c
===================================================================
@@ -12,10 +12,10 @@
 #include <linux/oom.h>
 #include <linux/suspend.h>
 #include <linux/module.h>
-#include <linux/syscalls.h>
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/fs.h>
 
 /* 
  * Timeout for stopping processes
@@ -147,6 +147,10 @@ int freeze_processes(void)
 		goto Exit;
 	printk("done.\n");
 
+	pr_info("Freezing filesystems ... ");
+	freeze_filesystems();
+	pr_info("done.\n");
+
 	printk("Freezing remaining freezable tasks ... ");
 	error = try_to_freeze_tasks(false);
 	if (error)
@@ -188,6 +192,7 @@ void thaw_processes(void)
 	printk("Restarting tasks ... ");
 	thaw_workqueues();
 	thaw_tasks(true);
+	thaw_filesystems();
 	thaw_tasks(false);
 	schedule();
 	printk("done.\n");
#36 lore raw
In reply to Rafael J. Wysocki

Hi!

Quoted 4 lines
Quoted 4 lines
Quoted 1 line

Why don't you simply submit a patch to do that?

a) I don't know how to test suspend/hibernate
b) I don't have any hardware I can test it on.

hibernation should work on any hardware. Just add cmdline parameter resume=<your swap> and use echo disk > /sys/power/state.

suspend is supported on most PCs, and certainly on any notebook. Just echo mem > /sys/power/state.
Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
author
#37 lore raw
Quoted 6 lines · Pavel Machek

Hi!

Quoted 4 lines
Quoted 4 lines
Quoted 1 line

Why don't you simply submit a patch to do that?

a) I don't know how to test suspend/hibernate
b) I don't have any hardware I can test it on.

Hi!

I do apologize fmy silence but I've been in a serious productions the last weeks.

If there any patches to test, let me know. I can run some decent stress tests.

chris

Quoted 7 lines

hibernation should work on any hardware. Just add cmdline parameter resume=<your swap> and use echo disk > /sys/power/state.

suspend is supported on most PCs, and certainly on any notebook. Just echo mem > /sys/power/state.
Pavel

author
#38 lore raw
In reply to Pavel Machek
Quoted 6 lines · Pavel Machek

Hi!

Quoted 4 lines
Quoted 4 lines
Quoted 1 line

Why don't you simply submit a patch to do that?

a) I don't know how to test suspend/hibernate
b) I don't have any hardware I can test it on.

Hi!

I do apologize fmy silence but I've been in a serious productions the last weeks.

If there any patches to test, let me know. I can run some decent stress tests.

chris

Quoted 7 lines

hibernation should work on any hardware. Just add cmdline parameter resume=<your swap> and use echo disk > /sys/power/state.

suspend is supported on most PCs, and certainly on any notebook. Just echo mem > /sys/power/state.
Pavel

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

#39 lore raw
Quoted 9 lines · Christoph
Quoted 6 lines · Pavel Machek

Hi!

Quoted 4 lines
Quoted 4 lines
Quoted 1 line

Why don't you simply submit a patch to do that?

a) I don't know how to test suspend/hibernate
b) I don't have any hardware I can test it on.

Quoted 6 lines

Hi!

I do apologize fmy silence but I've been in a serious productions the last weeks.

If there any patches to test, let me know. I can run some decent stress tests.

Well, please try the one attached to
https://bugzilla.kernel.org/show_bug.cgi?id=33622#c10

Thanks,
Rafael

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs