aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dlmglue.c
diff options
context:
space:
mode:
authorSrinivas Eeda <srinivas.eeda@oracle.com>2012-01-31 00:51:22 -0500
committerJoel Becker <jlbec@evilplan.org>2012-07-04 02:27:15 -0400
commita75e9ccabd925d16954739bd977c54695c9310d0 (patch)
treef3f80253d2fbabdba0fbe35d48482d6a550ea030 /fs/ocfs2/dlmglue.c
parent16865b7c42fbce8a4d2b278460e387e719e289cb (diff)
ocfs2: use spinlock irqsave for downconvert lock.patch
When ocfs2dc thread holds dc_task_lock spinlock and receives soft IRQ it deadlock itself trying to get same spinlock in ocfs2_wake_downconvert_thread. Below is the stack snippet. The patch disables interrupts when acquiring dc_task_lock spinlock. ocfs2_wake_downconvert_thread ocfs2_rw_unlock ocfs2_dio_end_io dio_complete ..... bio_endio req_bio_endio .... scsi_io_completion blk_done_softirq __do_softirq do_softirq irq_exit do_IRQ ocfs2_downconvert_thread [kthread] Signed-off-by: Srinivas Eeda <srinivas.eeda@oracle.com> Signed-off-by: Joel Becker <jlbec@evilplan.org>
Diffstat (limited to 'fs/ocfs2/dlmglue.c')
-rw-r--r--fs/ocfs2/dlmglue.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 274529cce9c..4f7795fb5fc 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -3932,6 +3932,8 @@ unqueue:
3932static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, 3932static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
3933 struct ocfs2_lock_res *lockres) 3933 struct ocfs2_lock_res *lockres)
3934{ 3934{
3935 unsigned long flags;
3936
3935 assert_spin_locked(&lockres->l_lock); 3937 assert_spin_locked(&lockres->l_lock);
3936 3938
3937 if (lockres->l_flags & OCFS2_LOCK_FREEING) { 3939 if (lockres->l_flags & OCFS2_LOCK_FREEING) {
@@ -3945,21 +3947,22 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
3945 3947
3946 lockres_or_flags(lockres, OCFS2_LOCK_QUEUED); 3948 lockres_or_flags(lockres, OCFS2_LOCK_QUEUED);
3947 3949
3948 spin_lock(&osb->dc_task_lock); 3950 spin_lock_irqsave(&osb->dc_task_lock, flags);
3949 if (list_empty(&lockres->l_blocked_list)) { 3951 if (list_empty(&lockres->l_blocked_list)) {
3950 list_add_tail(&lockres->l_blocked_list, 3952 list_add_tail(&lockres->l_blocked_list,
3951 &osb->blocked_lock_list); 3953 &osb->blocked_lock_list);
3952 osb->blocked_lock_count++; 3954 osb->blocked_lock_count++;
3953 } 3955 }
3954 spin_unlock(&osb->dc_task_lock); 3956 spin_unlock_irqrestore(&osb->dc_task_lock, flags);
3955} 3957}
3956 3958
3957static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb) 3959static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb)
3958{ 3960{
3959 unsigned long processed; 3961 unsigned long processed;
3962 unsigned long flags;
3960 struct ocfs2_lock_res *lockres; 3963 struct ocfs2_lock_res *lockres;
3961 3964
3962 spin_lock(&osb->dc_task_lock); 3965 spin_lock_irqsave(&osb->dc_task_lock, flags);
3963 /* grab this early so we know to try again if a state change and 3966 /* grab this early so we know to try again if a state change and
3964 * wake happens part-way through our work */ 3967 * wake happens part-way through our work */
3965 osb->dc_work_sequence = osb->dc_wake_sequence; 3968 osb->dc_work_sequence = osb->dc_wake_sequence;
@@ -3972,38 +3975,40 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb)
3972 struct ocfs2_lock_res, l_blocked_list); 3975 struct ocfs2_lock_res, l_blocked_list);
3973 list_del_init(&lockres->l_blocked_list); 3976 list_del_init(&lockres->l_blocked_list);
3974 osb->blocked_lock_count--; 3977 osb->blocked_lock_count--;
3975 spin_unlock(&osb->dc_task_lock); 3978 spin_unlock_irqrestore(&osb->dc_task_lock, flags);
3976 3979
3977 BUG_ON(!processed); 3980 BUG_ON(!processed);
3978 processed--; 3981 processed--;
3979 3982
3980 ocfs2_process_blocked_lock(osb, lockres); 3983 ocfs2_process_blocked_lock(osb, lockres);
3981 3984
3982 spin_lock(&osb->dc_task_lock); 3985 spin_lock_irqsave(&osb->dc_task_lock, flags);
3983 } 3986 }
3984 spin_unlock(&osb->dc_task_lock); 3987 spin_unlock_irqrestore(&osb->dc_task_lock, flags);
3985} 3988}
3986 3989
3987static int ocfs2_downconvert_thread_lists_empty(struct ocfs2_super *osb) 3990static int ocfs2_downconvert_thread_lists_empty(struct ocfs2_super *osb)
3988{ 3991{
3989 int empty = 0; 3992 int empty = 0;
3993 unsigned long flags;
3990 3994
3991 spin_lock(&osb->dc_task_lock); 3995 spin_lock_irqsave(&osb->dc_task_lock, flags);
3992 if (list_empty(&osb->blocked_lock_list)) 3996 if (list_empty(&osb->blocked_lock_list))
3993 empty = 1; 3997 empty = 1;
3994 3998
3995 spin_unlock(&osb->dc_task_lock); 3999 spin_unlock_irqrestore(&osb->dc_task_lock, flags);
3996 return empty; 4000 return empty;
3997} 4001}
3998 4002
3999static int ocfs2_downconvert_thread_should_wake(struct ocfs2_super *osb) 4003static int ocfs2_downconvert_thread_should_wake(struct ocfs2_super *osb)
4000{ 4004{
4001 int should_wake = 0; 4005 int should_wake = 0;
4006 unsigned long flags;
4002 4007
4003 spin_lock(&osb->dc_task_lock); 4008 spin_lock_irqsave(&osb->dc_task_lock, flags);
4004 if (osb->dc_work_sequence != osb->dc_wake_sequence) 4009 if (osb->dc_work_sequence != osb->dc_wake_sequence)
4005 should_wake = 1; 4010 should_wake = 1;
4006 spin_unlock(&osb->dc_task_lock); 4011 spin_unlock_irqrestore(&osb->dc_task_lock, flags);
4007 4012
4008 return should_wake; 4013 return should_wake;
4009} 4014}
@@ -4033,10 +4038,12 @@ static int ocfs2_downconvert_thread(void *arg)
4033 4038
4034void ocfs2_wake_downconvert_thread(struct ocfs2_super *osb) 4039void ocfs2_wake_downconvert_thread(struct ocfs2_super *osb)
4035{ 4040{
4036 spin_lock(&osb->dc_task_lock); 4041 unsigned long flags;
4042
4043 spin_lock_irqsave(&osb->dc_task_lock, flags);
4037 /* make sure the voting thread gets a swipe at whatever changes 4044 /* make sure the voting thread gets a swipe at whatever changes
4038 * the caller may have made to the voting state */ 4045 * the caller may have made to the voting state */
4039 osb->dc_wake_sequence++; 4046 osb->dc_wake_sequence++;
4040 spin_unlock(&osb->dc_task_lock); 4047 spin_unlock_irqrestore(&osb->dc_task_lock, flags);
4041 wake_up(&osb->dc_event); 4048 wake_up(&osb->dc_event);
4042} 4049}