mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +00:00
35ddf78e41
This patch fixes a deadlock, as follows: Node 1 Node 2 Node 3 1)volume a and b are only mount vol a only mount vol b mounted 2) start to mount b start to mount a 3) check hb of Node 3 check hb of Node 2 in vol a, qs_holds++ in vol b, qs_holds++ 4) -------------------- all nodes' network down -------------------- 5) progress of mount b the same situation as failed, and then call Node 2 ocfs2_dismount_volume. but the process is hung, since there is a work in ocfs2_wq cannot beo completed. This work is about vol a, because ocfs2_wq is global wq. BTW, this work which is scheduled in ocfs2_wq is ocfs2_orphan_scan_work, and the context in this work needs to take inode lock of orphan_dir, because lockres owner are Node 1 and all nodes' nework has been down at the same time, so it can't get the inode lock. 6) Why can't this node be fenced when network disconnected? Because the process of mount is hung what caused qs_holds is not equal 0. Because all works in the ocfs2_wq are relative to the super block. The solution is to change the ocfs2_wq from global to local. In other words, move it into struct ocfs2_super. Signed-off-by: Yiwen Jiang <jiangyiwen@huawei.com> Reviewed-by: Joseph Qi <joseph.qi@huawei.com> Cc: Xue jiufei <xuejiufei@huawei.com> Cc: Mark Fasheh <mfasheh@suse.de> Cc: Joel Becker <jlbec@evilplan.org> Cc: Cc: Junxiao Bi <junxiao.bi@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
54 lines
1.6 KiB
C
54 lines
1.6 KiB
C
/* -*- mode: c; c-basic-offset: 8; -*-
|
|
* vim: noexpandtab sw=8 ts=8 sts=0:
|
|
*
|
|
* super.h
|
|
*
|
|
* Function prototypes
|
|
*
|
|
* Copyright (C) 2002, 2004 Oracle. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this program; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 021110-1307, USA.
|
|
*/
|
|
|
|
#ifndef OCFS2_SUPER_H
|
|
#define OCFS2_SUPER_H
|
|
|
|
int ocfs2_publish_get_mount_state(struct ocfs2_super *osb,
|
|
int node_num);
|
|
|
|
__printf(3, 4)
|
|
int __ocfs2_error(struct super_block *sb, const char *function,
|
|
const char *fmt, ...);
|
|
|
|
#define ocfs2_error(sb, fmt, ...) \
|
|
__ocfs2_error(sb, __PRETTY_FUNCTION__, fmt, ##__VA_ARGS__)
|
|
|
|
__printf(3, 4)
|
|
void __ocfs2_abort(struct super_block *sb, const char *function,
|
|
const char *fmt, ...);
|
|
|
|
#define ocfs2_abort(sb, fmt, ...) \
|
|
__ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##__VA_ARGS__)
|
|
|
|
/*
|
|
* Void signal blockers, because in-kernel sigprocmask() only fails
|
|
* when SIG_* is wrong.
|
|
*/
|
|
void ocfs2_block_signals(sigset_t *oldset);
|
|
void ocfs2_unblock_signals(sigset_t *oldset);
|
|
|
|
#endif /* OCFS2_SUPER_H */
|