Whamcloud - gitweb
new llog_ldlm process and mgc_enqueue
[fs/lustre-release.git] / lustre / ldlm / l_lock.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5  *
6  *   This file is part of the Lustre file system, http://www.lustre.org
7  *   Lustre is a trademark of Cluster File Systems, Inc.
8  *
9  *   You may have signed or agreed to another license before downloading
10  *   this software.  If so, you are bound by the terms and conditions
11  *   of that agreement, and the following does not apply to you.  See the
12  *   LICENSE file included with this distribution for more information.
13  *
14  *   If you did not agree to a different license, then this copy of Lustre
15  *   is open source software; you can redistribute it and/or modify it
16  *   under the terms of version 2 of the GNU General Public License as
17  *   published by the Free Software Foundation.
18  *
19  *   In either case, Lustre is distributed in the hope that it will be
20  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
21  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *   license text for more details.
23  *
24  */
25
26 #define DEBUG_SUBSYSTEM S_LDLM
27 #ifdef __KERNEL__
28 #include <linux/config.h>
29 #include <linux/kernel.h>
30 #include <linux/mm.h>
31 #include <linux/string.h>
32 #include <linux/stat.h>
33 #include <linux/errno.h>
34 #include <linux/unistd.h>
35 #include <linux/version.h>
36
37 #include <asm/system.h>
38 #include <asm/uaccess.h>
39
40 #include <linux/fs.h>
41 #include <linux/stat.h>
42 #include <asm/uaccess.h>
43 #include <asm/segment.h>
44 #include <linux/mm.h>
45 #include <linux/pagemap.h>
46 #include <linux/smp_lock.h>
47 #else 
48 #include <liblustre.h>
49 #endif
50
51 #include <linux/lustre_dlm.h>
52 #include <linux/lustre_lib.h>
53
54 /* invariants:
55  - only the owner of the lock changes l_owner/l_depth
56  - if a non-owner changes or checks the variables a spin lock is taken
57 */
58
59 void l_lock_init(struct lustre_lock *lock)
60 {
61         sema_init(&lock->l_sem, 1);
62         spin_lock_init(&lock->l_spin);
63 }
64
65 void l_lock(struct lustre_lock *lock)
66 {
67         int owner = 0;
68
69         spin_lock(&lock->l_spin);
70         if (lock->l_owner == current)
71                 owner = 1;
72         spin_unlock(&lock->l_spin);
73
74         /* This is safe to increment outside the spinlock because we
75          * can only have 1 CPU running on the current task
76          * (i.e. l_owner == current), regardless of the number of CPUs.
77          */
78         if (owner) {
79                 ++lock->l_depth;
80         } else {
81                 down(&lock->l_sem);
82                 spin_lock(&lock->l_spin);
83                 lock->l_owner = current;
84                 lock->l_depth = 0;
85                 spin_unlock(&lock->l_spin);
86         }
87 }
88
89 void l_unlock(struct lustre_lock *lock)
90 {
91         LASSERTF(lock->l_owner == current, "lock %p, current %p\n",
92                  lock->l_owner, current);
93         LASSERTF(lock->l_depth >= 0, "depth %d\n", lock->l_depth);
94
95         spin_lock(&lock->l_spin);
96         if (--lock->l_depth < 0) {
97                 lock->l_owner = NULL;
98                 spin_unlock(&lock->l_spin);
99                 up(&lock->l_sem);
100                 return;
101         }
102         spin_unlock(&lock->l_spin);
103 }
104
105 int l_has_lock(struct lustre_lock *lock)
106 {
107         int depth = -1, owner = 0;
108
109         spin_lock(&lock->l_spin);
110         if (lock->l_owner == current) {
111                 depth = lock->l_depth;
112                 owner = 1;
113         }
114         spin_unlock(&lock->l_spin);
115
116         if (depth >= 0)
117                 CDEBUG(D_INFO, "lock_depth: %d\n", depth);
118         return owner;
119 }
120
121 #ifdef __KERNEL__
122 #include <linux/lustre_version.h>
123 void l_check_ns_lock(struct ldlm_namespace *ns)
124 {
125         static unsigned long next_msg;
126
127         if (!l_has_lock(&ns->ns_lock) && time_after(jiffies, next_msg)) {
128                 CERROR("namespace %s lock not held when it should be; tell "
129                        "phil\n", ns->ns_name);
130                 libcfs_debug_dumpstack(NULL);
131                 next_msg = jiffies + 60 * HZ;
132         }
133 }
134
135 void l_check_no_ns_lock(struct ldlm_namespace *ns)
136 {
137         static unsigned long next_msg;
138
139         if (l_has_lock(&ns->ns_lock) && time_after(jiffies, next_msg)) {
140                 CERROR("namespace %s lock held illegally; tell phil\n",
141                        ns->ns_name);
142                 libcfs_debug_dumpstack(NULL);
143                 next_msg = jiffies + 60 * HZ;
144         }
145 }
146
147 #else
148 void l_check_ns_lock(struct ldlm_namespace *ns)
149 {
150         if (!l_has_lock(&ns->ns_lock)) {
151                 CERROR("namespace %s lock not held when it should be; tell "
152                        "phil\n", ns->ns_name);
153         }
154 }
155
156 void l_check_no_ns_lock(struct ldlm_namespace *ns)
157 {
158         if (l_has_lock(&ns->ns_lock)) {
159                 CERROR("namespace %s lock held illegally; tell phil\n",
160                        ns->ns_name);
161         }
162 }
163 #endif /* __KERNEL__ */