diff options
| -rw-r--r-- | fs/ocfs2/dlm/dlmcommon.h | 12 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmmaster.c | 135 |
2 files changed, 63 insertions, 84 deletions
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index 4bdf7baee34..1aac42a2974 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h | |||
| @@ -401,6 +401,18 @@ static inline int dlm_lvb_is_empty(char *lvb) | |||
| 401 | return 1; | 401 | return 1; |
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | static inline char *dlm_list_in_text(enum dlm_lockres_list idx) | ||
| 405 | { | ||
| 406 | if (idx == DLM_GRANTED_LIST) | ||
| 407 | return "granted"; | ||
| 408 | else if (idx == DLM_CONVERTING_LIST) | ||
| 409 | return "converting"; | ||
| 410 | else if (idx == DLM_BLOCKED_LIST) | ||
| 411 | return "blocked"; | ||
| 412 | else | ||
| 413 | return "unknown"; | ||
| 414 | } | ||
| 415 | |||
| 404 | static inline struct list_head * | 416 | static inline struct list_head * |
| 405 | dlm_list_idx_to_ptr(struct dlm_lock_resource *res, enum dlm_lockres_list idx) | 417 | dlm_list_idx_to_ptr(struct dlm_lock_resource *res, enum dlm_lockres_list idx) |
| 406 | { | 418 | { |
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 84d166328cf..ec499462894 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
| @@ -2339,65 +2339,55 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data) | |||
| 2339 | dlm_lockres_put(res); | 2339 | dlm_lockres_put(res); |
| 2340 | } | 2340 | } |
| 2341 | 2341 | ||
| 2342 | /* Checks whether the lockres can be migrated. Returns 0 if yes, < 0 | 2342 | /* |
| 2343 | * if not. If 0, numlocks is set to the number of locks in the lockres. | 2343 | * A migrateable resource is one that is : |
| 2344 | * 1. locally mastered, and, | ||
| 2345 | * 2. zero local locks, and, | ||
| 2346 | * 3. one or more non-local locks, or, one or more references | ||
| 2347 | * Returns 1 if yes, 0 if not. | ||
| 2344 | */ | 2348 | */ |
| 2345 | static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm, | 2349 | static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm, |
| 2346 | struct dlm_lock_resource *res, | 2350 | struct dlm_lock_resource *res) |
| 2347 | int *numlocks, | ||
| 2348 | int *hasrefs) | ||
| 2349 | { | 2351 | { |
| 2350 | int ret; | 2352 | enum dlm_lockres_list idx; |
| 2351 | int i; | 2353 | int nonlocal = 0, node_ref; |
| 2352 | int count = 0; | ||
| 2353 | struct list_head *queue; | 2354 | struct list_head *queue; |
| 2354 | struct dlm_lock *lock; | 2355 | struct dlm_lock *lock; |
| 2356 | u64 cookie; | ||
| 2355 | 2357 | ||
| 2356 | assert_spin_locked(&res->spinlock); | 2358 | assert_spin_locked(&res->spinlock); |
| 2357 | 2359 | ||
| 2358 | *numlocks = 0; | 2360 | if (res->owner != dlm->node_num) |
| 2359 | *hasrefs = 0; | 2361 | return 0; |
| 2360 | |||
| 2361 | ret = -EINVAL; | ||
| 2362 | if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { | ||
| 2363 | mlog(0, "cannot migrate lockres with unknown owner!\n"); | ||
| 2364 | goto leave; | ||
| 2365 | } | ||
| 2366 | |||
| 2367 | if (res->owner != dlm->node_num) { | ||
| 2368 | mlog(0, "cannot migrate lockres this node doesn't own!\n"); | ||
| 2369 | goto leave; | ||
| 2370 | } | ||
| 2371 | 2362 | ||
| 2372 | ret = 0; | 2363 | for (idx = DLM_GRANTED_LIST; idx <= DLM_BLOCKED_LIST; idx++) { |
| 2373 | queue = &res->granted; | 2364 | queue = dlm_list_idx_to_ptr(res, idx); |
| 2374 | for (i = 0; i < 3; i++) { | ||
| 2375 | list_for_each_entry(lock, queue, list) { | 2365 | list_for_each_entry(lock, queue, list) { |
| 2376 | ++count; | 2366 | if (lock->ml.node != dlm->node_num) { |
| 2377 | if (lock->ml.node == dlm->node_num) { | 2367 | nonlocal++; |
| 2378 | mlog(0, "found a lock owned by this node still " | 2368 | continue; |
| 2379 | "on the %s queue! will not migrate this " | ||
| 2380 | "lockres\n", (i == 0 ? "granted" : | ||
| 2381 | (i == 1 ? "converting" : | ||
| 2382 | "blocked"))); | ||
| 2383 | ret = -ENOTEMPTY; | ||
| 2384 | goto leave; | ||
| 2385 | } | 2369 | } |
| 2370 | cookie = be64_to_cpu(lock->ml.cookie); | ||
| 2371 | mlog(0, "%s: Not migrateable res %.*s, lock %u:%llu on " | ||
| 2372 | "%s list\n", dlm->name, res->lockname.len, | ||
| 2373 | res->lockname.name, | ||
| 2374 | dlm_get_lock_cookie_node(cookie), | ||
| 2375 | dlm_get_lock_cookie_seq(cookie), | ||
| 2376 | dlm_list_in_text(idx)); | ||
| 2377 | return 0; | ||
| 2386 | } | 2378 | } |
| 2387 | queue++; | ||
| 2388 | } | 2379 | } |
| 2389 | 2380 | ||
| 2390 | *numlocks = count; | 2381 | if (!nonlocal) { |
| 2391 | 2382 | node_ref = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); | |
| 2392 | count = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); | 2383 | if (node_ref >= O2NM_MAX_NODES) |
| 2393 | if (count < O2NM_MAX_NODES) | 2384 | return 0; |
| 2394 | *hasrefs = 1; | 2385 | } |
| 2395 | 2386 | ||
| 2396 | mlog(0, "%s: res %.*s, Migrateable, locks %d, refs %d\n", dlm->name, | 2387 | mlog(0, "%s: res %.*s, Migrateable\n", dlm->name, res->lockname.len, |
| 2397 | res->lockname.len, res->lockname.name, *numlocks, *hasrefs); | 2388 | res->lockname.name); |
| 2398 | 2389 | ||
| 2399 | leave: | 2390 | return 1; |
| 2400 | return ret; | ||
| 2401 | } | 2391 | } |
| 2402 | 2392 | ||
| 2403 | /* | 2393 | /* |
| @@ -2416,7 +2406,6 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, | |||
| 2416 | const char *name; | 2406 | const char *name; |
| 2417 | unsigned int namelen; | 2407 | unsigned int namelen; |
| 2418 | int mle_added = 0; | 2408 | int mle_added = 0; |
| 2419 | int numlocks, hasrefs; | ||
| 2420 | int wake = 0; | 2409 | int wake = 0; |
| 2421 | 2410 | ||
| 2422 | if (!dlm_grab(dlm)) | 2411 | if (!dlm_grab(dlm)) |
| @@ -2427,19 +2416,13 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, | |||
| 2427 | 2416 | ||
| 2428 | mlog(0, "%s: Migrating %.*s to %u\n", dlm->name, namelen, name, target); | 2417 | mlog(0, "%s: Migrating %.*s to %u\n", dlm->name, namelen, name, target); |
| 2429 | 2418 | ||
| 2430 | /* | 2419 | /* Ensure this lockres is a proper candidate for migration */ |
| 2431 | * ensure this lockres is a proper candidate for migration | ||
| 2432 | */ | ||
| 2433 | spin_lock(&res->spinlock); | 2420 | spin_lock(&res->spinlock); |
| 2434 | ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs); | 2421 | ret = dlm_is_lockres_migrateable(dlm, res); |
| 2435 | if (ret < 0) { | ||
| 2436 | spin_unlock(&res->spinlock); | ||
| 2437 | goto leave; | ||
| 2438 | } | ||
| 2439 | spin_unlock(&res->spinlock); | 2422 | spin_unlock(&res->spinlock); |
| 2440 | 2423 | ||
| 2441 | /* no work to do */ | 2424 | /* No work to do */ |
| 2442 | if (numlocks == 0 && !hasrefs) | 2425 | if (!ret) |
| 2443 | goto leave; | 2426 | goto leave; |
| 2444 | 2427 | ||
| 2445 | /* | 2428 | /* |
| @@ -2658,44 +2641,35 @@ leave: | |||
| 2658 | 2641 | ||
| 2659 | dlm_put(dlm); | 2642 | dlm_put(dlm); |
| 2660 | 2643 | ||
| 2661 | mlog(0, "returning %d\n", ret); | 2644 | mlog(0, "%s: Migrating %.*s to %u, returns %d\n", dlm->name, namelen, |
| 2645 | name, target, ret); | ||
| 2662 | return ret; | 2646 | return ret; |
| 2663 | } | 2647 | } |
| 2664 | 2648 | ||
| 2665 | #define DLM_MIGRATION_RETRY_MS 100 | 2649 | #define DLM_MIGRATION_RETRY_MS 100 |
| 2666 | 2650 | ||
| 2667 | /* Should be called only after beginning the domain leave process. | 2651 | /* |
| 2652 | * Should be called only after beginning the domain leave process. | ||
| 2668 | * There should not be any remaining locks on nonlocal lock resources, | 2653 | * There should not be any remaining locks on nonlocal lock resources, |
| 2669 | * and there should be no local locks left on locally mastered resources. | 2654 | * and there should be no local locks left on locally mastered resources. |
| 2670 | * | 2655 | * |
| 2671 | * Called with the dlm spinlock held, may drop it to do migration, but | 2656 | * Called with the dlm spinlock held, may drop it to do migration, but |
| 2672 | * will re-acquire before exit. | 2657 | * will re-acquire before exit. |
| 2673 | * | 2658 | * |
| 2674 | * Returns: 1 if dlm->spinlock was dropped/retaken, 0 if never dropped */ | 2659 | * Returns: 1 if dlm->spinlock was dropped/retaken, 0 if never dropped |
| 2660 | */ | ||
| 2675 | int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) | 2661 | int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) |
| 2676 | { | 2662 | { |
| 2677 | int ret; | 2663 | int mig, ret; |
| 2678 | int lock_dropped = 0; | 2664 | int lock_dropped = 0; |
| 2679 | int numlocks, hasrefs; | ||
| 2680 | 2665 | ||
| 2681 | spin_lock(&res->spinlock); | 2666 | assert_spin_locked(&dlm->spinlock); |
| 2682 | if (res->owner != dlm->node_num) { | ||
| 2683 | if (!__dlm_lockres_unused(res)) { | ||
| 2684 | mlog(ML_ERROR, "%s:%.*s: this node is not master, " | ||
| 2685 | "trying to free this but locks remain\n", | ||
| 2686 | dlm->name, res->lockname.len, res->lockname.name); | ||
| 2687 | } | ||
| 2688 | spin_unlock(&res->spinlock); | ||
| 2689 | goto leave; | ||
| 2690 | } | ||
| 2691 | 2667 | ||
| 2692 | /* No need to migrate a lockres having no locks */ | 2668 | spin_lock(&res->spinlock); |
| 2693 | ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs); | 2669 | mig = dlm_is_lockres_migrateable(dlm, res); |
| 2694 | if (ret >= 0 && numlocks == 0 && !hasrefs) { | ||
| 2695 | spin_unlock(&res->spinlock); | ||
| 2696 | goto leave; | ||
| 2697 | } | ||
| 2698 | spin_unlock(&res->spinlock); | 2670 | spin_unlock(&res->spinlock); |
| 2671 | if (!mig) | ||
| 2672 | goto leave; | ||
| 2699 | 2673 | ||
| 2700 | /* Wheee! Migrate lockres here! Will sleep so drop spinlock. */ | 2674 | /* Wheee! Migrate lockres here! Will sleep so drop spinlock. */ |
| 2701 | spin_unlock(&dlm->spinlock); | 2675 | spin_unlock(&dlm->spinlock); |
| @@ -2704,15 +2678,8 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) | |||
| 2704 | ret = dlm_migrate_lockres(dlm, res, O2NM_MAX_NODES); | 2678 | ret = dlm_migrate_lockres(dlm, res, O2NM_MAX_NODES); |
| 2705 | if (ret >= 0) | 2679 | if (ret >= 0) |
| 2706 | break; | 2680 | break; |
| 2707 | if (ret == -ENOTEMPTY) { | 2681 | mlog(0, "%s: res %.*s, Migrate failed, retrying\n", dlm->name, |
| 2708 | mlog(ML_ERROR, "lockres %.*s still has local locks!\n", | 2682 | res->lockname.len, res->lockname.name); |
| 2709 | res->lockname.len, res->lockname.name); | ||
| 2710 | BUG(); | ||
| 2711 | } | ||
| 2712 | |||
| 2713 | mlog(0, "lockres %.*s: migrate failed, " | ||
| 2714 | "retrying\n", res->lockname.len, | ||
| 2715 | res->lockname.name); | ||
| 2716 | msleep(DLM_MIGRATION_RETRY_MS); | 2683 | msleep(DLM_MIGRATION_RETRY_MS); |
| 2717 | } | 2684 | } |
| 2718 | spin_lock(&dlm->spinlock); | 2685 | spin_lock(&dlm->spinlock); |
