]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
dlm: add rsb lists for iteration
authorAlexander Aring <aahringo@redhat.com>
Mon, 15 Apr 2024 18:39:38 +0000 (14:39 -0400)
committerDavid Teigland <teigland@redhat.com>
Tue, 16 Apr 2024 19:33:25 +0000 (14:33 -0500)
To prepare for using rhashtable, add two rsb lists for iterating
through rsb's in two uncommon cases where this is necesssary:
- when dumping rsb state from debugfs, now using seq_list.
- when looking at all rsb's during recovery.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
fs/dlm/debug_fs.c
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lockspace.c
fs/dlm/recover.c
fs/dlm/recoverd.c

index 37f4dfca5e44120b20e17536c6295447132ce955..70567919f1b7f0cc389bbb8ea2c83648011d6ff9 100644 (file)
@@ -366,12 +366,10 @@ static void print_format4(struct dlm_rsb *r, struct seq_file *s)
        unlock_rsb(r);
 }
 
-struct rsbtbl_iter {
-       struct dlm_rsb *rsb;
-       unsigned bucket;
-       int format;
-       int header;
-};
+static const struct seq_operations format1_seq_ops;
+static const struct seq_operations format2_seq_ops;
+static const struct seq_operations format3_seq_ops;
+static const struct seq_operations format4_seq_ops;
 
 /*
  * If the buffer is full, seq_printf can be called again, but it
@@ -382,220 +380,61 @@ struct rsbtbl_iter {
 
 static int table_seq_show(struct seq_file *seq, void *iter_ptr)
 {
-       struct rsbtbl_iter *ri = iter_ptr;
-
-       switch (ri->format) {
-       case 1:
-               print_format1(ri->rsb, seq);
-               break;
-       case 2:
-               if (ri->header) {
-                       seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
-                       ri->header = 0;
-               }
-               print_format2(ri->rsb, seq);
-               break;
-       case 3:
-               if (ri->header) {
-                       seq_puts(seq, "rsb ptr nodeid first_lkid flags !root_list_empty !recover_list_empty recover_locks_count len\n");
-                       ri->header = 0;
-               }
-               print_format3(ri->rsb, seq);
-               break;
-       case 4:
-               if (ri->header) {
-                       seq_puts(seq, "rsb ptr nodeid master_nodeid dir_nodeid our_nodeid toss_time flags len str|hex name\n");
-                       ri->header = 0;
-               }
-               print_format4(ri->rsb, seq);
-               break;
-       }
+       struct dlm_rsb *rsb = list_entry(iter_ptr, struct dlm_rsb, res_rsbs_list);
+
+       if (seq->op == &format1_seq_ops)
+               print_format1(rsb, seq);
+       else if (seq->op == &format2_seq_ops)
+               print_format2(rsb, seq);
+       else if (seq->op == &format3_seq_ops)
+               print_format3(rsb, seq);
+       else if (seq->op == &format4_seq_ops)
+               print_format4(rsb, seq);
 
        return 0;
 }
 
-static const struct seq_operations format1_seq_ops;
-static const struct seq_operations format2_seq_ops;
-static const struct seq_operations format3_seq_ops;
-static const struct seq_operations format4_seq_ops;
-
 static void *table_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       struct rb_root *tree;
-       struct rb_node *node;
        struct dlm_ls *ls = seq->private;
-       struct rsbtbl_iter *ri;
-       struct dlm_rsb *r;
-       loff_t n = *pos;
-       unsigned bucket, entry;
-       int toss = (seq->op == &format4_seq_ops);
-
-       bucket = n >> 32;
-       entry = n & ((1LL << 32) - 1);
-
-       if (bucket >= ls->ls_rsbtbl_size)
-               return NULL;
-
-       ri = kzalloc(sizeof(*ri), GFP_NOFS);
-       if (!ri)
-               return NULL;
-       if (n == 0)
-               ri->header = 1;
-       if (seq->op == &format1_seq_ops)
-               ri->format = 1;
-       if (seq->op == &format2_seq_ops)
-               ri->format = 2;
-       if (seq->op == &format3_seq_ops)
-               ri->format = 3;
-       if (seq->op == &format4_seq_ops)
-               ri->format = 4;
-
-       tree = &ls->ls_rsbtbl[bucket].r;
+       struct list_head *list;
 
-       spin_lock_bh(&ls->ls_rsbtbl_lock);
-       if (!RB_EMPTY_ROOT(tree)) {
-               for (node = rb_first(tree); node; node = rb_next(node)) {
-                       r = rb_entry(node, struct dlm_rsb, res_hashnode);
-                       if (toss) {
-                               if (!rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       } else {
-                               if (rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       }
-
-                       if (!entry--) {
-                               dlm_hold_rsb(r);
-                               ri->rsb = r;
-                               ri->bucket = bucket;
-                               spin_unlock_bh(&ls->ls_rsbtbl_lock);
-                               return ri;
-                       }
-               }
+       if (!*pos) {
+               if (seq->op == &format2_seq_ops)
+                       seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
+               else if (seq->op == &format3_seq_ops)
+                       seq_puts(seq, "rsb ptr nodeid first_lkid flags !root_list_empty !recover_list_empty recover_locks_count len\n");
+               else if (seq->op == &format4_seq_ops)
+                       seq_puts(seq, "rsb ptr nodeid master_nodeid dir_nodeid our_nodeid toss_time flags len str|hex name\n");
        }
-       spin_unlock_bh(&ls->ls_rsbtbl_lock);
-
-       /*
-        * move to the first rsb in the next non-empty bucket
-        */
-
-       /* zero the entry */
-       n &= ~((1LL << 32) - 1);
 
