diff options
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/cluster/heartbeat.c | 216 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 8 |
2 files changed, 182 insertions, 42 deletions
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 9f21dd785364..ad2e41d6879d 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -132,6 +132,33 @@ char *o2hb_heartbeat_mode_desc[O2HB_HEARTBEAT_NUM_MODES] = { | |||
132 | unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD; | 132 | unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD; |
133 | unsigned int o2hb_heartbeat_mode = O2HB_HEARTBEAT_LOCAL; | 133 | unsigned int o2hb_heartbeat_mode = O2HB_HEARTBEAT_LOCAL; |
134 | 134 | ||
135 | /* | ||
136 | * o2hb_dependent_users tracks the number of registered callbacks that depend | ||
137 | * on heartbeat. o2net and o2dlm are two entities that register this callback. | ||
138 | * However only o2dlm depends on the heartbeat. It does not want the heartbeat | ||
139 | * to stop while a dlm domain is still active. | ||
140 | */ | ||
141 | unsigned int o2hb_dependent_users; | ||
142 | |||
143 | /* | ||
144 | * In global heartbeat mode, all regions are pinned if there are one or more | ||
145 | * dependent users and the quorum region count is <= O2HB_PIN_CUT_OFF. All | ||
146 | * regions are unpinned if the region count exceeds the cut off or the number | ||
147 | * of dependent users falls to zero. | ||
148 | */ | ||
149 | #define O2HB_PIN_CUT_OFF 3 | ||
150 | |||
151 | /* | ||
152 | * In local heartbeat mode, we assume the dlm domain name to be the same as | ||
153 | * region uuid. This is true for domains created for the file system but not | ||
154 | * necessarily true for userdlm domains. This is a known limitation. | ||
155 | * | ||
156 | * In global heartbeat mode, we pin/unpin all o2hb regions. This solution | ||
157 | * works for both file system and userdlm domains. | ||
158 | */ | ||
159 | static int o2hb_region_pin(const char *region_uuid); | ||
160 | static void o2hb_region_unpin(const char *region_uuid); | ||
161 | |||
135 | /* Only sets a new threshold if there are no active regions. | 162 | /* Only sets a new threshold if there are no active regions. |
136 | * | 163 | * |
137 | * No locking or otherwise interesting code is required for reading | 164 | * No locking or otherwise interesting code is required for reading |
@@ -186,7 +213,9 @@ struct o2hb_region { | |||
186 | struct config_item hr_item; | 213 | struct config_item hr_item; |
187 | 214 | ||
188 | struct list_head hr_all_item; | 215 | struct list_head hr_all_item; |
189 | unsigned hr_unclean_stop:1; | 216 | unsigned hr_unclean_stop:1, |
217 | hr_item_pinned:1, | ||
218 | hr_item_dropped:1; | ||
190 | 219 | ||
191 | /* protected by the hr_callback_sem */ | 220 | /* protected by the hr_callback_sem */ |
192 | struct task_struct *hr_task; | 221 | struct task_struct *hr_task; |
@@ -702,6 +731,14 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg, | |||
702 | config_item_name(®->hr_item)); | 731 | config_item_name(®->hr_item)); |
703 | 732 | ||
704 | set_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); | 733 | set_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); |
734 | |||
735 | /* | ||
736 | * If global heartbeat active, unpin all regions if the | ||
737 | * region count > CUT_OFF | ||
738 | */ | ||
739 | if (o2hb_pop_count(&o2hb_quorum_region_bitmap, | ||
740 | O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF) | ||
741 | o2hb_region_unpin(NULL); | ||
705 | } | 742 | } |
706 | 743 | ||
707 | static int o2hb_check_slot(struct o2hb_region *reg, | 744 | static int o2hb_check_slot(struct o2hb_region *reg, |
@@ -1316,6 +1353,8 @@ int o2hb_init(void) | |||
1316 | memset(o2hb_quorum_region_bitmap, 0, sizeof(o2hb_quorum_region_bitmap)); | 1353 | memset(o2hb_quorum_region_bitmap, 0, sizeof(o2hb_quorum_region_bitmap)); |
1317 | memset(o2hb_failed_region_bitmap, 0, sizeof(o2hb_failed_region_bitmap)); | 1354 | memset(o2hb_failed_region_bitmap, 0, sizeof(o2hb_failed_region_bitmap)); |
1318 | 1355 | ||
1356 | o2hb_dependent_users = 0; | ||
1357 | |||
1319 | return o2hb_debug_init(); | 1358 | return o2hb_debug_init(); |
1320 | } | 1359 | } |
1321 | 1360 | ||
@@ -2003,16 +2042,20 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group, | |||
2003 | { | 2042 | { |
2004 | struct task_struct *hb_task; | 2043 | struct task_struct *hb_task; |
2005 | struct o2hb_region *reg = to_o2hb_region(item); | 2044 | struct o2hb_region *reg = to_o2hb_region(item); |
2045 | int quorum_region = 0; | ||
2006 | 2046 | ||
2007 | /* stop the thread when the user removes the region dir */ | 2047 | /* stop the thread when the user removes the region dir */ |
2008 | spin_lock(&o2hb_live_lock); | 2048 | spin_lock(&o2hb_live_lock); |
2009 | if (o2hb_global_heartbeat_active()) { | 2049 | if (o2hb_global_heartbeat_active()) { |
2010 | clear_bit(reg->hr_region_num, o2hb_region_bitmap); | 2050 | clear_bit(reg->hr_region_num, o2hb_region_bitmap); |
2011 | clear_bit(reg->hr_region_num, o2hb_live_region_bitmap); | 2051 | clear_bit(reg->hr_region_num, o2hb_live_region_bitmap); |
2052 | if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap)) | ||
2053 | quorum_region = 1; | ||
2012 | clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); | 2054 | clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap); |
2013 | } | 2055 | } |
2014 | hb_task = reg->hr_task; | 2056 | hb_task = reg->hr_task; |
2015 | reg->hr_task = NULL; | 2057 | reg->hr_task = NULL; |
2058 | reg->hr_item_dropped = 1; | ||
2016 | spin_unlock(&o2hb_live_lock); | 2059 | spin_unlock(&o2hb_live_lock); |
2017 | 2060 | ||
2018 | if (hb_task) | 2061 | if (hb_task) |
@@ -2030,7 +2073,27 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group, | |||
2030 | if (o2hb_global_heartbeat_active()) | 2073 | if (o2hb_global_heartbeat_active()) |
2031 | printk(KERN_NOTICE "o2hb: Heartbeat stopped on region %s\n", | 2074 | printk(KERN_NOTICE "o2hb: Heartbeat stopped on region %s\n", |
2032 | config_item_name(®->hr_item)); | 2075 | config_item_name(®->hr_item)); |
2076 | |||
2033 | config_item_put(item); | 2077 | config_item_put(item); |
2078 | |||
2079 | if (!o2hb_global_heartbeat_active() || !quorum_region) | ||
2080 | return; | ||
2081 | |||
2082 | /* | ||
2083 | * If global heartbeat active and there are dependent users, | ||
2084 | * pin all regions if quorum region count <= CUT_OFF | ||
2085 | */ | ||
2086 | spin_lock(&o2hb_live_lock); | ||
2087 | |||
2088 | if (!o2hb_dependent_users) | ||
2089 | goto unlock; | ||
2090 | |||
2091 | if (o2hb_pop_count(&o2hb_quorum_region_bitmap, | ||
2092 | O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF) | ||
2093 | o2hb_region_pin(NULL); | ||
2094 | |||
2095 | unlock: | ||
2096 | spin_unlock(&o2hb_live_lock); | ||
2034 | } | 2097 | } |
2035 | 2098 | ||
2036 | struct o2hb_heartbeat_group_attribute { | 2099 | struct o2hb_heartbeat_group_attribute { |
@@ -2216,63 +2279,138 @@ void o2hb_setup_callback(struct o2hb_callback_func *hc, | |||
2216 | } | 2279 | } |
2217 | EXPORT_SYMBOL_GPL(o2hb_setup_callback); | 2280 | EXPORT_SYMBOL_GPL(o2hb_setup_callback); |
2218 | 2281 | ||
2219 | static struct o2hb_region *o2hb_find_region(const char *region_uuid) | 2282 | /* |
2283 | * In local heartbeat mode, region_uuid passed matches the dlm domain name. | ||
2284 | * In global heartbeat mode, region_uuid passed is NULL. | ||
2285 | * | ||
2286 | * In local, we only pin the matching region. In global we pin all the active | ||
2287 | * regions. | ||
2288 | */ | ||
2289 | static int o2hb_region_pin(const char *region_uuid) | ||
2220 | { | 2290 | { |
2221 | struct o2hb_region *p, *reg = NULL; | 2291 | int ret = 0, found = 0; |
2292 | struct o2hb_region *reg; | ||
2293 | char *uuid; | ||
2222 | 2294 | ||
2223 | assert_spin_locked(&o2hb_live_lock); | 2295 | assert_spin_locked(&o2hb_live_lock); |
2224 | 2296 | ||
2225 | list_for_each_entry(p, &o2hb_all_regions, hr_all_item) { | 2297 | list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) { |
2226 | if (!strcmp(region_uuid, config_item_name(&p->hr_item))) { | 2298 | uuid = config_item_name(®->hr_item); |
2227 | reg = p; | 2299 | |
2228 | break; | 2300 | /* local heartbeat */ |
2301 | if (region_uuid) { | ||
2302 | if (strcmp(region_uuid, uuid)) | ||
2303 | continue; | ||
2304 | found = 1; | ||
2229 | } | 2305 | } |
2306 | |||
2307 | if (reg->hr_item_pinned || reg->hr_item_dropped) | ||
2308 | goto skip_pin; | ||
2309 | |||
2310 | /* Ignore ENOENT only for local hb (userdlm domain) */ | ||
2311 | ret = o2nm_depend_item(®->hr_item); | ||
2312 | if (!ret) { | ||
2313 | mlog(ML_CLUSTER, "Pin region %s\n", uuid); | ||
2314 | reg->hr_item_pinned = 1; | ||
2315 | } else { | ||
2316 | if (ret == -ENOENT && found) | ||
2317 | ret = 0; | ||
2318 | else { | ||
2319 | mlog(ML_ERROR, "Pin region %s fails with %d\n", | ||
2320 | uuid, ret); | ||
2321 | break; | ||
2322 | } | ||
2323 | } | ||
2324 | skip_pin: | ||
2325 | if (found) | ||
2326 | break; | ||
2230 | } | 2327 | } |
2231 | 2328 | ||
2232 | return reg; | 2329 | return ret; |
2233 | } | 2330 | } |
2234 | 2331 | ||
2235 | static int o2hb_region_get(const char *region_uuid) | 2332 | /* |
2333 | * In local heartbeat mode, region_uuid passed matches the dlm domain name. | ||
2334 | * In global heartbeat mode, region_uuid passed is NULL. | ||
2335 | * | ||
2336 | * In local, we only unpin the matching region. In global we unpin all the | ||
2337 | * active regions. | ||
2338 | */ | ||
2339 | static void o2hb_region_unpin(const char *region_uuid) | ||
2236 | { | 2340 | { |
2237 | int ret = 0; | ||
2238 | struct o2hb_region *reg; | 2341 | struct o2hb_region *reg; |
2342 | char *uuid; | ||
2343 | int found = 0; | ||
2239 | 2344 | ||
2240 | spin_lock(&o2hb_live_lock); | 2345 | assert_spin_locked(&o2hb_live_lock); |
2241 | 2346 | ||
2242 | reg = o2hb_find_region(region_uuid); | 2347 | list_for_each_entry(reg, &o2hb_all_regions, hr_all_item) { |
2243 | if (!reg) | 2348 | uuid = config_item_name(®->hr_item); |
2244 | ret = -ENOENT; | 2349 | if (region_uuid) { |
2245 | spin_unlock(&o2hb_live_lock); | 2350 | if (strcmp(region_uuid, uuid)) |
2351 | continue; | ||
2352 | found = 1; | ||
2353 | } | ||
2246 | 2354 | ||
2247 | if (ret) | 2355 | if (reg->hr_item_pinned) { |
2248 | goto out; | 2356 | mlog(ML_CLUSTER, "Unpin region %s\n", uuid); |
2357 | o2nm_undepend_item(®->hr_item); | ||
2358 | reg->hr_item_pinned = 0; | ||
2359 | } | ||
2360 | if (found) | ||
2361 | break; | ||
2362 | } | ||
2363 | } | ||
2249 | 2364 | ||
2250 | ret = o2nm_depend_this_node(); | 2365 | static int o2hb_region_inc_user(const char *region_uuid) |
2251 | if (ret) | 2366 | { |
2252 | goto out; | 2367 | int ret = 0; |
2253 | 2368 | ||
2254 | ret = o2nm_depend_item(®->hr_item); | 2369 | spin_lock(&o2hb_live_lock); |
2255 | if (ret) | ||
2256 | o2nm_undepend_this_node(); | ||
2257 | 2370 | ||
2258 | out: | 2371 | /* local heartbeat */ |
2372 | if (!o2hb_global_heartbeat_active()) { | ||
2373 | ret = o2hb_region_pin(region_uuid); | ||
2374 | goto unlock; | ||
2375 | } | ||
2376 | |||
2377 | /* | ||
2378 | * if global heartbeat active and this is the first dependent user, | ||
2379 | * pin all regions if quorum region count <= CUT_OFF | ||
2380 | */ | ||
2381 | o2hb_dependent_users++; | ||
2382 | if (o2hb_dependent_users > 1) | ||
2383 | goto unlock; | ||
2384 | |||
2385 | if (o2hb_pop_count(&o2hb_quorum_region_bitmap, | ||
2386 | O2NM_MAX_REGIONS) <= O2HB_PIN_CUT_OFF) | ||
2387 | ret = o2hb_region_pin(NULL); | ||
2388 | |||
2389 | unlock: | ||
2390 | spin_unlock(&o2hb_live_lock); | ||
2259 | return ret; | 2391 | return ret; |
2260 | } | 2392 | } |
2261 | 2393 | ||
2262 | static void o2hb_region_put(const char *region_uuid) | 2394 | void o2hb_region_dec_user(const char *region_uuid) |
2263 | { | 2395 | { |
2264 | struct o2hb_region *reg; | ||
2265 | |||
2266 | spin_lock(&o2hb_live_lock); | 2396 | spin_lock(&o2hb_live_lock); |
2267 | 2397 | ||
2268 | reg = o2hb_find_region(region_uuid); | 2398 | /* local heartbeat */ |
2399 | if (!o2hb_global_heartbeat_active()) { | ||
2400 | o2hb_region_unpin(region_uuid); | ||
2401 | goto unlock; | ||
2402 | } | ||
2269 | 2403 | ||
2270 | spin_unlock(&o2hb_live_lock); | 2404 | /* |
2405 | * if global heartbeat active and there are no dependent users, | ||
2406 | * unpin all quorum regions | ||
2407 | */ | ||
2408 | o2hb_dependent_users--; | ||
2409 | if (!o2hb_dependent_users) | ||
2410 | o2hb_region_unpin(NULL); | ||
2271 | 2411 | ||
2272 | if (reg) { | 2412 | unlock: |
2273 | o2nm_undepend_item(®->hr_item); | 2413 | spin_unlock(&o2hb_live_lock); |
2274 | o2nm_undepend_this_node(); | ||
2275 | } | ||
2276 | } | 2414 | } |
2277 | 2415 | ||
2278 | int o2hb_register_callback(const char *region_uuid, | 2416 | int o2hb_register_callback(const char *region_uuid, |
@@ -2293,9 +2431,11 @@ int o2hb_register_callback(const char *region_uuid, | |||
2293 | } | 2431 | } |
2294 | 2432 | ||
2295 | if (region_uuid) { | 2433 | if (region_uuid) { |
2296 | ret = o2hb_region_get(region_uuid); | 2434 | ret = o2hb_region_inc_user(region_uuid); |
2297 | if (ret) | 2435 | if (ret) { |
2436 | mlog_errno(ret); | ||
2298 | goto out; | 2437 | goto out; |
2438 | } | ||
2299 | } | 2439 | } |
2300 | 2440 | ||
2301 | down_write(&o2hb_callback_sem); | 2441 | down_write(&o2hb_callback_sem); |
@@ -2313,7 +2453,7 @@ int o2hb_register_callback(const char *region_uuid, | |||
2313 | up_write(&o2hb_callback_sem); | 2453 | up_write(&o2hb_callback_sem); |
2314 | ret = 0; | 2454 | ret = 0; |
2315 | out: | 2455 | out: |
2316 | mlog(ML_HEARTBEAT, "returning %d on behalf of %p for funcs %p\n", | 2456 | mlog(ML_CLUSTER, "returning %d on behalf of %p for funcs %p\n", |
2317 | ret, __builtin_return_address(0), hc); | 2457 | ret, __builtin_return_address(0), hc); |
2318 | return ret; | 2458 | return ret; |
2319 | } | 2459 | } |
@@ -2324,7 +2464,7 @@ void o2hb_unregister_callback(const char *region_uuid, | |||
2324 | { | 2464 | { |
2325 | BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); | 2465 | BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); |
2326 | 2466 | ||
2327 | mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n", | 2467 | mlog(ML_CLUSTER, "on behalf of %p for funcs %p\n", |
2328 | __builtin_return_address(0), hc); | 2468 | __builtin_return_address(0), hc); |
2329 | 2469 | ||
2330 | /* XXX Can this happen _with_ a region reference? */ | 2470 | /* XXX Can this happen _with_ a region reference? */ |
@@ -2332,7 +2472,7 @@ void o2hb_unregister_callback(const char *region_uuid, | |||
2332 | return; | 2472 | return; |
2333 | 2473 | ||
2334 | if (region_uuid) | 2474 | if (region_uuid) |
2335 | o2hb_region_put(region_uuid); | 2475 | o2hb_region_dec_user(region_uuid); |
2336 | 2476 | ||
2337 | down_write(&o2hb_callback_sem); | 2477 | down_write(&o2hb_callback_sem); |
2338 | 2478 | ||
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index fcc40c33489d..7e38a072d720 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -1659,8 +1659,8 @@ bail: | |||
1659 | 1659 | ||
1660 | static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm) | 1660 | static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm) |
1661 | { | 1661 | { |
1662 | o2hb_unregister_callback(NULL, &dlm->dlm_hb_up); | 1662 | o2hb_unregister_callback(dlm->name, &dlm->dlm_hb_up); |
1663 | o2hb_unregister_callback(NULL, &dlm->dlm_hb_down); | 1663 | o2hb_unregister_callback(dlm->name, &dlm->dlm_hb_down); |
1664 | o2net_unregister_handler_list(&dlm->dlm_domain_handlers); | 1664 | o2net_unregister_handler_list(&dlm->dlm_domain_handlers); |
1665 | } | 1665 | } |
1666 | 1666 | ||
@@ -1672,13 +1672,13 @@ static int dlm_register_domain_handlers(struct dlm_ctxt *dlm) | |||
1672 | 1672 | ||
1673 | o2hb_setup_callback(&dlm->dlm_hb_down, O2HB_NODE_DOWN_CB, | 1673 | o2hb_setup_callback(&dlm->dlm_hb_down, O2HB_NODE_DOWN_CB, |
1674 | dlm_hb_node_down_cb, dlm, DLM_HB_NODE_DOWN_PRI); | 1674 | dlm_hb_node_down_cb, dlm, DLM_HB_NODE_DOWN_PRI); |
1675 | status = o2hb_register_callback(NULL, &dlm->dlm_hb_down); | 1675 | status = o2hb_register_callback(dlm->name, &dlm->dlm_hb_down); |
1676 | if (status) | 1676 | if (status) |
1677 | goto bail; | 1677 | goto bail; |
1678 | 1678 | ||
1679 | o2hb_setup_callback(&dlm->dlm_hb_up, O2HB_NODE_UP_CB, | 1679 | o2hb_setup_callback(&dlm->dlm_hb_up, O2HB_NODE_UP_CB, |
1680 | dlm_hb_node_up_cb, dlm, DLM_HB_NODE_UP_PRI); | 1680 | dlm_hb_node_up_cb, dlm, DLM_HB_NODE_UP_PRI); |
1681 | status = o2hb_register_callback(NULL, &dlm->dlm_hb_up); | 1681 | status = o2hb_register_callback(dlm->name, &dlm->dlm_hb_up); |
1682 | if (status) | 1682 | if (status) |
1683 | goto bail; | 1683 | goto bail; |
1684 | 1684 | ||