diff options
author | Xue jiufei <xuejiufei@huawei.com> | 2014-06-04 19:06:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 19:53:54 -0400 |
commit | a9e9acaeb0a981a6dfa54b32dd756103aeefa6a7 (patch) | |
tree | 132b64a3d1e5c79a76c903a58f4f335869f87f5f | |
parent | c253ed1f6fd68df8542efed2d6b7656c3324f3e4 (diff) |
ocfs2: fix umount hang while shutting down truncate log
Revert commit 75f82eaa502c ("ocfs2: fix NULL pointer dereference when
dismount and ocfs2rec simultaneously") because it may cause a umount
hang while shutting down the truncate log.
fix NULL pointer dereference when dismount and ocfs2rec simultaneously
The situation is as followes:
ocfs2_dismout_volume
-> ocfs2_recovery_exit
-> free osb->recovery_map
-> ocfs2_truncate_shutdown
-> lock global bitmap inode
-> ocfs2_wait_for_recovery
-> check whether osb->recovery_map->rm_used is zero
Because osb->recovery_map is already freed, rm_used can be any other
values, so it may yield umount hang.
To prevent NULL pointer dereference while getting sys_root_inode, we use
a osb_tl_disable flag to disable schedule osb_truncate_log_wq after
truncate log shutdown.
Signed-off-by: joyce.xue <xuejiufei@huawei.com>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/ocfs2/alloc.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2.h | 1 |
2 files changed, 6 insertions, 1 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index b4deb5f750d9..9d8fcf2f3b94 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -6046,7 +6046,8 @@ static void ocfs2_truncate_log_worker(struct work_struct *work) | |||
6046 | void ocfs2_schedule_truncate_log_flush(struct ocfs2_super *osb, | 6046 | void ocfs2_schedule_truncate_log_flush(struct ocfs2_super *osb, |
6047 | int cancel) | 6047 | int cancel) |
6048 | { | 6048 | { |
6049 | if (osb->osb_tl_inode) { | 6049 | if (osb->osb_tl_inode && |
6050 | atomic_read(&osb->osb_tl_disable) == 0) { | ||
6050 | /* We want to push off log flushes while truncates are | 6051 | /* We want to push off log flushes while truncates are |
6051 | * still running. */ | 6052 | * still running. */ |
6052 | if (cancel) | 6053 | if (cancel) |
@@ -6223,6 +6224,8 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb) | |||
6223 | int status; | 6224 | int status; |
6224 | struct inode *tl_inode = osb->osb_tl_inode; | 6225 | struct inode *tl_inode = osb->osb_tl_inode; |
6225 | 6226 | ||
6227 | atomic_set(&osb->osb_tl_disable, 1); | ||
6228 | |||
6226 | if (tl_inode) { | 6229 | if (tl_inode) { |
6227 | cancel_delayed_work(&osb->osb_truncate_log_wq); | 6230 | cancel_delayed_work(&osb->osb_truncate_log_wq); |
6228 | flush_workqueue(ocfs2_wq); | 6231 | flush_workqueue(ocfs2_wq); |
@@ -6254,6 +6257,7 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb) | |||
6254 | * until we're sure all is well. */ | 6257 | * until we're sure all is well. */ |
6255 | INIT_DELAYED_WORK(&osb->osb_truncate_log_wq, | 6258 | INIT_DELAYED_WORK(&osb->osb_truncate_log_wq, |
6256 | ocfs2_truncate_log_worker); | 6259 | ocfs2_truncate_log_worker); |
6260 | atomic_set(&osb->osb_tl_disable, 0); | ||
6257 | osb->osb_tl_bh = tl_bh; | 6261 | osb->osb_tl_bh = tl_bh; |
6258 | osb->osb_tl_inode = tl_inode; | 6262 | osb->osb_tl_inode = tl_inode; |
6259 | 6263 | ||
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 8d64a97a9d5e..bbec539230fd 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -422,6 +422,7 @@ struct ocfs2_super | |||
422 | struct inode *osb_tl_inode; | 422 | struct inode *osb_tl_inode; |
423 | struct buffer_head *osb_tl_bh; | 423 | struct buffer_head *osb_tl_bh; |
424 | struct delayed_work osb_truncate_log_wq; | 424 | struct delayed_work osb_truncate_log_wq; |
425 | atomic_t osb_tl_disable; | ||
425 | /* | 426 | /* |
426 | * How many clusters in our truncate log. | 427 | * How many clusters in our truncate log. |
427 | * It must be protected by osb_tl_inode->i_mutex. | 428 | * It must be protected by osb_tl_inode->i_mutex. |