Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 27 Feb 2010 01:19:30 +0000 (17:19 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 27 Feb 2010 01:19:30 +0000 (17:19 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm:
  dlm: use bastmode in debugfs output
  dlm: Send lockspace name with uevents
  dlm: send reply before bast
  dlm: fix ordering of bast and cast

fs/dlm/ast.c
fs/dlm/ast.h
fs/dlm/debug_fs.c
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lockspace.c
fs/dlm/user.c
fs/dlm/user.h

index dc2ad60..4314f0d 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2010 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
@@ -33,10 +33,10 @@ void dlm_del_ast(struct dlm_lkb *lkb)
        spin_unlock(&ast_queue_lock);
 }
 
-void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
+void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode)
 {
        if (lkb->lkb_flags & DLM_IFL_USER) {
-               dlm_user_add_ast(lkb, type, bastmode);
+               dlm_user_add_ast(lkb, type, mode);
                return;
        }
 
@@ -44,10 +44,21 @@ void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
        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_first = type;
        }
+
+       /* sanity check, this should not happen */
+
+       if ((type == AST_COMP) && (lkb->lkb_ast_type & AST_COMP))
+               log_print("repeat cast %d castmode %d lock %x %s",
+                         mode, lkb->lkb_castmode,
+                         lkb->lkb_id, lkb->lkb_resource->res_name);
+
        lkb->lkb_ast_type |= type;
-       if (bastmode)
-               lkb->lkb_bastmode = bastmode;
+       if (type == AST_BAST)
+               lkb->lkb_bastmode = mode;
+       else
+               lkb->lkb_castmode = mode;
        spin_unlock(&ast_queue_lock);
 
        set_bit(WAKE_ASTS, &astd_wakeflags);
@@ -59,9 +70,9 @@ static void process_asts(void)
        struct dlm_ls *ls = NULL;
        struct dlm_rsb *r = NULL;
        struct dlm_lkb *lkb;
-       void (*cast) (void *astparam);
-       void (*bast) (void *astparam, int mode);
-       int type = 0, bastmode;
+       void (*castfn) (void *astparam);
+       void (*bastfn) (void *astparam, int mode);
+       int type, first, bastmode, castmode, do_bast, do_cast, last_castmode;
 
 repeat:
        spin_lock(&ast_queue_lock);
@@ -75,17 +86,48 @@ repeat:
                list_del(&lkb->lkb_astqueue);
                type = lkb->lkb_ast_type;
                lkb->lkb_ast_type = 0;
+               first = lkb->lkb_ast_first;
+               lkb->lkb_ast_first = 0;
                bastmode = lkb->lkb_bastmode;
-
+               castmode = lkb->lkb_castmode;
+               castfn = lkb->lkb_astfn;
+               bastfn = lkb->lkb_bastfn;
                spin_unlock(&ast_queue_lock);
-               cast = lkb->lkb_astfn;
-               bast = lkb->lkb_bastfn;
-
-               if ((type & AST_COMP) && cast)
-                       cast(lkb->lkb_astparam);
 
-               if ((type & AST_BAST) && bast)
-                       bast(lkb->lkb_astparam, bastmode);
+               do_cast = (type & AST_COMP) && castfn;
+               do_bast = (type & AST_BAST) && bastfn;
+
+               /* Skip a bast if its blocking mode is compatible with the
+                  granted mode of the preceding cast. */
+
+               if (do_bast) {
+                       if (first == AST_COMP)
+                               last_castmode = castmode;
+                       else
+                               last_castmode = lkb->lkb_castmode_done;
+                       if (dlm_modes_compat(bastmode, last_castmode))
+                               do_bast = 0;
+               }
+
+               if (first == AST_COMP) {
+                       if (do_cast)
+                               castfn(lkb->lkb_astparam);
+                       if (do_bast)
+                               bastfn(lkb->lkb_astparam, bastmode);
+               } else if (first == AST_BAST) {
+                       if (do_bast)
+                               bastfn(lkb->lkb_astparam, bastmode);
+                       if (do_cast)
+                               castfn(lkb->lkb_astparam);
+               } else {
+                       log_error(ls, "bad ast_first %d ast_type %d",
+                                 first, type);
+               }
+
+               if (do_cast)
+                       lkb->lkb_castmode_done = castmode;
+               if (do_bast)
+                       lkb->lkb_bastmode_done = bastmode;
 
                /* this removes the reference added by dlm_add_ast
                   and may result in the lkb being freed */
