mirror of
https://github.com/torvalds/linux.git
synced 2024-12-21 02:21:36 +00:00
36b71a8bfb
A deadlock sometimes occurs between dlm_controld closing a lowcomms connection through configfs and dlm_send looking up the address for a new connection in configfs. dlm_controld does a configfs rmdir which calls dlm_lowcomms_close which waits for dlm_send to cancel work on the workqueues. The dlm_send workqueue thread has called tcp_connect_to_sock which calls dlm_nodeid_to_addr which does a configfs lookup and blocks on a lock held by dlm_controld in the rmdir path. The solution here is to save the node addresses within the lowcomms code so that the lowcomms workqueue does not need to step through configfs to get a node address. dlm_controld: wait_for_completion+0x1d/0x20 __cancel_work_timer+0x1b3/0x1e0 cancel_work_sync+0x10/0x20 dlm_lowcomms_close+0x4c/0xb0 [dlm] drop_comm+0x22/0x60 [dlm] client_drop_item+0x26/0x50 [configfs] configfs_rmdir+0x180/0x230 [configfs] vfs_rmdir+0xbd/0xf0 do_rmdir+0x103/0x120 sys_rmdir+0x16/0x20 dlm_send: mutex_lock+0x2b/0x50 get_comm+0x34/0x140 [dlm] dlm_nodeid_to_addr+0x18/0xd0 [dlm] tcp_connect_to_sock+0xf4/0x2d0 [dlm] process_send_sockets+0x1d2/0x260 [dlm] worker_thread+0x170/0x2a0 Signed-off-by: David Teigland <teigland@redhat.com>
98 lines
2.0 KiB
C
98 lines
2.0 KiB
C
/******************************************************************************
|
|
*******************************************************************************
|
|
**
|
|
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
|
|
** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
|
**
|
|
** This copyrighted material is made available to anyone wishing to use,
|
|
** modify, copy, or redistribute it subject to the terms and conditions
|
|
** of the GNU General Public License v.2.
|
|
**
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
#include "dlm_internal.h"
|
|
#include "lockspace.h"
|
|
#include "lock.h"
|
|
#include "user.h"
|
|
#include "memory.h"
|
|
#include "config.h"
|
|
#include "lowcomms.h"
|
|
|
|
static int __init init_dlm(void)
|
|
{
|
|
int error;
|
|
|
|
error = dlm_memory_init();
|
|
if (error)
|
|
goto out;
|
|
|
|
error = dlm_lockspace_init();
|
|
if (error)
|
|
goto out_mem;
|
|
|
|
error = dlm_config_init();
|
|
if (error)
|
|
goto out_lockspace;
|
|
|
|
error = dlm_register_debugfs();
|
|
if (error)
|
|
goto out_config;
|
|
|
|
error = dlm_user_init();
|
|
if (error)
|
|
goto out_debug;
|
|
|
|
error = dlm_netlink_init();
|
|
if (error)
|
|
goto out_user;
|
|
|
|
error = dlm_plock_init();
|
|
if (error)
|
|
goto out_netlink;
|
|
|
|
printk("DLM installed\n");
|
|
|
|
return 0;
|
|
|
|
out_netlink:
|
|
dlm_netlink_exit();
|
|
out_user:
|
|
dlm_user_exit();
|
|
out_debug:
|
|
dlm_unregister_debugfs();
|
|
out_config:
|
|
dlm_config_exit();
|
|
out_lockspace:
|
|
dlm_lockspace_exit();
|
|
out_mem:
|
|
dlm_memory_exit();
|
|
out:
|
|
return error;
|
|
}
|
|
|
|
static void __exit exit_dlm(void)
|
|
{
|
|
dlm_plock_exit();
|
|
dlm_netlink_exit();
|
|
dlm_user_exit();
|
|
dlm_config_exit();
|
|
dlm_memory_exit();
|
|
dlm_lockspace_exit();
|
|
dlm_lowcomms_exit();
|
|
dlm_unregister_debugfs();
|
|
}
|
|
|
|
module_init(init_dlm);
|
|
module_exit(exit_dlm);
|
|
|
|
MODULE_DESCRIPTION("Distributed Lock Manager");
|
|
MODULE_AUTHOR("Red Hat, Inc.");
|
|
MODULE_LICENSE("GPL");
|
|
|
|
EXPORT_SYMBOL_GPL(dlm_new_lockspace);
|
|
EXPORT_SYMBOL_GPL(dlm_release_lockspace);
|
|
EXPORT_SYMBOL_GPL(dlm_lock);
|
|
EXPORT_SYMBOL_GPL(dlm_unlock);
|
|
|