summaryrefslogtreecommitdiffstats
path: root/fs/dlm/ast.c
diff options
context:
space:
mode:
authorAlexander Aring <aahringo@redhat.com>2024-03-28 16:48:33 +0100
committerDavid Teigland <teigland@redhat.com>2024-04-01 20:31:12 +0200
commitad191e0eeebf64a60ca2d16ca01a223d2b1dd25e (patch)
treeb7c967baae9edceeb693fc064cec42ef87896b7e /fs/dlm/ast.c
parentLinux 6.9-rc2 (diff)
downloadlinux-ad191e0eeebf64a60ca2d16ca01a223d2b1dd25e.tar.xz
linux-ad191e0eeebf64a60ca2d16ca01a223d2b1dd25e.zip
dlm: fix user space lock decision to copy lvb
This patch fixes the copy lvb decision for user space lock requests. Checking dlm_lvb_operations is done earlier, where granted/requested lock modes are available to use in the matrix. The decision had been moved to the wrong location, where granted mode and requested mode where the same, which causes the dlm_lvb_operations matix to produce the wrong copy decision. For PW or EX requests, the caller could get invalid lvb data. Fixes: 61bed0baa4db ("fs: dlm: use a non-static queue for callbacks") Signed-off-by: Alexander Aring <aahringo@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm/ast.c')
-rw-r--r--fs/dlm/ast.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index 1f2f70a1b824..decedc4ee15f 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.c
@@ -12,6 +12,7 @@
#include <trace/events/dlm.h>
#include "dlm_internal.h"
+#include "lvb_table.h"
#include "memory.h"
#include "lock.h"
#include "user.h"
@@ -42,6 +43,7 @@ int dlm_enqueue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
struct dlm_ls *ls = lkb->lkb_resource->res_ls;
int rv = DLM_ENQUEUE_CALLBACK_SUCCESS;
struct dlm_callback *cb;
+ int copy_lvb = 0;
int prev_mode;
if (flags & DLM_CB_BAST) {
@@ -73,6 +75,17 @@ int dlm_enqueue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
goto out;
}
}
+ } else if (flags & DLM_CB_CAST) {
+ if (test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) {
+ if (lkb->lkb_last_cast)
+ prev_mode = lkb->lkb_last_cb->mode;
+ else
+ prev_mode = -1;
+
+ if (!status && lkb->lkb_lksb->sb_lvbptr &&
+ dlm_lvb_operations[prev_mode + 1][mode + 1])
+ copy_lvb = 1;
+ }
}
cb = dlm_allocate_cb();
@@ -85,6 +98,7 @@ int dlm_enqueue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
cb->mode = mode;
cb->sb_status = status;
cb->sb_flags = (sbflags & 0x000000FF);
+ cb->copy_lvb = copy_lvb;
kref_init(&cb->ref);
if (!test_and_set_bit(DLM_IFL_CB_PENDING_BIT, &lkb->lkb_iflags))
rv = DLM_ENQUEUE_CALLBACK_NEED_SCHED;