-       while (1) {
-               bucket++;
-               n += 1LL << 32;
+       if (seq->op == &format4_seq_ops)
+               list = &ls->ls_toss;
+       else
+               list = &ls->ls_keep;
 
-               if (bucket >= ls->ls_rsbtbl_size) {
-                       kfree(ri);
-                       return NULL;
-               }
-               tree = &ls->ls_rsbtbl[bucket].r;
-
-               spin_lock_bh(&ls->ls_rsbtbl_lock);
-               if (!RB_EMPTY_ROOT(tree)) {
-                       node = rb_first(tree);
-                       r = rb_entry(node, struct dlm_rsb, res_hashnode);
-                       if (toss) {
-                               if (!rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       } else {
-                               if (rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       }
-
-                       dlm_hold_rsb(r);
-                       ri->rsb = r;
-                       ri->bucket = bucket;
-                       spin_unlock_bh(&ls->ls_rsbtbl_lock);
-                       *pos = n;
-                       return ri;
-               }
-               spin_unlock_bh(&ls->ls_rsbtbl_lock);
-       }
+       spin_lock_bh(&ls->ls_rsbtbl_lock);
+       return seq_list_start(list, *pos);
 }
 
 static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
 {
        struct dlm_ls *ls = seq->private;
-       struct rsbtbl_iter *ri = iter_ptr;
-       struct rb_root *tree;
-       struct rb_node *next;
-       struct dlm_rsb *r, *rp;
-       loff_t n = *pos;
-       unsigned bucket;
-       int toss = (seq->op == &format4_seq_ops);
-
-       bucket = n >> 32;
-
-       /*
-        * move to the next rsb in the same bucket
-        */
-
-       spin_lock_bh(&ls->ls_rsbtbl_lock);
-       rp = ri->rsb;
-       next = rb_next(&rp->res_hashnode);
-
-       if (next) {
-               r = rb_entry(next, struct dlm_rsb, res_hashnode);
-               dlm_hold_rsb(r);
-               ri->rsb = r;
-               spin_unlock_bh(&ls->ls_rsbtbl_lock);
-               dlm_put_rsb(rp);
-               ++*pos;
-               return ri;
-       }
-       spin_unlock_bh(&ls->ls_rsbtbl_lock);
-       dlm_put_rsb(rp);
-
-       /*
-        * move to the first rsb in the next non-empty bucket
-        */
+       struct list_head *list;
 
-       /* zero the entry */
-       n &= ~((1LL << 32) - 1);
-
-       while (1) {
-               bucket++;
-               n += 1LL << 32;
+       if (seq->op == &format4_seq_ops)
+               list = &ls->ls_toss;
+       else
+               list = &ls->ls_keep;
 
-               if (bucket >= ls->ls_rsbtbl_size) {
-                       kfree(ri);
-                       ++*pos;
-                       return NULL;
-               }
-               tree = &ls->ls_rsbtbl[bucket].r;
-
-               spin_lock_bh(&ls->ls_rsbtbl_lock);
-               if (!RB_EMPTY_ROOT(tree)) {
-                       next = rb_first(tree);
-                       r = rb_entry(next, struct dlm_rsb, res_hashnode);
-                       if (toss) {
-                               if (!rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       } else {
-                               if (rsb_flag(r, RSB_TOSS))
-                                       continue;
-                       }
-                       dlm_hold_rsb(r);
-                       ri->rsb = r;
-                       ri->bucket = bucket;
-                       spin_unlock_bh(&ls->ls_rsbtbl_lock);
-                       *pos = n;
-                       return ri;
-               }
-               spin_unlock_bh(&ls->ls_rsbtbl_lock);
-       }
+       return seq_list_next(iter_ptr, list, pos);
 }
 
 static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
 {
-       struct rsbtbl_iter *ri = iter_ptr;
+       struct dlm_ls *ls = seq->private;
 
-       if (ri) {
-               dlm_put_rsb(ri->rsb);
-               kfree(ri);
-       }
+       spin_unlock_bh(&ls->ls_rsbtbl_lock);
 }
 
 static const struct seq_operations format1_seq_ops = {
index af88fc2f978c296d7b3d2ab0c3d42613c29c5818..6d06840029c362495c89233676102f528fa59c6e 100644 (file)
@@ -339,6 +339,7 @@ struct dlm_rsb {
        struct list_head        res_convertqueue;
        struct list_head        res_waitqueue;
 
+       struct list_head        res_rsbs_list;
        struct list_head        res_root_list;      /* used for recovery */
        struct list_head        res_masters_list;   /* used for recovery */
        struct list_head        res_recover_list;   /* used for recovery */
@@ -595,6 +596,9 @@ struct dlm_ls {
        spinlock_t              ls_rsbtbl_lock;
        uint32_t                ls_rsbtbl_size;
 
+       struct list_head        ls_toss;
+       struct list_head        ls_keep;
+
        spinlock_t              ls_waiters_lock;
        struct list_head        ls_waiters;     /* lkbs needing a reply */
 
index 08ec1a04476a71ab3d98f304e9700140e9efe9d5..a70b8edb5d3f5f93e302e8b229abe55b180cd1a1 100644 (file)
@@ -668,6 +668,7 @@ static int find_rsb_dir(struct dlm_ls *ls, const void *name, int len,
                r->res_first_lkid = 0;
        }
 
+       list_move(&r->res_rsbs_list, &ls->ls_keep);
        rsb_clear_flag(r, RSB_TOSS);
        goto out_unlock;
 
@@ -730,6 +731,8 @@ static int find_rsb_dir(struct dlm_ls *ls, const void *name, int len,
 
  out_add:
        error = rsb_insert(r, &ls->ls_rsbtbl[b].r);
+       if (!error)
+               list_add(&r->res_rsbs_list, &ls->ls_keep);
  out_unlock:
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
  out:
@@ -801,6 +804,7 @@ static int find_rsb_nodir(struct dlm_ls *ls, const void *name, int len,
                r->res_nodeid = 0;
        }
 
+       list_move(&r->res_rsbs_list, &ls->ls_keep);
        rsb_clear_flag(r, RSB_TOSS);
        goto out_unlock;
 
@@ -826,6 +830,8 @@ static int find_rsb_nodir(struct dlm_ls *ls, const void *name, int len,
        kref_init(&r->res_ref);
 
        error = rsb_insert(r, &ls->ls_rsbtbl[b].r);
+       if (!error)
+               list_add(&r->res_rsbs_list, &ls->ls_keep);
  out_unlock:
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
  out:
@@ -1110,6 +1116,8 @@ int dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *name,
                goto retry;
        }
 
+       list_add(&r->res_rsbs_list, &ls->ls_toss);
+
        if (result)
                *result = DLM_LU_ADD;
        *r_nodeid = from_nodeid;
@@ -1120,20 +1128,12 @@ int dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *name,
 
 static void dlm_dump_rsb_hash(struct dlm_ls *ls, uint32_t hash)
 {
-       struct rb_node *n;
        struct dlm_rsb *r;
-       int i;
 
        spin_lock_bh(&ls->ls_rsbtbl_lock);
-       for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               for (n = rb_first(&ls->ls_rsbtbl[i].r); n; n = rb_next(n)) {
-                       r = rb_entry(n, struct dlm_rsb, res_hashnode);
-                       if (rsb_flag(r, RSB_TOSS))
-                               continue;
-
-                       if (r->res_hash == hash)
-                               dlm_dump_rsb(r);
-               }
+       list_for_each_entry(r, &ls->ls_keep, res_rsbs_list) {
+               if (r->res_hash == hash)
+                       dlm_dump_rsb(r);
        }
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
 }
@@ -1166,6 +1166,7 @@ static void toss_rsb(struct kref *kref)
        kref_init(&r->res_ref);
        WARN_ON(rsb_flag(r, RSB_TOSS));
        rsb_set_flag(r, RSB_TOSS);
+       list_move(&r->res_rsbs_list, &ls->ls_toss);
        r->res_toss_time = jiffies;
        set_bit(DLM_RTF_SHRINK_BIT, &ls->ls_rsbtbl[r->res_bucket].flags);
        if (r->res_lvbptr) {
@@ -1672,6 +1673,7 @@ static void shrink_bucket(struct dlm_ls *ls, int b)
                        continue;
                }
 
+               list_del(&r->res_rsbs_list);
                rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].r);
                dlm_free_rsb(r);
        }
@@ -1740,6 +1742,7 @@ static void shrink_bucket(struct dlm_ls *ls, int b)
                        continue;
                }
 
+               list_del(&r->res_rsbs_list);
                rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].r);
                send_remove(r);
                spin_unlock_bh(&ls->ls_rsbtbl_lock);
