Skip to content

Commit 6644925

Browse files
Alexander Aringteigland
authored andcommitted
dlm: do not use ref counts for rsb in the toss state
In the past we had problems when an rsb had a reference counter greater than one while in the toss state. An rsb in the toss state is not actively used for locking, and should not have any other references apart from the single ref keeping it on the rsb hash. Shift to freeing rsb's directly rather than using kref_put to free them, since the ref counting is not meant to be used in this state. Add warnings if ref counting is seen while an rsb is in the toss state. Signed-off-by: Alexander Aring <[email protected]> Signed-off-by: David Teigland <[email protected]>
1 parent 6c64803 commit 6644925

File tree

3 files changed

+32
-32
lines changed

3 files changed

+32
-32
lines changed

fs/dlm/lock.c

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
325325

326326
static inline void hold_rsb(struct dlm_rsb *r)
327327
{
328+
/* rsbs in toss state never get referenced */
329+
WARN_ON(rsb_flag(r, RSB_TOSS));
328330
kref_get(&r->res_ref);
329331
}
330332

@@ -631,6 +633,11 @@ static int find_rsb_dir(struct dlm_ls *ls, const void *name, int len,
631633

632634
list_move(&r->res_rsbs_list, &ls->ls_keep);
633635
rsb_clear_flag(r, RSB_TOSS);
636+
/* rsb got out of toss state, it becomes alive again
637+
* and we reinit the reference counter that is only
638+
* valid for keep state rsbs
639+
*/
640+
kref_init(&r->res_ref);
634641
goto out_unlock;
635642

636643

@@ -765,6 +772,11 @@ static int find_rsb_nodir(struct dlm_ls *ls, const void *name, int len,
765772

766773
list_move(&r->res_rsbs_list, &ls->ls_keep);
767774
rsb_clear_flag(r, RSB_TOSS);
775+
/* rsb got out of toss state, it becomes alive again
776+
* and we reinit the reference counter that is only
777+
* valid for keep state rsbs
778+
*/
779+
kref_init(&r->res_ref);
768780
goto out_unlock;
769781

770782

@@ -1112,8 +1124,6 @@ static void toss_rsb(struct kref *kref)
11121124
struct dlm_ls *ls = r->res_ls;
11131125

11141126
DLM_ASSERT(list_empty(&r->res_root_list), dlm_print_rsb(r););
1115-
kref_init(&r->res_ref);
1116-
WARN_ON(rsb_flag(r, RSB_TOSS));
11171127
rsb_set_flag(r, RSB_TOSS);
11181128
list_move(&r->res_rsbs_list, &ls->ls_toss);
11191129
r->res_toss_time = jiffies;
@@ -1129,16 +1139,20 @@ static void toss_rsb(struct kref *kref)
11291139
static void unhold_rsb(struct dlm_rsb *r)
11301140
{
11311141
int rv;
1142+
1143+
/* rsbs in toss state never get referenced */
1144+
WARN_ON(rsb_flag(r, RSB_TOSS));
11321145
rv = kref_put(&r->res_ref, toss_rsb);
11331146
DLM_ASSERT(!rv, dlm_dump_rsb(r););
11341147
}
11351148

1136-
static void kill_rsb(struct kref *kref)
1149+
void free_toss_rsb(struct dlm_rsb *r)
11371150
{
1138-
struct dlm_rsb *r = container_of(kref, struct dlm_rsb, res_ref);
1151+
WARN_ON_ONCE(!rsb_flag(r, RSB_TOSS));
11391152

1140-
/* All work is done after the return from kref_put() so we
1141-
can release the write_lock before the remove and free. */
1153+
/* check if all work is done after the rsb is on toss list
1154+
* and it can be freed.
1155+
*/
11421156

11431157
DLM_ASSERT(list_empty(&r->res_lookup), dlm_dump_rsb(r););
11441158
DLM_ASSERT(list_empty(&r->res_grantqueue), dlm_dump_rsb(r););
@@ -1147,6 +1161,8 @@ static void kill_rsb(struct kref *kref)
11471161
DLM_ASSERT(list_empty(&r->res_root_list), dlm_dump_rsb(r););
11481162
DLM_ASSERT(list_empty(&r->res_recover_list), dlm_dump_rsb(r););
11491163
DLM_ASSERT(list_empty(&r->res_masters_list), dlm_dump_rsb(r););
1164+
1165+
dlm_free_rsb(r);
11501166
}
11511167

11521168
/* Attaching/detaching lkb's from rsb's is for rsb reference counting.
@@ -1611,15 +1627,10 @@ static void shrink_bucket(struct dlm_ls *ls)
16111627
continue;
16121628
}
16131629

1614-
if (!kref_put(&r->res_ref, kill_rsb)) {
1615-
log_error(ls, "tossed rsb in use %s", r->res_name);
1616-
continue;
1617-
}
1618-
16191630
list_del(&r->res_rsbs_list);
16201631
rhashtable_remove_fast(&ls->ls_rsbtbl, &r->res_node,
16211632
dlm_rhash_rsb_params);
1622-
dlm_free_rsb(r);
1633+
free_toss_rsb(r);
16231634
}
16241635

16251636
if (need_shrink)
@@ -1680,19 +1691,13 @@ static void shrink_bucket(struct dlm_ls *ls)
16801691
continue;
16811692
}
16821693

1683-
if (!kref_put(&r->res_ref, kill_rsb)) {
1684-
spin_unlock_bh(&ls->ls_rsbtbl_lock);
1685-
log_error(ls, "remove_name in use %s", name);
1686-
continue;
1687-
}
1688-
16891694
list_del(&r->res_rsbs_list);
16901695
rhashtable_remove_fast(&ls->ls_rsbtbl, &r->res_node,
16911696
dlm_rhash_rsb_params);
16921697
send_remove(r);
16931698
spin_unlock_bh(&ls->ls_rsbtbl_lock);
16941699

1695-
dlm_free_rsb(r);
1700+
free_toss_rsb(r);
16961701
}
16971702
}
16981703

@@ -4180,18 +4185,12 @@ static void receive_remove(struct dlm_ls *ls, const struct dlm_message *ms)
41804185
return;
41814186
}
41824187

4183-
if (kref_put(&r->res_ref, kill_rsb)) {
4184-
list_del(&r->res_rsbs_list);
4185-
rhashtable_remove_fast(&ls->ls_rsbtbl, &r->res_node,
4186-
dlm_rhash_rsb_params);
4187-
spin_unlock_bh(&ls->ls_rsbtbl_lock);
4188-
dlm_free_rsb(r);
4189-
} else {
4190-
log_error(ls, "receive_remove from %d rsb ref error",
4191-
from_nodeid);
4192-
dlm_print_rsb(r);
4193-
spin_unlock_bh(&ls->ls_rsbtbl_lock);
4194-
}
4188+
list_del(&r->res_rsbs_list);
4189+
rhashtable_remove_fast(&ls->ls_rsbtbl, &r->res_node,
4190+
dlm_rhash_rsb_params);
4191+
spin_unlock_bh(&ls->ls_rsbtbl_lock);
4192+
4193+
free_toss_rsb(r);
41954194
}
41964195

41974196
static void receive_purge(struct dlm_ls *ls, const struct dlm_message *ms)

fs/dlm/lock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ void dlm_receive_message_saved(struct dlm_ls *ls, const struct dlm_message *ms,
1818
uint32_t saved_seq);
1919
void dlm_receive_buffer(const union dlm_packet *p, int nodeid);
2020
int dlm_modes_compat(int mode1, int mode2);
21+
void free_toss_rsb(struct dlm_rsb *r);
2122
void dlm_put_rsb(struct dlm_rsb *r);
2223
void dlm_hold_rsb(struct dlm_rsb *r);
2324
int dlm_put_lkb(struct dlm_lkb *lkb);

fs/dlm/recover.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ void dlm_clear_toss(struct dlm_ls *ls)
889889
list_del(&r->res_rsbs_list);
890890
rhashtable_remove_fast(&ls->ls_rsbtbl, &r->res_node,
891891
dlm_rhash_rsb_params);
892-
dlm_free_rsb(r);
892+
free_toss_rsb(r);
893893
count++;
894894
}
895895
spin_unlock_bh(&ls->ls_rsbtbl_lock);

0 commit comments

Comments
 (0)