mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-03 00:54:09 +08:00
dlm: fix user space lock decision to copy lvb
[ Upstream commitad191e0eee
] 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:61bed0baa4
("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
0fdbbe7ee7
commit
bc236ebc2a
14
fs/dlm/ast.c
14
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;
|
||||
|
@ -222,6 +222,7 @@ struct dlm_callback {
|
||||
int sb_status; /* copy to lksb status */
|
||||
uint8_t sb_flags; /* copy to lksb flags */
|
||||
int8_t mode; /* rq mode of bast, gr mode of cast */
|
||||
int copy_lvb;
|
||||
|
||||
struct list_head list;
|
||||
struct kref ref;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "dlm_internal.h"
|
||||
#include "lockspace.h"
|
||||
#include "lock.h"
|
||||
#include "lvb_table.h"
|
||||
#include "user.h"
|
||||
#include "ast.h"
|
||||
#include "config.h"
|
||||
@ -806,8 +805,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
|
||||
struct dlm_lkb *lkb;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
struct dlm_callback *cb;
|
||||
int rv, ret, copy_lvb = 0;
|
||||
int old_mode, new_mode;
|
||||
int rv, ret;
|
||||
|
||||
if (count == sizeof(struct dlm_device_version)) {
|
||||
rv = copy_version_to_user(buf, count);
|
||||
@ -864,9 +862,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
|
||||
|
||||
lkb = list_first_entry(&proc->asts, struct dlm_lkb, lkb_cb_list);
|
||||
|
||||
/* rem_lkb_callback sets a new lkb_last_cast */
|
||||
old_mode = lkb->lkb_last_cast->mode;
|
||||
|
||||
rv = dlm_dequeue_lkb_callback(lkb, &cb);
|
||||
switch (rv) {
|
||||
case DLM_DEQUEUE_CALLBACK_EMPTY:
|
||||
@ -895,12 +890,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
|
||||
if (cb->flags & DLM_CB_BAST) {
|
||||
trace_dlm_bast(lkb->lkb_resource->res_ls, lkb, cb->mode);
|
||||
} else if (cb->flags & DLM_CB_CAST) {
|
||||
new_mode = cb->mode;
|
||||
|
||||
if (!cb->sb_status && lkb->lkb_lksb->sb_lvbptr &&
|
||||
dlm_lvb_operations[old_mode + 1][new_mode + 1])
|
||||
copy_lvb = 1;
|
||||
|
||||
lkb->lkb_lksb->sb_status = cb->sb_status;
|
||||
lkb->lkb_lksb->sb_flags = cb->sb_flags;
|
||||
trace_dlm_ast(lkb->lkb_resource->res_ls, lkb);
|
||||
@ -908,7 +897,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
|
||||
|
||||
ret = copy_result_to_user(lkb->lkb_ua,
|
||||
test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
|
||||
cb->flags, cb->mode, copy_lvb, buf, count);
|
||||
cb->flags, cb->mode, cb->copy_lvb, buf, count);
|
||||
|
||||
kref_put(&cb->ref, dlm_release_callback);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user