mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2026-02-01 20:13:26 +00:00
This patch fixes the following issue: node 1 is dir node 2 is master node 3 is other 1->2: unlock 2: put final lkb, rsb moved to toss 2->1: unlock_reply 1: queue lkb callback with EUNLOCK 2->1: remove 1: receive_remove ignored (rsb on keep because of queued lkb callback) 1: complete lkb callback, put_lkb, move rsb to toss 3->1: lookup 1->3: lookup_reply master=2 3->2: request 2->3: request_reply EBADR In summary: An unexpected lkb reference causes the rsb to remain on the wrong list. The rsb being on the wrong list causes receive_remove to be ignored. An ignored receive_remove causes inconsistent dir and master state. This sequence requires an unusually long delay in delivering the unlock callback, because the remove message from 2->1 usually happens after some seconds. So, it's not known exactly how frequently this sequence occurs in pratice. It's possible that the same end result could also have another unknown cause. The solution for this issue is to further separate callback state from the lkb, so that an lkb reference (and from that, an rsb ref) are not held while a callback remains queued. Then, within the unlock_reply, the lkb will be freed and the rsb moved to the toss list. So, the receive_remove will not be ignored. Signed-off-by: Alexander Aring <aahringo@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com>
34 lines
1.2 KiB
C
34 lines
1.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/******************************************************************************
|
|
*******************************************************************************
|
|
**
|
|
** Copyright (C) 2005-2010 Red Hat, Inc. All rights reserved.
|
|
**
|
|
**
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
#ifndef __ASTD_DOT_H__
|
|
#define __ASTD_DOT_H__
|
|
|
|
#define DLM_ENQUEUE_CALLBACK_NEED_SCHED 1
|
|
#define DLM_ENQUEUE_CALLBACK_SUCCESS 0
|
|
#define DLM_ENQUEUE_CALLBACK_FAILURE -1
|
|
int dlm_queue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
|
|
int status, uint32_t sbflags,
|
|
struct dlm_callback **cb);
|
|
void dlm_add_cb(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
|
|
uint32_t sbflags);
|
|
void dlm_callback_set_last_ptr(struct dlm_callback **from,
|
|
struct dlm_callback *to);
|
|
|
|
void dlm_release_callback(struct kref *ref);
|
|
int dlm_callback_start(struct dlm_ls *ls);
|
|
void dlm_callback_stop(struct dlm_ls *ls);
|
|
void dlm_callback_suspend(struct dlm_ls *ls);
|
|
void dlm_callback_resume(struct dlm_ls *ls);
|
|
|
|
#endif
|
|
|
|
|