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