diff options
author | Kurt Hackel <kurt.hackel@oracle.com> | 2007-01-05 18:00:17 -0500 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-02-07 15:00:57 -0500 |
commit | ddc09c8ddac8d0f170ba8caa8128801f358dccff (patch) | |
tree | bba638e3017266b87e165eb0312d0671164f8917 /fs/ocfs2/dlm/dlmthread.c | |
parent | faf0ec9f13defb57f4269ecb22ed86f2874ee89a (diff) |
ocfs2_dlm: Fixes race between migrate and dirty
dlmthread was removing lockres' from the dirty list
and resetting the dirty flag before shuffling the list.
This patch retains the dirty state flag until the lists
are shuffled.
Signed-off-by: Kurt Hackel <kurt.hackel@oracle.com>
Signed-off-by: Sunil Mushran <Sunil.Mushran@oracle.com>
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/dlm/dlmthread.c')
-rw-r--r-- | fs/ocfs2/dlm/dlmthread.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index baa99979904c..3b94e4dec351 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c | |||
@@ -95,7 +95,7 @@ int __dlm_lockres_has_locks(struct dlm_lock_resource *res) | |||
95 | int __dlm_lockres_unused(struct dlm_lock_resource *res) | 95 | int __dlm_lockres_unused(struct dlm_lock_resource *res) |
96 | { | 96 | { |
97 | if (!__dlm_lockres_has_locks(res) && | 97 | if (!__dlm_lockres_has_locks(res) && |
98 | list_empty(&res->dirty)) { | 98 | (list_empty(&res->dirty) && !(res->state & DLM_LOCK_RES_DIRTY))) { |
99 | /* try not to scan the bitmap unless the first two | 99 | /* try not to scan the bitmap unless the first two |
100 | * conditions are already true */ | 100 | * conditions are already true */ |
101 | int bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); | 101 | int bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); |
@@ -455,12 +455,17 @@ void __dlm_dirty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) | |||
455 | assert_spin_locked(&res->spinlock); | 455 | assert_spin_locked(&res->spinlock); |
456 | 456 | ||
457 | /* don't shuffle secondary queues */ | 457 | /* don't shuffle secondary queues */ |
458 | if ((res->owner == dlm->node_num) && | 458 | if ((res->owner == dlm->node_num)) { |
459 | !(res->state & DLM_LOCK_RES_DIRTY)) { | 459 | if (res->state & (DLM_LOCK_RES_MIGRATING | |
460 | /* ref for dirty_list */ | 460 | DLM_LOCK_RES_BLOCK_DIRTY)) |
461 | dlm_lockres_get(res); | 461 | return; |
462 | list_add_tail(&res->dirty, &dlm->dirty_list); | 462 | |
463 | res->state |= DLM_LOCK_RES_DIRTY; | 463 | if (list_empty(&res->dirty)) { |
464 | /* ref for dirty_list */ | ||
465 | dlm_lockres_get(res); | ||
466 | list_add_tail(&res->dirty, &dlm->dirty_list); | ||
467 | res->state |= DLM_LOCK_RES_DIRTY; | ||
468 | } | ||
464 | } | 469 | } |
465 | } | 470 | } |
466 | 471 | ||
@@ -639,7 +644,7 @@ static int dlm_thread(void *data) | |||
639 | dlm_lockres_get(res); | 644 | dlm_lockres_get(res); |
640 | 645 | ||
641 | spin_lock(&res->spinlock); | 646 | spin_lock(&res->spinlock); |
642 | res->state &= ~DLM_LOCK_RES_DIRTY; | 647 | /* We clear the DLM_LOCK_RES_DIRTY state once we shuffle lists below */ |
643 | list_del_init(&res->dirty); | 648 | list_del_init(&res->dirty); |
644 | spin_unlock(&res->spinlock); | 649 | spin_unlock(&res->spinlock); |
645 | spin_unlock(&dlm->spinlock); | 650 | spin_unlock(&dlm->spinlock); |
@@ -663,10 +668,11 @@ static int dlm_thread(void *data) | |||
663 | /* it is now ok to move lockreses in these states | 668 | /* it is now ok to move lockreses in these states |
664 | * to the dirty list, assuming that they will only be | 669 | * to the dirty list, assuming that they will only be |
665 | * dirty for a short while. */ | 670 | * dirty for a short while. */ |
671 | BUG_ON(res->state & DLM_LOCK_RES_MIGRATING); | ||
666 | if (res->state & (DLM_LOCK_RES_IN_PROGRESS | | 672 | if (res->state & (DLM_LOCK_RES_IN_PROGRESS | |
667 | DLM_LOCK_RES_MIGRATING | | ||
668 | DLM_LOCK_RES_RECOVERING)) { | 673 | DLM_LOCK_RES_RECOVERING)) { |
669 | /* move it to the tail and keep going */ | 674 | /* move it to the tail and keep going */ |
675 | res->state &= ~DLM_LOCK_RES_DIRTY; | ||
670 | spin_unlock(&res->spinlock); | 676 | spin_unlock(&res->spinlock); |
671 | mlog(0, "delaying list shuffling for in-" | 677 | mlog(0, "delaying list shuffling for in-" |
672 | "progress lockres %.*s, state=%d\n", | 678 | "progress lockres %.*s, state=%d\n", |
@@ -687,6 +693,7 @@ static int dlm_thread(void *data) | |||
687 | 693 | ||
688 | /* called while holding lockres lock */ | 694 | /* called while holding lockres lock */ |
689 | dlm_shuffle_lists(dlm, res); | 695 | dlm_shuffle_lists(dlm, res); |
696 | res->state &= ~DLM_LOCK_RES_DIRTY; | ||
690 | spin_unlock(&res->spinlock); | 697 | spin_unlock(&res->spinlock); |
691 | 698 | ||
692 | dlm_lockres_calc_usage(dlm, res); | 699 | dlm_lockres_calc_usage(dlm, res); |
@@ -697,11 +704,8 @@ in_progress: | |||
697 | /* if the lock was in-progress, stick | 704 | /* if the lock was in-progress, stick |
698 | * it on the back of the list */ | 705 | * it on the back of the list */ |
699 | if (delay) { | 706 | if (delay) { |
700 | /* ref for dirty_list */ | ||
701 | dlm_lockres_get(res); | ||
702 | spin_lock(&res->spinlock); | 707 | spin_lock(&res->spinlock); |
703 | list_add_tail(&res->dirty, &dlm->dirty_list); | 708 | __dlm_dirty_lockres(dlm, res); |
704 | res->state |= DLM_LOCK_RES_DIRTY; | ||
705 | spin_unlock(&res->spinlock); | 709 | spin_unlock(&res->spinlock); |
706 | } | 710 | } |
707 | dlm_lockres_put(res); | 711 | dlm_lockres_put(res); |