Skip to content

Commit c217adf

Browse files
committed
dlm: fix add_scan and del_scan usage
Remove a few calls to add_scan() and del_scan() in cases where the rsb is a dir record, so the rsb should never be placed on the scan list at all. Add WARN_ON to catch cases where this is done. Signed-off-by: David Teigland <[email protected]>
1 parent 4f5957a commit c217adf

File tree

1 file changed

+35
-22
lines changed

1 file changed

+35
-22
lines changed

fs/dlm/lock.c

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,9 @@ static void del_scan(struct dlm_ls *ls, struct dlm_rsb *r)
420420
{
421421
struct dlm_rsb *first;
422422

423+
/* active rsbs should never be on the scan list */
424+
WARN_ON(!rsb_flag(r, RSB_INACTIVE));
425+
423426
spin_lock_bh(&ls->ls_scan_lock);
424427
r->res_toss_time = 0;
425428

@@ -457,17 +460,16 @@ static void add_scan(struct dlm_ls *ls, struct dlm_rsb *r)
457460
int our_nodeid = dlm_our_nodeid();
458461
struct dlm_rsb *first;
459462

460-
/* If we're the directory record for this rsb, and
461-
* we're not the master of it, then we need to wait
462-
* for the master node to send us a dir remove for
463-
* before removing the dir record.
464-
*/
465-
if (!dlm_no_directory(ls) &&
466-
(r->res_master_nodeid != our_nodeid) &&
467-
(dlm_dir_nodeid(r) == our_nodeid)) {
468-
del_scan(ls, r);
469-
return;
470-
}
463+
/* A dir record for a remote master rsb should never be on the scan list. */
464+
WARN_ON(!dlm_no_directory(ls) &&
465+
(r->res_master_nodeid != our_nodeid) &&
466+
(dlm_dir_nodeid(r) == our_nodeid));
467+
468+
/* An active rsb should never be on the scan list. */
469+
WARN_ON(!rsb_flag(r, RSB_INACTIVE));
470+
471+
/* An rsb should not already be on the scan list. */
472+
WARN_ON(!list_empty(&r->res_scan_list));
471473

472474
spin_lock_bh(&ls->ls_scan_lock);
473475
/* set the new rsb absolute expire time in the rsb */
@@ -479,12 +481,6 @@ static void add_scan(struct dlm_ls *ls, struct dlm_rsb *r)
479481
list_add_tail(&r->res_scan_list, &ls->ls_scan_list);
480482
enable_scan_timer(ls, r->res_toss_time);
481483
} else {
482-
/* check if the rsb was already queued, if so delete
483-
* it from the toss queue
484-
*/
485-
if (!list_empty(&r->res_scan_list))
486-
list_del(&r->res_scan_list);
487-
488484
/* try to get the maybe new first element and then add
489485
* to this rsb with the oldest expire time to the end
490486
* of the queue. If the list was empty before this
@@ -807,10 +803,12 @@ static int find_rsb_dir(struct dlm_ls *ls, const void *name, int len,
807803
r->res_first_lkid = 0;
808804
}
809805

806+
/* A dir record will not be on the scan list. */
807+
if (r->res_dir_nodeid != our_nodeid)
808+
del_scan(ls, r);
810809
list_move(&r->res_slow_list, &ls->ls_slow_active);
811810
rsb_clear_flag(r, RSB_INACTIVE);
812-
kref_init(&r->res_ref);
813-
del_scan(ls, r);
811+
kref_init(&r->res_ref); /* ref is now used in active state */
814812
write_unlock_bh(&ls->ls_rsbtbl_lock);
815813

816814
goto out;
@@ -1272,7 +1270,10 @@ int dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *name,
12721270
__dlm_master_lookup(ls, r, our_nodeid, from_nodeid, true, flags,
12731271
r_nodeid, result);
12741272

1275-
add_scan(ls, r);
1273+
/* A dir record rsb should never be on scan list. */
1274+
/* Try to fix this with del_scan? */
1275+
WARN_ON(!list_empty(&r->res_scan_list));
1276+
12761277
write_unlock_bh(&ls->ls_rsbtbl_lock);
12771278

12781279
return 0;
@@ -1305,7 +1306,6 @@ int dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *name,
13051306
}
13061307

13071308
list_add(&r->res_slow_list, &ls->ls_slow_inactive);
1308-
add_scan(ls, r);
13091309
write_unlock_bh(&ls->ls_rsbtbl_lock);
13101310

13111311
if (result)
@@ -1346,11 +1346,24 @@ static void deactivate_rsb(struct kref *kref)
13461346
{
13471347
struct dlm_rsb *r = container_of(kref, struct dlm_rsb, res_ref);
13481348
struct dlm_ls *ls = r->res_ls;
1349+
int our_nodeid = dlm_our_nodeid();
13491350

13501351
DLM_ASSERT(list_empty(&r->res_root_list), dlm_print_rsb(r););
13511352
rsb_set_flag(r, RSB_INACTIVE);
13521353
list_move(&r->res_slow_list, &ls->ls_slow_inactive);
1353-
add_scan(ls, r);
1354+
1355+
/*
1356+
* When the rsb becomes unused:
1357+
* - If it's not a dir record for a remote master rsb,
1358+
* then it is put on the scan list to be freed.
1359+
* - If it's a dir record for a remote master rsb,
1360+
* then it is kept in the inactive state until
1361+
* receive_remove() from the master node.
1362+
*/
1363+
if (!dlm_no_directory(ls) &&
1364+
(r->res_master_nodeid != our_nodeid) &&
1365+
(dlm_dir_nodeid(r) != our_nodeid))
1366+
add_scan(ls, r);
13541367

13551368
if (r->res_lvbptr) {
13561369
dlm_free_lvb(r->res_lvbptr);

0 commit comments

Comments
 (0)