]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
dlm: add new configfs entry release_recover for lockspace members
authorAlexander Aring <aahringo@redhat.com>
Wed, 23 Jul 2025 15:21:55 +0000 (11:21 -0400)
committerDavid Teigland <teigland@redhat.com>
Tue, 12 Aug 2025 16:32:09 +0000 (11:32 -0500)
A new configfs entry is added for a lockspace member:
  /config/dlm/<cluster>/spaces/<space>/nodes/<node>/release_recover

release_recover can be set to 1 by userspace (dlm_controld process)
prior to removing the lockspace member (rmdir of the <node>).
This tells the kernel to handle the removed member as if it had failed,
i.e. recovery steps for a failed node should be perfomed, as opposed
to the recovery steps for a node doing a controlled leave.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
fs/dlm/config.c
fs/dlm/config.h
fs/dlm/member.c

index a23fd524a6ee35a686d1b0ac385036c668159a38..a0d75b5c83c63266113a0ca051c56b7b1008b1f2 100644 (file)
@@ -26,6 +26,7 @@
 /*
  * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/nodeid (refers to <node>)
  * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight
+ * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/release_recover
  * /config/dlm/<cluster>/comms/<comm>/nodeid (refers to <comm>)
  * /config/dlm/<cluster>/comms/<comm>/local
  * /config/dlm/<cluster>/comms/<comm>/addr      (write only)
@@ -267,6 +268,7 @@ enum {
 enum {
        NODE_ATTR_NODEID = 0,
        NODE_ATTR_WEIGHT,
+       NODE_ATTR_RELEASE_RECOVER,
 };
 
 struct dlm_clusters {
@@ -280,6 +282,8 @@ struct dlm_spaces {
 struct dlm_space {
        struct config_group group;
        struct list_head members;
+       struct list_head members_gone;
+       int members_gone_count;
        struct mutex members_lock;
        int members_count;
        struct dlm_nodes *nds;
@@ -310,6 +314,14 @@ struct dlm_node {
        int weight;
        int new;
        int comm_seq; /* copy of cm->seq when nd->nodeid is set */
+       unsigned int release_recover;
+};
+
+struct dlm_member_gone {
+       int nodeid;
+       unsigned int release_recover;
+
+       struct list_head list; /* space->members_gone */
 };
 
 static struct configfs_group_operations clusters_ops = {
@@ -480,6 +492,7 @@ static struct config_group *make_space(struct config_group *g, const char *name)
        configfs_add_default_group(&nds->ns_group, &sp->group);
 
        INIT_LIST_HEAD(&sp->members);
+       INIT_LIST_HEAD(&sp->members_gone);
        mutex_init(&sp->members_lock);
        sp->members_count = 0;
        sp->nds = nds;
@@ -587,10 +600,20 @@ static void drop_node(struct config_group *g, struct config_item *i)
 {
        struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
        struct dlm_node *nd = config_item_to_node(i);
+       struct dlm_member_gone *mb_gone;
+
+       mb_gone = kzalloc(sizeof(*mb_gone), GFP_KERNEL);
+       if (!mb_gone)
+               return;
 
        mutex_lock(&sp->members_lock);
        list_del(&nd->list);
        sp->members_count--;
+
+       mb_gone->nodeid = nd->nodeid;
+       mb_gone->release_recover = nd->release_recover;
+       list_add(&mb_gone->list, &sp->members_gone);
+       sp->members_gone_count++;
        mutex_unlock(&sp->members_lock);
 
        config_item_put(i);
@@ -815,12 +838,34 @@ static ssize_t node_weight_store(struct config_item *item, const char *buf,
        return len;
 }
 
+static ssize_t node_release_recover_show(struct config_item *item, char *buf)
+{
+       struct dlm_node *n = config_item_to_node(item);
+
+       return sprintf(buf, "%u\n", n->release_recover);
+}
+
+static ssize_t node_release_recover_store(struct config_item *item,
+                                         const char *buf, size_t len)
+{
+       struct dlm_node *n = config_item_to_node(item);
+       int rc;
+
+       rc = kstrtouint(buf, 0, &n->release_recover);
+       if (rc)
+               return rc;
+
+       return len;
+}
+
 CONFIGFS_ATTR(node_, nodeid);
 CONFIGFS_ATTR(node_, weight);
+CONFIGFS_ATTR(node_, release_recover);
 
 static struct configfs_attribute *node_attrs[] = {
        [NODE_ATTR_NODEID] = &node_attr_nodeid,
        [NODE_ATTR_WEIGHT] = &node_attr_weight,
+       [NODE_ATTR_RELEASE_RECOVER] = &node_attr_release_recover,
        NULL,
 };
 
@@ -882,9 +927,10 @@ static void put_comm(struct dlm_comm *cm)
 int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
                     int *count_out)
 {
+       struct dlm_member_gone *mb_gone, *mb_safe;
+       struct dlm_config_node *nodes, *node;
        struct dlm_space *sp;
        struct dlm_node *nd;
-       struct dlm_config_node *nodes, *node;
        int rv, count;
 
        sp = get_space(lsname);
@@ -898,7 +944,7 @@ int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
                goto out;
        }
 
-       count = sp->members_count;
+       count = sp->members_count + sp->members_gone_count;
 
        nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS);
        if (!nodes) {
@@ -917,6 +963,20 @@ int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
                nd->new = 0;
        }
 
+       /* we delay the remove on nodes until here as configfs does
+        * not support addtional attributes for rmdir().
+        */
+       list_for_each_entry_safe(mb_gone, mb_safe, &sp->members_gone, list) {
+               node->nodeid = mb_gone->nodeid;
+               node->release_recover = mb_gone->release_recover;
+               node->gone = true;
+               node++;
+
+               list_del(&mb_gone->list);
+               sp->members_gone_count--;
+               kfree(mb_gone);
+       }
+
        *count_out = count;
        *nodes_out = nodes;
        rv = 0;
index 13a3d0b2619425f26ae3b2aced59d21d4d7bcc16..4ebd45f752762c8d11982fd3f95e8798c78151f1 100644 (file)
 struct dlm_config_node {
        int nodeid;
        int weight;
+       bool gone;
        int new;
        uint32_t comm_seq;
+       unsigned int release_recover;
 };
 
 extern const struct rhashtable_params dlm_rhash_rsb_params;
index b0864c93230f53dd4e31ee23550bcc7335fae765..152d2cb16f59143c55968afc11e58d82fec1c156 100644 (file)
@@ -569,10 +569,10 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
 
        list_for_each_entry_safe(memb, safe, &ls->ls_nodes, list) {
                node = find_config_node(rv, memb->nodeid);
-               if (node && !node->new)
+               if (node && !node->new && !node->gone)
                        continue;
 
-               if (!node) {
+               if (node->gone) {
                        log_rinfo(ls, "remove member %d", memb->nodeid);
                } else {
                        /* removed and re-added */
@@ -591,6 +591,9 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
 
        for (i = 0; i < rv->nodes_count; i++) {
                node = &rv->nodes[i];
+               if (node->gone)
+                       continue;
+
                if (dlm_is_member(ls, node->nodeid))
                        continue;
                error = dlm_add_member(ls, node);