Setting tag linux-2.6-22-50
[linux-2.6.git] / linux-2.6-592-GC-dcookies-nosleep.patch
1 --- linux-chopstix/include/linux/dcookies.h.orig        2009-03-05 08:45:29.000000000 -0500
2 +++ linux-chopstix/include/linux/dcookies.h     2009-03-12 13:43:53.000000000 -0400
3 @@ -45,6 +45,27 @@
4  int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt,
5         unsigned long * cookie);
6  
7 +
8 +/**
9 + * dcookie_swap - switch to the next dcookie epoch
10 + *
11 + * Deactivate the current dcookie hash table and activate
12 + * the next one
13 + *
14 + * Returns 0 on success
15 + */
16 +
17 +int dcookie_swap(void);
18 +
19 +/**
20 + * dcookie_garbage_collect - clear the hash table next in line
21 + *
22 + * Clear the hash table to be activated in the next epoch.
23 + *
24 + * Returns 0 on success
25 + */
26 +
27 +int dcookie_garbage_colect(void);
28  #else
29  
30  static inline struct dcookie_user * dcookie_register(void)
31 --- linux-chopstix/fs/dcookies.c.orig   2009-03-05 08:46:09.000000000 -0500
32 +++ linux-chopstix/fs/dcookies.c        2009-04-06 11:37:35.000000000 -0400
33 @@ -23,6 +23,7 @@
34  #include <linux/errno.h>
35  #include <linux/dcookies.h>
36  #include <linux/mutex.h>
37 +#include <linux/spinlock.h>
38  #include <asm/uaccess.h>
39  
40  /* The dcookies are allocated from a kmem_cache and
41 @@ -37,15 +38,21 @@
42  
43  static LIST_HEAD(dcookie_users);
44  static DEFINE_MUTEX(dcookie_mutex);
45 +spinlock_t dcookie_hash_write_lock = SPIN_LOCK_UNLOCKED;
46  static struct kmem_cache *dcookie_cache __read_mostly;
47 -static struct list_head *dcookie_hashtable __read_mostly;
48 +static struct list_head *dcookie_hashtable[3] __read_mostly;
49  static size_t hash_size __read_mostly;
50 +unsigned int current_hash = 1, old_hash = 0;
51  
52  static inline int is_live(void)
53  {
54         return !(list_empty(&dcookie_users));
55  }
56  
57 +static inline int is_shared(void)
58 +{
59 +       return !(list_empty(&dcookie_users)) && !(list_empty(dcookie_users.next));
60 +}
61  
62  /* The dentry is locked, its address will do for the cookie */
63  static inline unsigned long dcookie_value(struct dcookie_struct * dcs)
64 @@ -67,7 +74,7 @@
65         struct list_head * pos;
66         struct list_head * list;
67  
68 -       list = dcookie_hashtable + dcookie_hash(dcookie);
69 +       list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie);
70  
71         list_for_each(pos, list) {
72                 dcs = list_entry(pos, struct dcookie_struct, hash_list);
73 @@ -77,13 +84,26 @@
74                 }
75         }
76  
77 +    if (!found) {
78 +        list = dcookie_hashtable[old_hash] + dcookie_hash(dcookie);
79 +
80 +        list_for_each(pos, list) {
81 +            dcs = list_entry(pos, struct dcookie_struct, hash_list);
82 +            if (dcookie_value(dcs) == dcookie) {
83 +                found = dcs;
84 +                break;
85 +            }
86 +        }
87 +
88 +    }
89 +
90         return found;
91  }
92  
93  
94  static void hash_dcookie(struct dcookie_struct * dcs)
95  {
96 -       struct list_head * list = dcookie_hashtable + dcookie_hash(dcookie_value(dcs));
97 +       struct list_head * list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie_value(dcs));
98         list_add(&dcs->hash_list, list);
99  }
100  
101 @@ -91,7 +111,7 @@
102  static struct dcookie_struct * alloc_dcookie(struct dentry * dentry,
103         struct vfsmount * vfsmnt)
104  {
105 -       struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_KERNEL);
106 +       struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_ATOMIC);
107         if (!dcs)
108                 return NULL;
109  
110 @@ -114,7 +134,7 @@
111         int err = 0;
112         struct dcookie_struct * dcs;
113  
114 -       mutex_lock(&dcookie_mutex);
115 +       spin_lock(&dcookie_hash_write_lock);
116  
117         if (!is_live()) {
118                 err = -EINVAL;
119 @@ -134,7 +154,7 @@
120         *cookie = dcookie_value(dcs);
121  
122  out:
123 -       mutex_unlock(&dcookie_mutex);
124 +       spin_unlock(&dcookie_hash_write_lock);
125         return err;
126  }
127  
128 @@ -210,9 +230,18 @@
129         if (!dcookie_cache)
130                 goto out;
131  
132 -       dcookie_hashtable = kmalloc(PAGE_SIZE, GFP_KERNEL);
133 -       if (!dcookie_hashtable)
134 +       dcookie_hashtable[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
135 +       if (!dcookie_hashtable[0])
136                 goto out_kmem;
137 +    
138 +    dcookie_hashtable[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
139 +       if (!dcookie_hashtable[1])
140 +               goto out_kmem;
141 +
142 +    dcookie_hashtable[2] = kmalloc(PAGE_SIZE, GFP_KERNEL);
143 +       if (!dcookie_hashtable[2])
144 +               goto out_kmem;
145 +    
146  
147         err = 0;
148  
149 @@ -235,7 +264,24 @@
150         hash_size = 1UL << hash_bits;
151  
152         /* And initialize the newly allocated array */
153 -       d = dcookie_hashtable;
154 +
155 +       d = dcookie_hashtable[0];
156 +       i = hash_size;
157 +       do {
158 +               INIT_LIST_HEAD(d);
159 +               d++;
160 +               i--;
161 +       } while (i);
162 +
163 +    d = dcookie_hashtable[1];
164 +       i = hash_size;
165 +       do {
166 +               INIT_LIST_HEAD(d);
167 +               d++;
168 +               i--;
169 +       } while (i);
170 +
171 +    d = dcookie_hashtable[2];
172         i = hash_size;
173         do {
174                 INIT_LIST_HEAD(d);
175 @@ -259,6 +305,39 @@
176         kmem_cache_free(dcookie_cache, dcs);
177  }
178  
179 +int dcookie_swap(void) {
180 +    if (is_shared())
181 +        return -EAGAIN;
182 +
183 +    old_hash=current_hash;
184 +    current_hash = (current_hash + 1) % 3;
185 +    return 0;
186 +}
187 +
188 +/* Switch to the second hash */
189 +int dcookie_garbage_collect(void) {
190 +    struct list_head * list;
191 +       struct list_head * pos;
192 +       struct list_head * pos2;
193 +       struct dcookie_struct * dcs;
194 +       size_t i;
195 +    int next_hash=(current_hash + 1) % 3;
196 +
197 +    if (is_shared())
198 +        return -EAGAIN;
199 +
200 +    /* XXX consider the consequence of dcookie allocation concurring with this cleanup */
201 +       for (i = 0; i < hash_size; ++i) {
202 +               list = dcookie_hashtable[next_hash] + i;
203 +               list_for_each_safe(pos, pos2, list) {
204 +                       dcs = list_entry(pos, struct dcookie_struct, hash_list);
205 +                       list_del(&dcs->hash_list);
206 +                       free_dcookie(dcs);
207 +               }
208 +       }
209 +
210 +    return 0;
211 +}
212  
213  static void dcookie_exit(void)
214  {
215 @@ -269,7 +348,21 @@
216         size_t i;
217  
218         for (i = 0; i < hash_size; ++i) {
219 -               list = dcookie_hashtable + i;
220 +               list = dcookie_hashtable[0] + i;
221 +               list_for_each_safe(pos, pos2, list) {
222 +                       dcs = list_entry(pos, struct dcookie_struct, hash_list);
223 +                       list_del(&dcs->hash_list);
224 +                       free_dcookie(dcs);
225 +               }
226 +
227 +        list = dcookie_hashtable[1] + i;
228 +               list_for_each_safe(pos, pos2, list) {
229 +                       dcs = list_entry(pos, struct dcookie_struct, hash_list);
230 +                       list_del(&dcs->hash_list);
231 +                       free_dcookie(dcs);
232 +               }
233 +
234 +        list = dcookie_hashtable[2] + i;
235                 list_for_each_safe(pos, pos2, list) {
236                         dcs = list_entry(pos, struct dcookie_struct, hash_list);
237                         list_del(&dcs->hash_list);
238 @@ -277,7 +370,9 @@
239                 }
240         }
241  
242 -       kfree(dcookie_hashtable);
243 +       kfree(dcookie_hashtable[0]);
244 +       kfree(dcookie_hashtable[1]);
245 +       kfree(dcookie_hashtable[2]);
246         kmem_cache_destroy(dcookie_cache);
247  }
248  
249 @@ -327,3 +422,5 @@
250  EXPORT_SYMBOL_GPL(dcookie_register);
251  EXPORT_SYMBOL_GPL(dcookie_unregister);
252  EXPORT_SYMBOL_GPL(get_dcookie);
253 +EXPORT_SYMBOL_GPL(dcookie_garbage_collect);
254 +EXPORT_SYMBOL_GPL(dcookie_swap);