diff options
Diffstat (limited to 'fs/dlm/recover.c')
-rw-r--r-- | fs/dlm/recover.c | 202 |
1 files changed, 76 insertions, 126 deletions
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c index 53917c0aa3c0..2e1169c81c6e 100644 --- a/fs/dlm/recover.c +++ b/fs/dlm/recover.c @@ -74,9 +74,9 @@ int dlm_wait_function(struct dlm_ls *ls, int (*testfn) (struct dlm_ls *ls)) uint32_t dlm_recover_status(struct dlm_ls *ls) { uint32_t status; - spin_lock(&ls->ls_recover_lock); + spin_lock_bh(&ls->ls_recover_lock); status = ls->ls_recover_status; - spin_unlock(&ls->ls_recover_lock); + spin_unlock_bh(&ls->ls_recover_lock); return status; } @@ -87,9 +87,9 @@ static void _set_recover_status(struct dlm_ls *ls, uint32_t status) void dlm_set_recover_status(struct dlm_ls *ls, uint32_t status) { - spin_lock(&ls->ls_recover_lock); + spin_lock_bh(&ls->ls_recover_lock); _set_recover_status(ls, status); - spin_unlock(&ls->ls_recover_lock); + spin_unlock_bh(&ls->ls_recover_lock); } static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status, @@ -188,13 +188,13 @@ int dlm_recover_members_wait(struct dlm_ls *ls, uint64_t seq) rv = dlm_slots_assign(ls, &num_slots, &slots_size, &slots, &gen); if (!rv) { - spin_lock(&ls->ls_recover_lock); + spin_lock_bh(&ls->ls_recover_lock); _set_recover_status(ls, DLM_RS_NODES_ALL); ls->ls_num_slots = num_slots; ls->ls_slots_size = slots_size; ls->ls_slots = slots; ls->ls_generation = gen; - spin_unlock(&ls->ls_recover_lock); + spin_unlock_bh(&ls->ls_recover_lock); } else { dlm_set_recover_status(ls, DLM_RS_NODES_ALL); } @@ -241,9 +241,9 @@ static int recover_list_empty(struct dlm_ls *ls) { int empty; - spin_lock(&ls->ls_recover_list_lock); + spin_lock_bh(&ls->ls_recover_list_lock); empty = list_empty(&ls->ls_recover_list); - spin_unlock(&ls->ls_recover_list_lock); + spin_unlock_bh(&ls->ls_recover_list_lock); return empty; } @@ -252,23 +252,23 @@ static void recover_list_add(struct dlm_rsb *r) { struct dlm_ls *ls = r->res_ls; - spin_lock(&ls->ls_recover_list_lock); + spin_lock_bh(&ls->ls_recover_list_lock); if (list_empty(&r->res_recover_list)) { list_add_tail(&r->res_recover_list, &ls->ls_recover_list); ls->ls_recover_list_count++; dlm_hold_rsb(r); } - spin_unlock(&ls->ls_recover_list_lock); + spin_unlock_bh(&ls->ls_recover_list_lock); } static void recover_list_del(struct dlm_rsb *r) { struct dlm_ls *ls = r->res_ls; - spin_lock(&ls->ls_recover_list_lock); + spin_lock_bh(&ls->ls_recover_list_lock); list_del_init(&r->res_recover_list); ls->ls_recover_list_count--; - spin_unlock(&ls->ls_recover_list_lock); + spin_unlock_bh(&ls->ls_recover_list_lock); dlm_put_rsb(r); } @@ -277,7 +277,7 @@ static void recover_list_clear(struct dlm_ls *ls) { struct dlm_rsb *r, *s; - spin_lock(&ls->ls_recover_list_lock); + spin_lock_bh(&ls->ls_recover_list_lock); list_for_each_entry_safe(r, s, &ls->ls_recover_list, res_recover_list) { list_del_init(&r->res_recover_list); r->res_recover_locks_count = 0; @@ -290,78 +290,81 @@ static void recover_list_clear(struct dlm_ls *ls) ls->ls_recover_list_count); ls->ls_recover_list_count = 0; } - spin_unlock(&ls->ls_recover_list_lock); + spin_unlock_bh(&ls->ls_recover_list_lock); } -static int recover_idr_empty(struct dlm_ls *ls) +static int recover_xa_empty(struct dlm_ls *ls) { int empty = 1; - spin_lock(&ls->ls_recover_idr_lock); + spin_lock_bh(&ls->ls_recover_xa_lock); if (ls->ls_recover_list_count) empty = 0; - spin_unlock(&ls->ls_recover_idr_lock); + spin_unlock_bh(&ls->ls_recover_xa_lock); return empty; } -static int recover_idr_add(struct dlm_rsb *r) +static int recover_xa_add(struct dlm_rsb *r) { struct dlm_ls *ls = r->res_ls; + struct xa_limit limit = { + .min = 1, + .max = UINT_MAX, + }; + uint32_t id; int rv; - idr_preload(GFP_NOFS); - spin_lock(&ls->ls_recover_idr_lock); + spin_lock_bh(&ls->ls_recover_xa_lock); if (r->res_id) { rv = -1; goto out_unlock; } - rv = idr_alloc(&ls->ls_recover_idr, r, 1, 0, GFP_NOWAIT); + rv = xa_alloc(&ls->ls_recover_xa, &id, r, limit, GFP_ATOMIC); if (rv < 0) goto out_unlock; - r->res_id = rv; + r->res_id = id; ls->ls_recover_list_count++; dlm_hold_rsb(r); rv = 0; out_unlock: - spin_unlock(&ls->ls_recover_idr_lock); - idr_preload_end(); + spin_unlock_bh(&ls->ls_recover_xa_lock); return rv; } -static void recover_idr_del(struct dlm_rsb *r) +static void recover_xa_del(struct dlm_rsb *r) { struct dlm_ls *ls = r->res_ls; - spin_lock(&ls->ls_recover_idr_lock); - idr_remove(&ls->ls_recover_idr, r->res_id); + spin_lock_bh(&ls->ls_recover_xa_lock); + xa_erase_bh(&ls->ls_recover_xa, r->res_id); r->res_id = 0; ls->ls_recover_list_count--; - spin_unlock(&ls->ls_recover_idr_lock); + spin_unlock_bh(&ls->ls_recover_xa_lock); dlm_put_rsb(r); } -static struct dlm_rsb *recover_idr_find(struct dlm_ls *ls, uint64_t id) +static struct dlm_rsb *recover_xa_find(struct dlm_ls *ls, uint64_t id) { struct dlm_rsb *r; - spin_lock(&ls->ls_recover_idr_lock); - r = idr_find(&ls->ls_recover_idr, (int)id); - spin_unlock(&ls->ls_recover_idr_lock); + spin_lock_bh(&ls->ls_recover_xa_lock); + r = xa_load(&ls->ls_recover_xa, (int)id); + spin_unlock_bh(&ls->ls_recover_xa_lock); return r; } -static void recover_idr_clear(struct dlm_ls *ls) +static void recover_xa_clear(struct dlm_ls *ls) { struct dlm_rsb *r; - int id; + unsigned long id; - spin_lock(&ls->ls_recover_idr_lock); + spin_lock_bh(&ls->ls_recover_xa_lock); - idr_for_each_entry(&ls->ls_recover_idr, r, id) { - idr_remove(&ls->ls_recover_idr, id); + xa_for_each(&ls->ls_recover_xa, id, r) { + xa_erase_bh(&ls->ls_recover_xa, id); r->res_id = 0; r->res_recover_locks_count = 0; ls->ls_recover_list_count--; @@ -374,7 +377,7 @@ static void recover_idr_clear(struct dlm_ls *ls) ls->ls_recover_list_count); ls->ls_recover_list_count = 0; } - spin_unlock(&ls->ls_recover_idr_lock); + spin_unlock_bh(&ls->ls_recover_xa_lock); } @@ -449,10 +452,11 @@ static int recover_master(struct dlm_rsb *r, unsigned int *count, uint64_t seq) int is_removed = 0; int error; - if (is_master(r)) + if (r->res_nodeid != -1 && is_master(r)) return 0; - is_removed = dlm_is_removed(ls, r->res_nodeid); + if (r->res_nodeid != -1) + is_removed = dlm_is_removed(ls, r->res_nodeid); if (!is_removed && !rsb_flag(r, RSB_NEW_MASTER)) return 0; @@ -472,7 +476,7 @@ static int recover_master(struct dlm_rsb *r, unsigned int *count, uint64_t seq) set_new_master(r); error = 0; } else { - recover_idr_add(r); + recover_xa_add(r); error = dlm_send_rcom_lookup(r, dir_nodeid, seq); } @@ -521,7 +525,8 @@ static int recover_master_static(struct dlm_rsb *r, unsigned int *count) * the correct dir node. */ -int dlm_recover_masters(struct dlm_ls *ls, uint64_t seq) +int dlm_recover_masters(struct dlm_ls *ls, uint64_t seq, + const struct list_head *root_list) { struct dlm_rsb *r; unsigned int total = 0; @@ -531,10 +536,8 @@ int dlm_recover_masters(struct dlm_ls *ls, uint64_t seq) log_rinfo(ls, "dlm_recover_masters"); - down_read(&ls->ls_root_sem); - list_for_each_entry(r, &ls->ls_root_list, res_root_list) { + list_for_each_entry(r, root_list, res_root_list) { if (dlm_recovery_stopped(ls)) { - up_read(&ls->ls_root_sem); error = -EINTR; goto out; } @@ -548,19 +551,16 @@ int dlm_recover_masters(struct dlm_ls *ls, uint64_t seq) cond_resched(); total++; - if (error) { - up_read(&ls->ls_root_sem); + if (error) goto out; - } } - up_read(&ls->ls_root_sem); log_rinfo(ls, "dlm_recover_masters %u of %u", count, total); - error = dlm_wait_function(ls, &recover_idr_empty); + error = dlm_wait_function(ls, &recover_xa_empty); out: if (error) - recover_idr_clear(ls); + recover_xa_clear(ls); return error; } @@ -569,7 +569,7 @@ int dlm_recover_master_reply(struct dlm_ls *ls, const struct dlm_rcom *rc) struct dlm_rsb *r; int ret_nodeid, new_master; - r = recover_idr_find(ls, le64_to_cpu(rc->rc_id)); + r = recover_xa_find(ls, le64_to_cpu(rc->rc_id)); if (!r) { log_error(ls, "dlm_recover_master_reply no id %llx", (unsigned long long)le64_to_cpu(rc->rc_id)); @@ -588,9 +588,9 @@ int dlm_recover_master_reply(struct dlm_ls *ls, const struct dlm_rcom *rc) r->res_nodeid = new_master; set_new_master(r); unlock_rsb(r); - recover_idr_del(r); + recover_xa_del(r); - if (recover_idr_empty(ls)) + if (recover_xa_empty(ls)) wake_up(&ls->ls_wait_general); out: return 0; @@ -658,14 +658,14 @@ static int recover_locks(struct dlm_rsb *r, uint64_t seq) return error; } -int dlm_recover_locks(struct dlm_ls *ls, uint64_t seq) +int dlm_recover_locks(struct dlm_ls *ls, uint64_t seq, + const struct list_head *root_list) { struct dlm_rsb *r; int error, count = 0; - down_read(&ls->ls_root_sem); - list_for_each_entry(r, &ls->ls_root_list, res_root_list) { - if (is_master(r)) { + list_for_each_entry(r, root_list, res_root_list) { + if (r->res_nodeid != -1 && is_master(r)) { rsb_clear_flag(r, RSB_NEW_MASTER); continue; } @@ -675,19 +675,15 @@ int dlm_recover_locks(struct dlm_ls *ls, uint64_t seq) if (dlm_recovery_stopped(ls)) { error = -EINTR; - up_read(&ls->ls_root_sem); goto out; } error = recover_locks(r, seq); - if (error) { - up_read(&ls->ls_root_sem); + if (error) goto out; - } count += r->res_recover_locks_count; } - up_read(&ls->ls_root_sem); log_rinfo(ls, "dlm_recover_locks %d out", count); @@ -856,15 +852,14 @@ static void recover_grant(struct dlm_rsb *r) rsb_set_flag(r, RSB_RECOVER_GRANT); } -void dlm_recover_rsbs(struct dlm_ls *ls) +void dlm_recover_rsbs(struct dlm_ls *ls, const struct list_head *root_list) { struct dlm_rsb *r; unsigned int count = 0; - down_read(&ls->ls_root_sem); - list_for_each_entry(r, &ls->ls_root_list, res_root_list) { + list_for_each_entry(r, root_list, res_root_list) { lock_rsb(r); - if (is_master(r)) { + if (r->res_nodeid != -1 && is_master(r)) { if (rsb_flag(r, RSB_RECOVER_CONVERT)) recover_conversion(r); @@ -883,76 +878,31 @@ void dlm_recover_rsbs(struct dlm_ls *ls) rsb_clear_flag(r, RSB_NEW_MASTER2); unlock_rsb(r); } - up_read(&ls->ls_root_sem); if (count) log_rinfo(ls, "dlm_recover_rsbs %d done", count); } -/* Create a single list of all root rsb's to be used during recovery */ - -int dlm_create_root_list(struct dlm_ls *ls) -{ - struct rb_node *n; - struct dlm_rsb *r; - int i, error = 0; - - down_write(&ls->ls_root_sem); - if (!list_empty(&ls->ls_root_list)) { - log_error(ls, "root list not empty"); - error = -EINVAL; - goto out; - } - - for (i = 0; i < ls->ls_rsbtbl_size; i++) { - spin_lock(&ls->ls_rsbtbl[i].lock); - for (n = rb_first(&ls->ls_rsbtbl[i].keep); n; n = rb_next(n)) { - r = rb_entry(n, struct dlm_rsb, res_hashnode); - list_add(&r->res_root_list, &ls->ls_root_list); - dlm_hold_rsb(r); - } - - if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[i].toss)) - log_error(ls, "dlm_create_root_list toss not empty"); - spin_unlock(&ls->ls_rsbtbl[i].lock); - } - out: - up_write(&ls->ls_root_sem); - return error; -} - -void dlm_release_root_list(struct dlm_ls *ls) +void dlm_clear_inactive(struct dlm_ls *ls) { struct dlm_rsb *r, *safe; + unsigned int count = 0; - down_write(&ls->ls_root_sem); - list_for_each_entry_safe(r, safe, &ls->ls_root_list, res_root_list) { - list_del_init(&r->res_root_list); - dlm_put_rsb(r); - } - up_write(&ls->ls_root_sem); -} + write_lock_bh(&ls->ls_rsbtbl_lock); + list_for_each_entry_safe(r, safe, &ls->ls_slow_inactive, res_slow_list) { + list_del(&r->res_slow_list); + rhashtable_remove_fast(&ls->ls_rsbtbl, &r->res_node, + dlm_rhash_rsb_params); -void dlm_clear_toss(struct dlm_ls *ls) -{ - struct rb_node *n, *next; - struct dlm_rsb *r; - unsigned int count = 0; - int i; - - for (i = 0; i < ls->ls_rsbtbl_size; i++) { - spin_lock(&ls->ls_rsbtbl[i].lock); - for (n = rb_first(&ls->ls_rsbtbl[i].toss); n; n = next) { - next = rb_next(n); - r = rb_entry(n, struct dlm_rsb, res_hashnode); - rb_erase(n, &ls->ls_rsbtbl[i].toss); - dlm_free_rsb(r); - count++; - } - spin_unlock(&ls->ls_rsbtbl[i].lock); + if (!list_empty(&r->res_scan_list)) + list_del_init(&r->res_scan_list); + + free_inactive_rsb(r); + count++; } + write_unlock_bh(&ls->ls_rsbtbl_lock); if (count) - log_rinfo(ls, "dlm_clear_toss %u done", count); + log_rinfo(ls, "dlm_clear_inactive %u done", count); } |