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
4 int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt,
5 unsigned long * cookie);
9 + * dcookie_swap - switch to the next dcookie epoch
11 + * Deactivate the current dcookie hash table and activate
14 + * Returns 0 on success
17 +int dcookie_swap(void);
20 + * dcookie_garbage_collect - clear the hash table next in line
22 + * Clear the hash table to be activated in the next epoch.
24 + * Returns 0 on success
27 +int dcookie_garbage_colect(void);
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
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>
40 /* The dcookies are allocated from a kmem_cache and
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;
52 static inline int is_live(void)
54 return !(list_empty(&dcookie_users));
57 +static inline int is_shared(void)
59 + return !(list_empty(&dcookie_users)) && !(list_empty(dcookie_users.next));
62 /* The dentry is locked, its address will do for the cookie */
63 static inline unsigned long dcookie_value(struct dcookie_struct * dcs)
65 struct list_head * pos;
66 struct list_head * list;
68 - list = dcookie_hashtable + dcookie_hash(dcookie);
69 + list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie);
71 list_for_each(pos, list) {
72 dcs = list_entry(pos, struct dcookie_struct, hash_list);
78 + list = dcookie_hashtable[old_hash] + dcookie_hash(dcookie);
80 + list_for_each(pos, list) {
81 + dcs = list_entry(pos, struct dcookie_struct, hash_list);
82 + if (dcookie_value(dcs) == dcookie) {
94 static void hash_dcookie(struct dcookie_struct * dcs)
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);
102 static struct dcookie_struct * alloc_dcookie(struct dentry * dentry,
103 struct vfsmount * vfsmnt)
105 - struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_KERNEL);
106 + struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_ATOMIC);
112 struct dcookie_struct * dcs;
114 - mutex_lock(&dcookie_mutex);
115 + spin_lock(&dcookie_hash_write_lock);
120 *cookie = dcookie_value(dcs);
123 - mutex_unlock(&dcookie_mutex);
124 + spin_unlock(&dcookie_hash_write_lock);
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])
138 + dcookie_hashtable[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
139 + if (!dcookie_hashtable[1])
142 + dcookie_hashtable[2] = kmalloc(PAGE_SIZE, GFP_KERNEL);
143 + if (!dcookie_hashtable[2])
150 hash_size = 1UL << hash_bits;
152 /* And initialize the newly allocated array */
153 - d = dcookie_hashtable;
155 + d = dcookie_hashtable[0];
163 + d = dcookie_hashtable[1];
171 + d = dcookie_hashtable[2];
176 kmem_cache_free(dcookie_cache, dcs);
179 +int dcookie_swap(void) {
183 + old_hash=current_hash;
184 + current_hash = (current_hash + 1) % 3;
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;
195 + int next_hash=(current_hash + 1) % 3;
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);
213 static void dcookie_exit(void)
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);
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);
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);
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);
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);