aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/cluster/heartbeat.c216
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c8
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] = {
132unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD; 132unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD;
133unsigned int o2hb_heartbeat_mode = O2HB_HEARTBEAT_LOCAL; 133unsigned 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 */
141unsigned 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 */
159static int o2hb_region_pin(const char *region_uuid);
160static 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(&reg->hr_item)); 731 config_item_name(&reg->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
707static int o2hb_check_slot(struct o2hb_region *reg, 744static 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(&reg->hr_item)); 2075 config_item_name(&reg->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
2095unlock:
2096 spin_unlock(&o2hb_live_lock);
2034} 2097}
2035 2098
2036struct o2hb_heartbeat_group_attribute { 2099struct o2hb_heartbeat_group_attribute {
@@ -2216,63 +2279,138 @@ void o2hb_setup_callback(struct o2hb_callback_func *hc,
2216} 2279}
2217EXPORT_SYMBOL_GPL(o2hb_setup_callback); 2280EXPORT_SYMBOL_GPL(o2hb_setup_callback);
2218 2281
2219static 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 */
2289static 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(&reg->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(&reg->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 }
2324skip_pin:
2325 if (found)
2326 break;
2230 } 2327 }
2231 2328
2232 return reg; 2329 return ret;
2233} 2330}
2234 2331
2235static 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 */
2339static 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(&reg->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(&reg->hr_item);
2358 reg->hr_item_pinned = 0;
2359 }
2360 if (found)
2361 break;
2362 }
2363}
2249 2364
2250 ret = o2nm_depend_this_node(); 2365static 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(&reg->hr_item); 2369 spin_lock(&o2hb_live_lock);
2255 if (ret)
2256 o2nm_undepend_this_node();
2257 2370
2258out: 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
2389unlock:
2390 spin_unlock(&o2hb_live_lock);
2259 return ret; 2391 return ret;
2260} 2392}
2261 2393
2262static void o2hb_region_put(const char *region_uuid) 2394void 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) { 2412unlock:
2273 o2nm_undepend_item(&reg->hr_item); 2413 spin_unlock(&o2hb_live_lock);
2274 o2nm_undepend_this_node();
2275 }
2276} 2414}
2277 2415
2278int o2hb_register_callback(const char *region_uuid, 2416int 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;
2315out: 2455out:
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
1660static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm) 1660static 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