Skip to content

Commit

Permalink
[DLM] The core of the DLM for GFS2/CLVM
Browse files Browse the repository at this point in the history
This is the core of the distributed lock manager which is required
to use GFS2 as a cluster filesystem. It is also used by CLVM and
can be used as a standalone lock manager independantly of either
of these two projects.

It implements VAX-style locking modes.

Signed-off-by: David Teigland <[email protected]>
Signed-off-by: Steve Whitehouse <[email protected]>
  • Loading branch information
teigland authored and swhiteho committed Jan 18, 2006
1 parent e473142 commit e7fd417
Show file tree
Hide file tree
Showing 39 changed files with 12,178 additions and 0 deletions.
1 change: 1 addition & 0 deletions fs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1831,6 +1831,7 @@ source "fs/partitions/Kconfig"
endmenu

source "fs/nls/Kconfig"
source "fs/dlm/Kconfig"

endmenu

1 change: 1 addition & 0 deletions fs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ obj-$(CONFIG_SYSFS) += sysfs/
obj-y += devpts/

obj-$(CONFIG_PROFILING) += dcookies.o
obj-$(CONFIG_DLM) += dlm/

# Do not add any filesystems before this line
obj-$(CONFIG_REISERFS_FS) += reiserfs/
Expand Down
30 changes: 30 additions & 0 deletions fs/dlm/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
menu "Distributed Lock Manager"
depends on INET && EXPERIMENTAL

config DLM
tristate "Distributed Lock Manager (DLM)"
depends on SYSFS
depends on IPV6 || IPV6=n
select IP_SCTP
select CONFIGFS_FS
help
A general purpose distributed lock manager for kernel or userspace
applications.

config DLM_DEVICE
tristate "DLM device for userspace access"
depends on DLM
help
This module creates a misc device through which the dlm lockspace
and locking functions become available to userspace applications
(usually through the libdlm library).

config DLM_DEBUG
bool "DLM debugging"
depends on DLM
help
Under the debugfs mount point, the name of each lockspace will
appear as a file in the "dlm" directory. The output is the
list of resource and locks the local node knows about.

endmenu
21 changes: 21 additions & 0 deletions fs/dlm/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
obj-$(CONFIG_DLM) += dlm.o
obj-$(CONFIG_DLM_DEVICE) += dlm_device.o

dlm-y := ast.o \
config.o \
dir.o \
lock.o \
lockspace.o \
lowcomms.o \
main.o \
member.o \
memory.o \
midcomms.o \
rcom.o \
recover.o \
recoverd.o \
requestqueue.o \
util.o
dlm-$(CONFIG_DLM_DEBUG) += debug_fs.o

dlm_device-y := device.o
167 changes: 167 additions & 0 deletions fs/dlm/ast.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/******************************************************************************
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
** of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/

#include "dlm_internal.h"
#include "lock.h"
#include "ast.h"

#define WAKE_ASTS 0

static struct list_head ast_queue;
static spinlock_t ast_queue_lock;
static struct task_struct * astd_task;
static unsigned long astd_wakeflags;
static struct semaphore astd_running;


void dlm_del_ast(struct dlm_lkb *lkb)
{
spin_lock(&ast_queue_lock);
if (lkb->lkb_ast_type & (AST_COMP | AST_BAST))
list_del(&lkb->lkb_astqueue);
spin_unlock(&ast_queue_lock);
}

void dlm_add_ast(struct dlm_lkb *lkb, int type)
{
spin_lock(&ast_queue_lock);
if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
kref_get(&lkb->lkb_ref);
list_add_tail(&lkb->lkb_astqueue, &ast_queue);
}
lkb->lkb_ast_type |= type;
spin_unlock(&ast_queue_lock);

set_bit(WAKE_ASTS, &astd_wakeflags);
wake_up_process(astd_task);
}

static void process_asts(void)
{
struct dlm_ls *ls = NULL;
struct dlm_rsb *r = NULL;
struct dlm_lkb *lkb;
void (*cast) (long param);
void (*bast) (long param, int mode);
int type = 0, found, bmode;

for (;;) {
found = FALSE;
spin_lock(&ast_queue_lock);
list_for_each_entry(lkb, &ast_queue, lkb_astqueue) {
r = lkb->lkb_resource;
ls = r->res_ls;

if (dlm_locking_stopped(ls))
continue;

list_del(&lkb->lkb_astqueue);
type = lkb->lkb_ast_type;
lkb->lkb_ast_type = 0;
found = TRUE;
break;
}
spin_unlock(&ast_queue_lock);

if (!found)
break;

cast = lkb->lkb_astaddr;
bast = lkb->lkb_bastaddr;
bmode = lkb->lkb_bastmode;

if ((type & AST_COMP) && cast)
cast(lkb->lkb_astparam);

/* FIXME: Is it safe to look at lkb_grmode here
without doing a lock_rsb() ?
Look at other checks in v1 to avoid basts. */

if ((type & AST_BAST) && bast)
if (!dlm_modes_compat(lkb->lkb_grmode, bmode))
bast(lkb->lkb_astparam, bmode);

/* this removes the reference added by dlm_add_ast
and may result in the lkb being freed */
dlm_put_lkb(lkb);

schedule();
}
}

static inline int no_asts(void)
{
int ret;

spin_lock(&ast_queue_lock);
ret = list_empty(&ast_queue);
spin_unlock(&ast_queue_lock);
return ret;
}

static int dlm_astd(void *data)
{
while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE);
if (!test_bit(WAKE_ASTS, &astd_wakeflags))
schedule();
set_current_state(TASK_RUNNING);

down(&astd_running);
if (test_and_clear_bit(WAKE_ASTS, &astd_wakeflags))
process_asts();
up(&astd_running);
}
return 0;
}

void dlm_astd_wake(void)
{
if (!no_asts()) {
set_bit(WAKE_ASTS, &astd_wakeflags);
wake_up_process(astd_task);
}
}

int dlm_astd_start(void)
{
struct task_struct *p;
int error = 0;

INIT_LIST_HEAD(&ast_queue);
spin_lock_init(&ast_queue_lock);
init_MUTEX(&astd_running);

p = kthread_run(dlm_astd, NULL, "dlm_astd");
if (IS_ERR(p))
error = PTR_ERR(p);
else
astd_task = p;
return error;
}

void dlm_astd_stop(void)
{
kthread_stop(astd_task);
}

void dlm_astd_suspend(void)
{
down(&astd_running);
}

void dlm_astd_resume(void)
{
up(&astd_running);
}

26 changes: 26 additions & 0 deletions fs/dlm/ast.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/******************************************************************************
*******************************************************************************
**
** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
** of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/

#ifndef __ASTD_DOT_H__
#define __ASTD_DOT_H__

void dlm_add_ast(struct dlm_lkb *lkb, int type);
void dlm_del_ast(struct dlm_lkb *lkb);

void dlm_astd_wake(void);
int dlm_astd_start(void);
void dlm_astd_stop(void);
void dlm_astd_suspend(void);
void dlm_astd_resume(void);

#endif

Loading

0 comments on commit e7fd417

Please sign in to comment.