From 1416bd508c78bdfdb9ae0b4511369e5581f348ea Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Tue, 20 Jan 2026 10:35:05 -0500 Subject: [PATCH 1/6] dlm: fix recovery pending middle conversion During a workload involving conversions between lock modes PR and CW, lock recovery can create a "conversion deadlock" state between locks that have been recovered. When this occurs, kernel warning messages are logged, e.g. "dlm: WARN: pending deadlock 1e node 0 2 1bf21" "dlm: receive_rcom_lock_args 2e middle convert gr 3 rq 2 remote 2 1e" After this occurs, the deadlocked conversions both appear on the convert queue of the resource being locked, and the conversion requests do not complete. Outside of recovery, conversions that would produce a deadlock are resolved immediately, and return -EDEADLK. The locks are not placed on the convert queue in the deadlocked state. To fix this problem, an lkb under conversion between PR/CW is rebuilt during recovery on a new master's granted queue, with the currently granted mode, rather than being rebuilt on the new master's convert queue, with the currently granted mode and the newly requested mode. The in-progress convert is then resent to the new master after recovery, so the conversion deadlock will be processed outside of the recovery context and handled as described above. Signed-off-by: Alexander Aring Signed-off-by: David Teigland --- fs/dlm/lock.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index be938fdf17d9..c01a291db401 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -5014,25 +5014,8 @@ void dlm_receive_buffer(const union dlm_packet *p, int nodeid) static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb, struct dlm_message *ms_local) { - if (middle_conversion(lkb)) { - log_rinfo(ls, "%s %x middle convert in progress", __func__, - lkb->lkb_id); - - /* We sent this lock to the new master. The new master will - * tell us when it's granted. We no longer need a reply, so - * use a fake reply to put the lkb into the right state. - */ - hold_lkb(lkb); - memset(ms_local, 0, sizeof(struct dlm_message)); - ms_local->m_type = cpu_to_le32(DLM_MSG_CONVERT_REPLY); - ms_local->m_result = cpu_to_le32(to_dlm_errno(-EINPROGRESS)); - ms_local->m_header.h_nodeid = cpu_to_le32(lkb->lkb_nodeid); - _receive_convert_reply(lkb, ms_local, true); - unhold_lkb(lkb); - - } else if (lkb->lkb_rqmode >= lkb->lkb_grmode) { + if (middle_conversion(lkb) || lkb->lkb_rqmode >= lkb->lkb_grmode) set_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags); - } /* lkb->lkb_rqmode < lkb->lkb_grmode shouldn't happen since down conversions are async; there's no reply from the remote master */ From 080e5563f878c64e697b89e7439d730d0daad882 Mon Sep 17 00:00:00 2001 From: Ezrak1e Date: Tue, 20 Jan 2026 10:35:06 -0500 Subject: [PATCH 2/6] dlm: validate length in dlm_search_rsb_tree The len parameter in dlm_dump_rsb_name() is not validated and comes from network messages. When it exceeds DLM_RESNAME_MAXLEN, it can cause out-of-bounds write in dlm_search_rsb_tree(). Add length validation to prevent potential buffer overflow. Signed-off-by: Ezrak1e Signed-off-by: Alexander Aring Signed-off-by: David Teigland --- fs/dlm/lock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index c01a291db401..a393ecaf3442 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -626,7 +626,8 @@ int dlm_search_rsb_tree(struct rhashtable *rhash, const void *name, int len, struct dlm_rsb **r_ret) { char key[DLM_RESNAME_MAXLEN] = {}; - + if (len > DLM_RESNAME_MAXLEN) + return -EINVAL; memcpy(key, name, len); *r_ret = rhashtable_lookup_fast(rhash, &key, dlm_rhash_rsb_params); if (*r_ret) From 6155b409761f50c7f3353739610bb37e02422116 Mon Sep 17 00:00:00 2001 From: Shaurya Rane Date: Tue, 20 Jan 2026 10:35:07 -0500 Subject: [PATCH 3/6] fs/dlm: use list_add_tail() instead of open-coding list insertion Replace the manual list pointer manipulation in add_ordered_member() with the standard list_add_tail() helper. The original code explicitly updated ->prev and ->next pointers to insert @newlist before @tmp, which is exactly what list_add_tail(newlist, tmp) provides. Using the list macro improves readability, removes a source of potential pointer bugs, and satisfies the existing FIXME requesting conversion to the list helpers. No functional change in the ordering logic for DLM members. Signed-off-by: Shaurya Rane Signed-off-by: Alexander Aring Signed-off-by: David Teigland --- fs/dlm/member.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/fs/dlm/member.c b/fs/dlm/member.c index c0f557a80a75..c1b5598997b7 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c @@ -299,11 +299,7 @@ static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new) if (!memb) list_add_tail(newlist, head); else { - /* FIXME: can use list macro here */ - newlist->prev = tmp->prev; - newlist->next = tmp; - tmp->prev->next = newlist; - tmp->prev = newlist; + list_add_tail(newlist, tmp); } } From 596ce53d647ca7c8d6408a4148dc44ead39e8474 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 20 Jan 2026 10:35:08 -0500 Subject: [PATCH 4/6] dlm: Constify struct configfs_item_operations and configfs_group_operations 'struct configfs_item_operations' and 'configfs_group_operations' are not modified in this driver. Constifying these structures moves some data to a read-only section, so increases overall security, especially when the structure holds some function pointers. On a x86_64, with allmodconfig, as an example: Before: ====== text data bss dec hex filename 29436 12952 384 42772 a714 fs/dlm/config.o After: ===== text data bss dec hex filename 30076 12312 384 42772 a714 fs/dlm/config.o Signed-off-by: Christophe JAILLET Signed-off-by: Alexander Aring Signed-off-by: David Teigland --- fs/dlm/config.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/dlm/config.c b/fs/dlm/config.c index a0d75b5c83c6..82cc3215663f 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -324,39 +324,39 @@ struct dlm_member_gone { struct list_head list; /* space->members_gone */ }; -static struct configfs_group_operations clusters_ops = { +static const struct configfs_group_operations clusters_ops = { .make_group = make_cluster, .drop_item = drop_cluster, }; -static struct configfs_item_operations cluster_ops = { +static const struct configfs_item_operations cluster_ops = { .release = release_cluster, }; -static struct configfs_group_operations spaces_ops = { +static const struct configfs_group_operations spaces_ops = { .make_group = make_space, .drop_item = drop_space, }; -static struct configfs_item_operations space_ops = { +static const struct configfs_item_operations space_ops = { .release = release_space, }; -static struct configfs_group_operations comms_ops = { +static const struct configfs_group_operations comms_ops = { .make_item = make_comm, .drop_item = drop_comm, }; -static struct configfs_item_operations comm_ops = { +static const struct configfs_item_operations comm_ops = { .release = release_comm, }; -static struct configfs_group_operations nodes_ops = { +static const struct configfs_group_operations nodes_ops = { .make_item = make_node, .drop_item = drop_node, }; -static struct configfs_item_operations node_ops = { +static const struct configfs_item_operations node_ops = { .release = release_node, }; From 6dda4f0a31b0b8c0824cb63ebda600e6da886e1d Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Tue, 20 Jan 2026 10:35:09 -0500 Subject: [PATCH 5/6] fs/dlm/dir: remove unuse variable count_match The variable was never used after introduced. Better to comment it if we want to keep the info. fs/dlm/dir.c:65:26: error: variable 'count_match' set but not used [-Werror,-Wunused-but-set-variable] 65 | unsigned int count = 0, count_match = 0, count_bad = 0, count_add = 0; | ^ 1 error generated. Signed-off-by: Alex Shi Signed-off-by: Alexander Aring Signed-off-by: David Teigland --- fs/dlm/dir.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c index b1ab0adbd9d0..01c292379f5b 100644 --- a/fs/dlm/dir.c +++ b/fs/dlm/dir.c @@ -62,7 +62,7 @@ int dlm_recover_directory(struct dlm_ls *ls, uint64_t seq) char *b, *last_name = NULL; int error = -ENOMEM, last_len, nodeid, result; uint16_t namelen; - unsigned int count = 0, count_match = 0, count_bad = 0, count_add = 0; + unsigned int count = 0, count_bad = 0, count_add = 0; log_rinfo(ls, "dlm_recover_directory"); @@ -157,12 +157,12 @@ int dlm_recover_directory(struct dlm_ls *ls, uint64_t seq) } /* The name was found in rsbtbl, and the - * master nodeid matches memb->nodeid. */ + * master nodeid matches memb->nodeid. if (result == DLM_LU_MATCH && nodeid == memb->nodeid) { count_match++; - } + }*/ /* The name was not found in rsbtbl and was * added with memb->nodeid as the master. */ From 2c3a0b730012ef87aaaf35243e1fbe9880666f7c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 22 Sep 2025 16:20:47 +0200 Subject: [PATCH 6/6] dlm: Avoid -Wflex-array-member-not-at-end warning -Wflex-array-member-not-at-end was introduced in GCC-14, and we are getting ready to enable it, globally. Move the conflicting declaration to the end of the corresponding structure. Notice that `struct dlm_message` is a flexible structure, this is a structure that contains a flexible-array member. Fix the following warning: fs/dlm/dlm_internal.h:609:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end] Signed-off-by: Gustavo A. R. Silva Signed-off-by: David Teigland --- fs/dlm/dlm_internal.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index d534a4bc162b..9df842421ae0 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -606,7 +606,6 @@ struct dlm_ls { struct dlm_rsb ls_local_rsb; /* for returning errors */ struct dlm_lkb ls_local_lkb; /* for returning errors */ - struct dlm_message ls_local_ms; /* for faking a reply */ struct dentry *ls_debug_rsb_dentry; /* debugfs */ struct dentry *ls_debug_waiters_dentry; /* debugfs */ @@ -665,6 +664,9 @@ struct dlm_ls { int ls_namelen; char ls_name[DLM_LOCKSPACE_LEN + 1]; + + /* Must be last --ends in a flexible-array member.*/ + struct dlm_message ls_local_ms; /* for faking a reply */ }; /*