index 1b5fc5f..bcb1aab 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2010 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
@@ -13,7 +13,7 @@
 #ifndef __ASTD_DOT_H__
 #define __ASTD_DOT_H__
 
-void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode);
+void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode);
 void dlm_del_ast(struct dlm_lkb *lkb);
 
 void dlm_astd_wake(void);
index 375a235..29d6139 100644 (file)
@@ -256,7 +256,7 @@ static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
                        lkb->lkb_status,
                        lkb->lkb_grmode,
                        lkb->lkb_rqmode,
-                       lkb->lkb_highbast,
+                       lkb->lkb_bastmode,
                        rsb_lookup,
                        lkb->lkb_wait_type,
                        lkb->lkb_lvbseq,
index 826d3dc..f632b58 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2010 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
@@ -232,11 +232,17 @@ struct dlm_lkb {
        int8_t                  lkb_status;     /* granted, waiting, convert */
        int8_t                  lkb_rqmode;     /* requested lock mode */
        int8_t                  lkb_grmode;     /* granted lock mode */
-       int8_t                  lkb_bastmode;   /* requested mode */
        int8_t                  lkb_highbast;   /* highest mode bast sent for */
+
        int8_t                  lkb_wait_type;  /* type of reply waiting for */
        int8_t                  lkb_wait_count;
        int8_t                  lkb_ast_type;   /* type of ast queued for */
+       int8_t                  lkb_ast_first;  /* type of first ast queued */
+
+       int8_t                  lkb_bastmode;   /* req mode of queued bast */
+       int8_t                  lkb_castmode;   /* gr mode of queued cast */
+       int8_t                  lkb_bastmode_done; /* last delivered bastmode */
+       int8_t                  lkb_castmode_done; /* last delivered castmode */
 
        struct list_head        lkb_idtbl_list; /* lockspace lkbtbl */
        struct list_head        lkb_statequeue; /* rsb g/c/w list */
index 9c0c1db..46ffd3e 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2010 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
@@ -307,7 +307,7 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
        lkb->lkb_lksb->sb_status = rv;
        lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
 
-       dlm_add_ast(lkb, AST_COMP, 0);
+       dlm_add_ast(lkb, AST_COMP, lkb->lkb_grmode);
 }
 
 static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -320,10 +320,12 @@ static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
 {
        lkb->lkb_time_bast = ktime_get();
 
-       if (is_master_copy(lkb))
+       if (is_master_copy(lkb)) {
+               lkb->lkb_bastmode = rqmode; /* printed by debugfs */
                send_bast(r, lkb, rqmode);
-       else
+       } else {
                dlm_add_ast(lkb, AST_BAST, rqmode);
+       }
 }
 
 /*
@@ -2280,20 +2282,30 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
        if (can_be_queued(lkb)) {
                error = -EINPROGRESS;
                add_lkb(r, lkb, DLM_LKSTS_WAITING);
-               send_blocking_asts(r, lkb);
                add_timeout(lkb);
                goto out;
        }
 
        error = -EAGAIN;
-       if (force_blocking_asts(lkb))
-               send_blocking_asts_all(r, lkb);
        queue_cast(r, lkb, -EAGAIN);
-
  out:
        return error;
 }
 
+static void do_request_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
+                              int error)
+{
+       switch (error) {
+       case -EAGAIN:
+               if (force_blocking_asts(lkb))
+                       send_blocking_asts_all(r, lkb);
+               break;
+       case -EINPROGRESS:
+               send_blocking_asts(r, lkb);
+               break;
+       }
+}
+
 static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
        int error = 0;
@@ -2304,7 +2316,6 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
        if (can_be_granted(r, lkb, 1, &deadlk)) {
                grant_lock(r, lkb);
                queue_cast(r, lkb, 0);
-               grant_pending_locks(r);
                goto out;
        }
 
@@ -2334,7 +2345,6 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
                if (_can_be_granted(r, lkb, 1)) {
                        grant_lock(r, lkb);
                        queue_cast(r, lkb, 0);
-                       grant_pending_locks(r);
                        goto out;
                }
                /* else fall through and move to convert queue */