@@ -4243,6 +4246,7 @@ static void receive_remove(struct dlm_ls *ls, const struct dlm_message *ms)
        }
 
        if (kref_put(&r->res_ref, kill_rsb)) {
+               list_del(&r->res_rsbs_list);
                rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].r);
                spin_unlock_bh(&ls->ls_rsbtbl_lock);
                dlm_free_rsb(r);
@@ -5313,17 +5317,12 @@ void dlm_recover_purge(struct dlm_ls *ls, const struct list_head *root_list)
                          lkb_count, nodes_count);
 }
 
-static struct dlm_rsb *find_grant_rsb(struct dlm_ls *ls, int bucket)
+static struct dlm_rsb *find_grant_rsb(struct dlm_ls *ls)
 {
-       struct rb_node *n;
        struct dlm_rsb *r;
 
        spin_lock_bh(&ls->ls_rsbtbl_lock);
-       for (n = rb_first(&ls->ls_rsbtbl[bucket].r); n; n = rb_next(n)) {
-               r = rb_entry(n, struct dlm_rsb, res_hashnode);
-               if (rsb_flag(r, RSB_TOSS))
-                       continue;
-
+       list_for_each_entry(r, &ls->ls_keep, res_rsbs_list) {
                if (!rsb_flag(r, RSB_RECOVER_GRANT))
                        continue;
                if (!is_master(r)) {
@@ -5358,19 +5357,15 @@ static struct dlm_rsb *find_grant_rsb(struct dlm_ls *ls, int bucket)
 void dlm_recover_grant(struct dlm_ls *ls)
 {
        struct dlm_rsb *r;
-       int bucket = 0;
        unsigned int count = 0;
        unsigned int rsb_count = 0;
        unsigned int lkb_count = 0;
 
        while (1) {
-               r = find_grant_rsb(ls, bucket);
-               if (!r) {
-                       if (bucket == ls->ls_rsbtbl_size - 1)
-                               break;
-                       bucket++;
-                       continue;
-               }
+               r = find_grant_rsb(ls);
+               if (!r)
+                       break;
+
                rsb_count++;
                count = 0;
                lock_rsb(r);
index b5184ad550fa947802dfd66d737ff3d46d0b09de..2b5771a7bf3119b4bce03f474dab94322134a987 100644 (file)
@@ -495,6 +495,8 @@ static int new_lockspace(const char *name, const char *cluster,
         */
        ls->ls_exflags = (flags & ~(DLM_LSFL_FS | DLM_LSFL_NEWEXCL));
 
+       INIT_LIST_HEAD(&ls->ls_toss);
+       INIT_LIST_HEAD(&ls->ls_keep);
        spin_lock_init(&ls->ls_rsbtbl_lock);
        size = READ_ONCE(dlm_config.ci_rsbtbl_size);
        ls->ls_rsbtbl_size = size;
@@ -838,6 +840,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
        for (i = 0; i < ls->ls_rsbtbl_size; i++) {
                while ((n = rb_first(&ls->ls_rsbtbl[i].r))) {
                        rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
+                       list_del(&rsb->res_rsbs_list);
                        rb_erase(n, &ls->ls_rsbtbl[i].r);
                        dlm_free_rsb(rsb);
                }
index e53d88e4ec935302e7959d27df9a6a7af0d29ea5..512c1ae81a96e587c825c92c67be0890f40fea0c 100644 (file)
@@ -881,23 +881,15 @@ void dlm_recover_rsbs(struct dlm_ls *ls, const struct list_head *root_list)
 
 void dlm_clear_toss(struct dlm_ls *ls)
 {
-       struct rb_node *n, *next;
-       struct dlm_rsb *r;
+       struct dlm_rsb *r, *safe;
        unsigned int count = 0;
-       int i;
-
-       spin_lock(&ls->ls_rsbtbl_lock);
-       for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               for (n = rb_first(&ls->ls_rsbtbl[i].r); n; n = next) {
-                       next = rb_next(n);
-                       r = rb_entry(n, struct dlm_rsb, res_hashnode);
-                       if (!rsb_flag(r, RSB_TOSS))
-                               continue;
-
-                       rb_erase(n, &ls->ls_rsbtbl[i].r);
-                       dlm_free_rsb(r);
-                       count++;
-               }
+
+       spin_lock_bh(&ls->ls_rsbtbl_lock);
+       list_for_each_entry_safe(r, safe, &ls->ls_toss, res_rsbs_list) {
+               list_del(&r->res_rsbs_list);
+               rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[r->res_bucket].r);
+               dlm_free_rsb(r);
+               count++;
        }
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
 
index ad696528ebe7b715903265924a1720b297f81051..5e8e10030b744ae69f8bc50da7ad6dc0c979579e 100644 (file)
@@ -22,9 +22,8 @@
 
 static int dlm_create_masters_list(struct dlm_ls *ls)
 {
-       struct rb_node *n;
        struct dlm_rsb *r;
-       int i, error = 0;
+       int error = 0;
 
        write_lock_bh(&ls->ls_masters_lock);
        if (!list_empty(&ls->ls_masters_list)) {
@@ -34,15 +33,12 @@ static int dlm_create_masters_list(struct dlm_ls *ls)
        }
 
        spin_lock_bh(&ls->ls_rsbtbl_lock);
-       for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               for (n = rb_first(&ls->ls_rsbtbl[i].r); n; n = rb_next(n)) {
-                       r = rb_entry(n, struct dlm_rsb, res_hashnode);
-                       if (rsb_flag(r, RSB_TOSS) || r->res_nodeid)
-                               continue;
-
-                       list_add(&r->res_masters_list, &ls->ls_masters_list);
-                       dlm_hold_rsb(r);
-               }
+       list_for_each_entry(r, &ls->ls_keep, res_rsbs_list) {
+               if (r->res_nodeid)
+                       continue;
+
+               list_add(&r->res_masters_list, &ls->ls_masters_list);
+               dlm_hold_rsb(r);
        }
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
  out:
@@ -64,21 +60,15 @@ static void dlm_release_masters_list(struct dlm_ls *ls)
 
 static void dlm_create_root_list(struct dlm_ls *ls, struct list_head *root_list)
 {
-       struct rb_node *n;
        struct dlm_rsb *r;
-       int i;
 
        spin_lock_bh(&ls->ls_rsbtbl_lock);
-       for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               for (n = rb_first(&ls->ls_rsbtbl[i].r); n; n = rb_next(n)) {
-                       r = rb_entry(n, struct dlm_rsb, res_hashnode);
-                       if (WARN_ON_ONCE(rsb_flag(r, RSB_TOSS)))
-                               continue;
-
-                       list_add(&r->res_root_list, root_list);
-                       dlm_hold_rsb(r);
-               }
+       list_for_each_entry(r, &ls->ls_keep, res_rsbs_list) {
+               list_add(&r->res_root_list, root_list);
+               dlm_hold_rsb(r);
        }
+
+       WARN_ON_ONCE(!list_empty(&ls->ls_toss));
        spin_unlock_bh(&ls->ls_rsbtbl_lock);
 }