*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2008 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
#include "dlm_internal.h"
#include "lock.h"
+#include "user.h"
#include "ast.h"
#define WAKE_ASTS 0
static spinlock_t ast_queue_lock;
static struct task_struct * astd_task;
static unsigned long astd_wakeflags;
-static struct semaphore astd_running;
+static struct mutex astd_running;
void dlm_del_ast(struct dlm_lkb *lkb)
spin_unlock(&ast_queue_lock);
}
-void dlm_add_ast(struct dlm_lkb *lkb, int type)
+void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
{
+ if (lkb->lkb_flags & DLM_IFL_USER) {
+ dlm_user_add_ast(lkb, type, bastmode);
+ return;
+ }
+
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;
+ if (bastmode)
+ lkb->lkb_bastmode = bastmode;
spin_unlock(&ast_queue_lock);
set_bit(WAKE_ASTS, &astd_wakeflags);
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);
+ void (*cast) (void *astparam);
+ void (*bast) (void *astparam, int mode);
+ int type = 0, bastmode;
+
+repeat:
+ spin_lock(&ast_queue_lock);
+ list_for_each_entry(lkb, &ast_queue, lkb_astqueue) {
+ r = lkb->lkb_resource;
+ ls = r->res_ls;
- if (!found)
- break;
+ if (dlm_locking_stopped(ls))
+ continue;
- cast = lkb->lkb_astaddr;
- bast = lkb->lkb_bastaddr;
- bmode = lkb->lkb_bastmode;
+ list_del(&lkb->lkb_astqueue);
+ type = lkb->lkb_ast_type;
+ lkb->lkb_ast_type = 0;
+ bastmode = lkb->lkb_bastmode;
+
+ spin_unlock(&ast_queue_lock);
+ cast = lkb->lkb_astfn;
+ bast = lkb->lkb_bastfn;
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);
+ bast(lkb->lkb_astparam, bastmode);
/* this removes the reference added by dlm_add_ast
and may result in the lkb being freed */
dlm_put_lkb(lkb);
- schedule();
+ cond_resched();
+ goto repeat;
}
+ spin_unlock(&ast_queue_lock);
}
static inline int no_asts(void)
schedule();
set_current_state(TASK_RUNNING);
- down(&astd_running);
+ mutex_lock(&astd_running);
if (test_and_clear_bit(WAKE_ASTS, &astd_wakeflags))
process_asts();
- up(&astd_running);
+ mutex_unlock(&astd_running);
}
return 0;
}
INIT_LIST_HEAD(&ast_queue);
spin_lock_init(&ast_queue_lock);
- init_MUTEX(&astd_running);
+ mutex_init(&astd_running);
p = kthread_run(dlm_astd, NULL, "dlm_astd");
if (IS_ERR(p))
void dlm_astd_suspend(void)
{
- down(&astd_running);
+ mutex_lock(&astd_running);
}
void dlm_astd_resume(void)
{
- up(&astd_running);
+ mutex_unlock(&astd_running);
}