@@ -2344,28 +2354,47 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
                error = -EINPROGRESS;
                del_lkb(r, lkb);
                add_lkb(r, lkb, DLM_LKSTS_CONVERT);
-               send_blocking_asts(r, lkb);
                add_timeout(lkb);
                goto out;
        }
 
        error = -EAGAIN;
-       if (force_blocking_asts(lkb))
-               send_blocking_asts_all(r, lkb);
        queue_cast(r, lkb, -EAGAIN);
-
  out:
        return error;
 }
 
+static void do_convert_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
+                              int error)
+{
+       switch (error) {
+       case 0:
+               grant_pending_locks(r);
+               /* grant_pending_locks also sends basts */
+               break;
+       case -EAGAIN:
+               if (force_blocking_asts(lkb))
+                       send_blocking_asts_all(r, lkb);
+               break;
+       case -EINPROGRESS:
+               send_blocking_asts(r, lkb);
+               break;
+       }
+}
+
 static int do_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
        remove_lock(r, lkb);
        queue_cast(r, lkb, -DLM_EUNLOCK);
-       grant_pending_locks(r);
        return -DLM_EUNLOCK;
 }
 
+static void do_unlock_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
+                             int error)
+{
+       grant_pending_locks(r);
+}
+
 /* returns: 0 did nothing, -DLM_ECANCEL canceled lock */
  
 static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -2375,12 +2404,18 @@ static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb)
        error = revert_lock(r, lkb);
        if (error) {
                queue_cast(r, lkb, -DLM_ECANCEL);
-               grant_pending_locks(r);
                return -DLM_ECANCEL;
        }
        return 0;
 }
 
+static void do_cancel_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
+                             int error)
+{
+       if (error)
+               grant_pending_locks(r);
+}
+
 /*
  * Four stage 3 varieties:
  * _request_lock(), _convert_lock(), _unlock_lock(), _cancel_lock()
@@ -2402,11 +2437,15 @@ static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
                goto out;
        }
 
-       if (is_remote(r))
+       if (is_remote(r)) {
                /* receive_request() calls do_request() on remote node */
                error = send_request(r, lkb);
-       else
+       } else {
                error = do_request(r, lkb);
+               /* for remote locks the request_reply is sent
+                  between do_request and do_request_effects */
+               do_request_effects(r, lkb, error);
+       }
  out:
        return error;
 }
@@ -2417,11 +2456,15 @@ static int _convert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
        int error;
 
-       if (is_remote(r))
+       if (is_remote(r)) {
                /* receive_convert() calls do_convert() on remote node */
                error = send_convert(r, lkb);
-       else
+       } else {
                error = do_convert(r, lkb);
+               /* for remote locks the convert_reply is sent
+                  between do_convert and do_convert_effects */
+               do_convert_effects(r, lkb, error);
+       }
 
        return error;
 }
@@ -2432,11 +2475,15 @@ static int _unlock_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
        int error;
 
-       if (is_remote(r))
+       if (is_remote(r)) {
                /* receive_unlock() calls do_unlock() on remote node */
                error = send_unlock(r, lkb);
-       else
+       } else {
                error = do_unlock(r, lkb);
+               /* for remote locks the unlock_reply is sent
+                  between do_unlock and do_unlock_effects */
+               do_unlock_effects(r, lkb, error);
+       }
 
        return error;
 }
@@ -2447,11 +2494,15 @@ static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
        int error;
 
-       if (is_remote(r))
+       if (is_remote(r)) {
                /* receive_cancel() calls do_cancel() on remote node */
                error = send_cancel(r, lkb);
-       else
+       } else {
                error = do_cancel(r, lkb);
+               /* for remote locks the cancel_reply is sent
+                  between do_cancel and do_cancel_effects */
+               do_cancel_effects(r, lkb, error);
+       }
 
        return error;
 }
