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