Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dlm: move dlm_search_rsb_tree() out of lock

The rhashtable structure is lockless for readers such as
rhashtable_lookup_fast(). It should be save to call this lookup
functionality out of holding ls_rsbtbl_lock to get the rsb pointer out
of the hash. This reduce the contention time of ls_rsbtbl_lock in some
cases. We still need to check if the rsb is part of the check as this
state can be changed while ls_rsbtbl_lock is not held. If its part of
the rhashtable data structure we take a reference to be sure it will not
be freed after we drop the ls_rsbtbl_lock read lock.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>

authored by

Alexander Aring and committed by
David Teigland
5be323b0 98ff7d95

+50 -33
+50 -33
fs/dlm/lock.c
··· 733 733 } 734 734 735 735 retry: 736 + error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r); 737 + if (error) 738 + goto do_new; 736 739 737 740 /* check if the rsb is active under read lock - likely path */ 738 741 read_lock_bh(&ls->ls_rsbtbl_lock); 739 - error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r); 740 - if (error) { 742 + if (!rsb_flag(r, RSB_HASHED)) { 741 743 read_unlock_bh(&ls->ls_rsbtbl_lock); 742 744 goto do_new; 743 745 } ··· 920 918 int error; 921 919 922 920 retry: 921 + error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r); 922 + if (error) 923 + goto do_new; 923 924 924 925 /* check if the rsb is in active state under read lock - likely path */ 925 926 read_lock_bh(&ls->ls_rsbtbl_lock); 926 - error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r); 927 - if (error) { 927 + if (!rsb_flag(r, RSB_HASHED)) { 928 928 read_unlock_bh(&ls->ls_rsbtbl_lock); 929 929 goto do_new; 930 930 } ··· 1280 1276 } 1281 1277 1282 1278 retry: 1279 + error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r); 1280 + if (error) 1281 + goto not_found; 1283 1282 1284 1283 /* check if the rsb is active under read lock - likely path */ 1285 1284 read_lock_bh(&ls->ls_rsbtbl_lock); 1286 - error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r); 1287 - if (!error) { 1288 - if (rsb_flag(r, RSB_INACTIVE)) { 1289 - read_unlock_bh(&ls->ls_rsbtbl_lock); 1290 - goto do_inactive; 1291 - } 1292 - 1293 - /* because the rsb is active, we need to lock_rsb before 1294 - * checking/changing re_master_nodeid 1295 - */ 1296 - 1297 - hold_rsb(r); 1298 - read_unlock_bh(&ls->ls_rsbtbl_lock); 1299 - lock_rsb(r); 1300 - 1301 - __dlm_master_lookup(ls, r, our_nodeid, from_nodeid, false, 1302 - flags, r_nodeid, result); 1303 - 1304 - /* the rsb was active */ 1305 - unlock_rsb(r); 1306 - put_rsb(r); 1307 - 1308 - return 0; 1309 - } else { 1285 + if (!rsb_flag(r, RSB_HASHED)) { 1310 1286 read_unlock_bh(&ls->ls_rsbtbl_lock); 1311 1287 goto not_found; 1312 1288 } 1289 + 1290 + if (rsb_flag(r, RSB_INACTIVE)) { 1291 + read_unlock_bh(&ls->ls_rsbtbl_lock); 1292 + goto do_inactive; 1293 + } 1294 + 1295 + /* because the rsb is active, we need to lock_rsb before 1296 + * checking/changing re_master_nodeid 1297 + */ 1298 + 1299 + hold_rsb(r); 1300 + read_unlock_bh(&ls->ls_rsbtbl_lock); 1301 + lock_rsb(r); 1302 + 1303 + __dlm_master_lookup(ls, r, our_nodeid, from_nodeid, false, 1304 + flags, r_nodeid, result); 1305 + 1306 + /* the rsb was active */ 1307 + unlock_rsb(r); 1308 + put_rsb(r); 1309 + 1310 + return 0; 1313 1311 1314 1312 do_inactive: 1315 1313 /* unlikely path - check if still part of ls_rsbtbl */ ··· 1409 1403 struct dlm_rsb *r = NULL; 1410 1404 int error; 1411 1405 1412 - read_lock_bh(&ls->ls_rsbtbl_lock); 1406 + rcu_read_lock(); 1413 1407 error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r); 1414 1408 if (!error) 1415 1409 goto out; 1416 1410 1417 1411 dlm_dump_rsb(r); 1418 1412 out: 1419 - read_unlock_bh(&ls->ls_rsbtbl_lock); 1413 + rcu_read_unlock(); 1420 1414 } 1421 1415 1422 1416 static void deactivate_rsb(struct kref *kref) ··· 4315 4309 memset(name, 0, sizeof(name)); 4316 4310 memcpy(name, ms->m_extra, len); 4317 4311 4318 - write_lock_bh(&ls->ls_rsbtbl_lock); 4319 - 4312 + rcu_read_lock(); 4320 4313 rv = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r); 4321 4314 if (rv) { 4315 + rcu_read_unlock(); 4322 4316 /* should not happen */ 4323 4317 log_error(ls, "%s from %d not found %s", __func__, 4324 4318 from_nodeid, name); 4325 - write_unlock_bh(&ls->ls_rsbtbl_lock); 4326 4319 return; 4327 4320 } 4321 + 4322 + write_lock_bh(&ls->ls_rsbtbl_lock); 4323 + if (!rsb_flag(r, RSB_HASHED)) { 4324 + rcu_read_unlock(); 4325 + write_unlock_bh(&ls->ls_rsbtbl_lock); 4326 + /* should not happen */ 4327 + log_error(ls, "%s from %d got removed during removal %s", 4328 + __func__, from_nodeid, name); 4329 + return; 4330 + } 4331 + /* at this stage the rsb can only being freed here */ 4332 + rcu_read_unlock(); 4328 4333 4329 4334 if (!rsb_flag(r, RSB_INACTIVE)) { 4330 4335 if (r->res_master_nodeid != from_nodeid) {