@@ -3191,6 +3242,7 @@ static void receive_request(struct dlm_ls *ls, struct dlm_message *ms)
        attach_lkb(r, lkb);
        error = do_request(r, lkb);
        send_request_reply(r, lkb, error);
+       do_request_effects(r, lkb, error);
 
        unlock_rsb(r);
        put_rsb(r);
@@ -3226,15 +3278,19 @@ static void receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
                goto out;
 
        receive_flags(lkb, ms);
+
        error = receive_convert_args(ls, lkb, ms);
-       if (error)
-               goto out_reply;
+       if (error) {
+               send_convert_reply(r, lkb, error);
+               goto out;
+       }
+
        reply = !down_conversion(lkb);
 
        error = do_convert(r, lkb);
- out_reply:
        if (reply)
                send_convert_reply(r, lkb, error);
+       do_convert_effects(r, lkb, error);
  out:
        unlock_rsb(r);
        put_rsb(r);
@@ -3266,13 +3322,16 @@ static void receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
                goto out;
 
        receive_flags(lkb, ms);
+
        error = receive_unlock_args(ls, lkb, ms);
-       if (error)
-               goto out_reply;
+       if (error) {
+               send_unlock_reply(r, lkb, error);
+               goto out;
+       }
 
        error = do_unlock(r, lkb);
- out_reply:
        send_unlock_reply(r, lkb, error);
+       do_unlock_effects(r, lkb, error);
  out:
        unlock_rsb(r);
        put_rsb(r);
@@ -3307,6 +3366,7 @@ static void receive_cancel(struct dlm_ls *ls, struct dlm_message *ms)
 
        error = do_cancel(r, lkb);
        send_cancel_reply(r, lkb, error);
+       do_cancel_effects(r, lkb, error);
  out:
        unlock_rsb(r);
        put_rsb(r);
index c010ecf..26a8bd4 100644 (file)
@@ -191,6 +191,18 @@ static int do_uevent(struct dlm_ls *ls, int in)
        return error;
 }
 
+static int dlm_uevent(struct kset *kset, struct kobject *kobj,
+                     struct kobj_uevent_env *env)
+{
+       struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
+
+       add_uevent_var(env, "LOCKSPACE=%s", ls->ls_name);
+       return 0;
+}
+
+static struct kset_uevent_ops dlm_uevent_ops = {
+       .uevent = dlm_uevent,
+};
 
 int __init dlm_lockspace_init(void)
 {
@@ -199,7 +211,7 @@ int __init dlm_lockspace_init(void)
        INIT_LIST_HEAD(&lslist);
        spin_lock_init(&lslist_lock);
 
-       dlm_kset = kset_create_and_add("dlm", NULL, kernel_kobj);
+       dlm_kset = kset_create_and_add("dlm", &dlm_uevent_ops, kernel_kobj);
        if (!dlm_kset) {
                printk(KERN_WARNING "%s: can not create kset\n", __func__);
                return -ENOMEM;
index e73a4bb..a4bfd31 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2009 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2006-2010 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
@@ -173,7 +173,7 @@ static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
 /* we could possibly check if the cancel of an orphan has resulted in the lkb
    being removed and then remove that lkb from the orphans list and free it */
 
-void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
+void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode)
 {
        struct dlm_ls *ls;
        struct dlm_user_args *ua;
@@ -206,8 +206,10 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
 
        ast_type = lkb->lkb_ast_type;
        lkb->lkb_ast_type |= type;
-       if (bastmode)
-               lkb->lkb_bastmode = bastmode;
+       if (type == AST_BAST)
+               lkb->lkb_bastmode = mode;
+       else
+               lkb->lkb_castmode = mode;
 
        if (!ast_type) {
                kref_get(&lkb->lkb_ref);
index 1c96864..f196091 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2006-2010 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
@@ -9,7 +9,7 @@
 #ifndef __USER_DOT_H__
 #define __USER_DOT_H__
 
-void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode);
+void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode);
 int dlm_user_init(void);
 void dlm_user_exit(void);
 int dlm_device_deregister(struct dlm_ls *ls);