Whamcloud - gitweb
4c729214f9c239b05c7bb83ac660999b79f10b5a
[fs/lustre-release.git] / lustre / kernel_patches / patches / dynamic-locks-2.4.24.patch
1  include/linux/dynlocks.h |   33 ++++++++++
2  lib/Makefile             |    4 -
3  lib/dynlocks.c           |  152 +++++++++++++++++++++++++++++++++++++++++++++++
4  3 files changed, 187 insertions(+), 2 deletions(-)
5
6 Index: linux-2.4.24/include/linux/dynlocks.h
7 ===================================================================
8 --- linux-2.4.24.orig/include/linux/dynlocks.h  2003-01-30 13:24:37.000000000 +0300
9 +++ linux-2.4.24/include/linux/dynlocks.h       2004-07-16 10:25:15.000000000 +0400
10 @@ -0,0 +1,45 @@
11 +#ifndef _LINUX_DYNLOCKS_H
12 +#define _LINUX_DYNLOCKS_H
13 +
14 +#include <linux/list.h>
15 +#include <linux/wait.h>
16 +
17 +#define DYNLOCK_MAGIC          0xd19a10c
18 +#define DYNLOCK_MAGIC2         0xd1956ee
19 +
20 +struct dynlock;
21 +
22 +struct dynlock_member {
23 +       unsigned                dl_magic;
24 +       struct list_head        dl_list;
25 +       unsigned long           dl_value;       /* lock value */
26 +       int                     dl_refcount;    /* number of users */
27 +       int                     dl_readers;
28 +       int                     dl_writers;
29 +       int                     dl_pid;         /* holder of the lock */
30 +       wait_queue_head_t       dl_wait;
31 +       struct dynlock          *dl_head;
32 +};
33 +
34 +/*
35 + * lock's namespace:
36 + *   - list of locks
37 + *   - lock to protect this list
38 + */
39 +
40 +#define DYNLOCK_LIST_MAGIC     0x11ee91e6
41 +
42 +struct dynlock {
43 +       unsigned dl_magic;
44 +       struct list_head dl_list;
45 +       spinlock_t dl_list_lock;
46 +       struct dynlock * dl_back;
47 +};
48 +
49 +void dynlock_init(struct dynlock *dl);
50 +void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp);
51 +void dynlock_unlock(struct dynlock *dl, void *lock);
52 +
53 +
54 +#endif
55 +
56 Index: linux-2.4.24/lib/dynlocks.c
57 ===================================================================
58 --- linux-2.4.24.orig/lib/dynlocks.c    2003-01-30 13:24:37.000000000 +0300
59 +++ linux-2.4.24/lib/dynlocks.c 2004-07-16 11:53:38.000000000 +0400
60 @@ -0,0 +1,199 @@
61 +/*
62 + * Dynamic Locks
63 + *
64 + * struct dynlock is lockspace
65 + * one may request lock (exclusive or shared) for some value
66 + * in that lockspace
67 + *
68 + */
69 +
70 +#include <linux/dynlocks.h>
71 +#include <linux/module.h>
72 +#include <linux/slab.h>
73 +#include <linux/sched.h>
74 +
75 +/*
76 + * dynlock_init
77 + *
78 + * initialize lockspace
79 + *
80 + */
81 +void dynlock_init(struct dynlock *dl)
82 +{
83 +       spin_lock_init(&dl->dl_list_lock);
84 +       INIT_LIST_HEAD(&dl->dl_list);
85 +       dl->dl_magic = DYNLOCK_LIST_MAGIC;
86 +       dl->dl_back = dl;
87 +}
88 +
89 +/*
90 + * dynlock_lock
91 + *
92 + * acquires lock (exclusive or shared) in specified lockspace
93 + * each lock in lockspace is allocated separately, so user have
94 + * to specify GFP flags.
95 + * routine returns pointer to lock. this pointer is intended to
96 + * be passed to dynlock_unlock
97 + *
98 + */
99 +void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp)
100 +{
101 +       struct dynlock_member *nhl = NULL; 
102 +       struct dynlock_member *hl; 
103 +       struct list_head *cur;
104 +       int num = 0;
105 +
106 +       BUG_ON(dl == NULL);
107 +       if (dl->dl_magic != DYNLOCK_LIST_MAGIC) {
108 +               printk("corrupted dynlock head 0x%p: magic 0x%x (!=0x%x)\n",
109 +                       dl, dl->dl_magic, DYNLOCK_LIST_MAGIC);
110 +               BUG();
111 +       }
112 +       BUG_ON(dl->dl_back != dl);
113 +repeat:
114 +       /* find requested lock in lockspace */
115 +       spin_lock(&dl->dl_list_lock);
116 +       BUG_ON(dl->dl_list.next == NULL);
117 +       BUG_ON(dl->dl_list.prev == NULL);
118 +       list_for_each(cur, &dl->dl_list) {
119 +               BUG_ON(cur->next == NULL);
120 +               BUG_ON(cur->prev == NULL);
121 +               hl = list_entry(cur, struct dynlock_member, dl_list);
122 +               if (hl->dl_magic != DYNLOCK_MAGIC || hl->dl_head != dl) {
123 +                       printk("corrupted lock 0x%p/%d: magic 0x%x (!=0x%x)\n",
124 +                               hl, num, hl->dl_magic, DYNLOCK_MAGIC);
125 +                       printk("  value 0x%lx, %d readers, %d writers, pid %d, %d refs\n",
126 +                               hl->dl_value, hl->dl_readers, hl->dl_writers,
127 +                               hl->dl_pid, hl->dl_refcount);
128 +                       printk("   head 0x%p\n", hl->dl_head);
129 +                       BUG();
130 +               }
131 +               if (hl->dl_value == value) {
132 +                       /* lock is found */
133 +                       if (nhl) {
134 +                               /* someone else just allocated
135 +                                * lock we didn't find and just created
136 +                                * so, we drop our lock
137 +                                */
138 +                               kfree(nhl);
139 +                               nhl = NULL;
140 +                       }
141 +                       hl->dl_refcount++;
142 +                       goto found;
143 +               }
144 +               num++;
145 +       }
146 +       /* lock not found */
147 +       if (nhl) {
148 +               /* we already have allocated lock. use it */
149 +               hl = nhl;
150 +               nhl = NULL;
151 +               list_add(&hl->dl_list, &dl->dl_list);
152 +               goto found;
153 +       }
154 +       spin_unlock(&dl->dl_list_lock);
155 +       
156 +       /* lock not found and we haven't allocated lock yet. allocate it */
157 +       nhl = kmalloc(sizeof(struct dynlock_member), gfp);
158 +       if (nhl == NULL)
159 +               return NULL;
160 +       nhl->dl_refcount = 1;
161 +       nhl->dl_value = value;
162 +       nhl->dl_readers = 0;
163 +       nhl->dl_writers = 0;
164 +       nhl->dl_magic = DYNLOCK_MAGIC;
165 +       nhl->dl_head = dl;
166 +       init_waitqueue_head(&nhl->dl_wait);
167 +
168 +       /* while lock is being allocated, someone else may allocate it
169 +        * and put onto to list. check this situation
170 +        */
171 +       goto repeat;
172 +
173 +found:
174 +       if (rw) {
175 +               /* exclusive lock: user don't want to share lock at all
176 +                * NOTE: one process may take the same lock several times
177 +                * this functionaly is useful for rename operations */
178 +               while ((hl->dl_writers && hl->dl_pid != current->pid) ||
179 +                               hl->dl_readers) {
180 +                       spin_unlock(&dl->dl_list_lock);
181 +                       wait_event(hl->dl_wait,
182 +                               hl->dl_writers == 0 && hl->dl_readers == 0);
183 +                       spin_lock(&dl->dl_list_lock);
184 +               }
185 +               hl->dl_writers++;
186 +       } else {
187 +               /* shared lock: user do not want to share lock with writer */
188 +               while (hl->dl_writers) {
189 +                       spin_unlock(&dl->dl_list_lock);
190 +                       wait_event(hl->dl_wait, hl->dl_writers == 0);
191 +                       spin_lock(&dl->dl_list_lock);
192 +               }
193 +               hl->dl_readers++;
194 +       }
195 +       hl->dl_pid = current->pid;
196 +       spin_unlock(&dl->dl_list_lock);
197 +
198 +       BUG_ON(hl->dl_magic != DYNLOCK_MAGIC);
199 +       return hl;
200 +}
201 +
202 +
203 +/*
204 + * dynlock_unlock
205 + *
206 + * user have to specify lockspace (dl) and pointer to lock structure
207 + * returned by dynlock_lock()
208 + *
209 + */
210 +void dynlock_unlock(struct dynlock *dl, void *lock)
211 +{
212 +       struct dynlock_member *hl = lock;
213 +       int wakeup = 0;
214 +       
215 +       BUG_ON(dl == NULL);
216 +       BUG_ON(hl == NULL);
217 +       BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC);
218 +       BUG_ON(dl->dl_back != dl);
219 +       if (hl->dl_magic != DYNLOCK_MAGIC || hl->dl_head != dl) {
220 +               printk("corrupted lock 0x%p: magic 0x%x (!=0x%x)\n",
221 +                               hl, hl->dl_magic, DYNLOCK_MAGIC);
222 +               printk("  value 0x%lx, %d readers, %d writers, pid %d, %d refs\n",
223 +                               hl->dl_value, hl->dl_readers, hl->dl_writers,
224 +                               hl->dl_pid, hl->dl_refcount);
225 +               printk("   head 0x%p\n", hl->dl_head);
226 +               BUG();
227 +       }
228 +       BUG_ON(current->pid != hl->dl_pid);
229 +
230 +       spin_lock(&dl->dl_list_lock);
231 +       if (hl->dl_writers) {
232 +               BUG_ON(hl->dl_readers > 0 || hl->dl_readers < 0);
233 +               hl->dl_writers--;
234 +               if (hl->dl_writers == 0)
235 +                       wakeup = 1;
236 +       } else if (hl->dl_readers) {
237 +               hl->dl_readers--;
238 +               if (hl->dl_readers == 0)
239 +                       wakeup = 1;
240 +       } else {
241 +               BUG_ON(1);
242 +       }
243 +       if (wakeup) {
244 +               hl->dl_pid = 0;
245 +               wake_up(&hl->dl_wait);
246 +       }
247 +       if (--(hl->dl_refcount) == 0) {
248 +               hl->dl_magic = DYNLOCK_MAGIC2;
249 +               list_del(&hl->dl_list);
250 +       }
251 +       spin_unlock(&dl->dl_list_lock);
252 +       if (hl->dl_refcount == 0)
253 +               kfree(hl);
254 +}
255 +
256 +EXPORT_SYMBOL(dynlock_init);
257 +EXPORT_SYMBOL(dynlock_lock);
258 +EXPORT_SYMBOL(dynlock_unlock);
259 +
260 Index: linux-2.4.24/lib/Makefile
261 ===================================================================
262 --- linux-2.4.24.orig/lib/Makefile      2004-06-24 09:06:32.000000000 +0400
263 +++ linux-2.4.24/lib/Makefile   2004-07-14 18:14:28.000000000 +0400
264 @@ -9,10 +9,10 @@
265  L_TARGET := lib.a
266  
267  export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o \
268 -              rbtree.o crc32.o firmware_class.o
269 +              rbtree.o crc32.o firmware_class.o dynlocks.o
270  
271  obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
272 -        bust_spinlocks.o rbtree.o dump_stack.o
273 +        bust_spinlocks.o rbtree.o dump_stack.o dynlocks.o
274  
275  obj-$(CONFIG_FW_LOADER) += firmware_class.o
276  obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o