1 From d8e2bd85a3188b65ae8a3a82cc6dade218f69aa0 Mon Sep 17 00:00:00 2001
2 From: S.Çağlar Onur <caglar@cs.princeton.edu>
3 Date: Tue, 7 Dec 2010 11:09:20 -0500
4 Subject: [PATCH] linux-2.6-590-dcookies-mm.patch
7 fs/dcookies.c | 97 +++++++++++++++++++++++++++++++++++++--------
8 include/linux/dcookies.h | 21 ++++++++++
9 2 files changed, 100 insertions(+), 18 deletions(-)
11 diff --git a/fs/dcookies.c b/fs/dcookies.c
12 index a21cabd..1e95c94 100644
16 #include <linux/dcookies.h>
17 #include <linux/mutex.h>
18 #include <linux/path.h>
19 +#include <linux/spinlock.h>
20 #include <asm/uaccess.h>
22 /* The dcookies are allocated from a kmem_cache and
23 @@ -38,15 +39,21 @@ struct dcookie_struct {
25 static LIST_HEAD(dcookie_users);
26 static DEFINE_MUTEX(dcookie_mutex);
27 +spinlock_t dcookie_hash_write_lock = SPIN_LOCK_UNLOCKED;
28 static struct kmem_cache *dcookie_cache __read_mostly;
29 -static struct list_head *dcookie_hashtable __read_mostly;
30 +static struct list_head *dcookie_hashtable[3] __read_mostly;
31 static size_t hash_size __read_mostly;
32 +unsigned int current_hash = 1, old_hash = 0;
34 static inline int is_live(void)
36 return !(list_empty(&dcookie_users));
39 +static inline int is_shared(void)
41 + return !(list_empty(&dcookie_users)) && !(list_empty(dcookie_users.next));
44 /* The dentry is locked, its address will do for the cookie */
45 static inline unsigned long dcookie_value(struct dcookie_struct * dcs)
46 @@ -68,7 +75,7 @@ static struct dcookie_struct * find_dcookie(unsigned long dcookie)
47 struct list_head * pos;
48 struct list_head * list;
50 - list = dcookie_hashtable + dcookie_hash(dcookie);
51 + list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie);
53 list_for_each(pos, list) {
54 dcs = list_entry(pos, struct dcookie_struct, hash_list);
55 @@ -78,21 +85,33 @@ static struct dcookie_struct * find_dcookie(unsigned long dcookie)
60 + list = dcookie_hashtable[old_hash] + dcookie_hash(dcookie);
62 + list_for_each(pos, list) {
63 + dcs = list_entry(pos, struct dcookie_struct, hash_list);
64 + if (dcookie_value(dcs) == dcookie) {
75 static void hash_dcookie(struct dcookie_struct * dcs)
77 - struct list_head * list = dcookie_hashtable + dcookie_hash(dcookie_value(dcs));
78 + struct list_head * list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie_value(dcs));
79 list_add(&dcs->hash_list, list);
83 static struct dcookie_struct *alloc_dcookie(struct path *path)
85 - struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache,
87 + struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache, GFP_ATOMIC);
92 @@ -117,7 +136,7 @@ int get_dcookie(struct path *path, unsigned long *cookie)
94 struct dcookie_struct * dcs;
96 - mutex_lock(&dcookie_mutex);
97 + spin_lock(&dcookie_hash_write_lock);
101 @@ -137,7 +156,7 @@ int get_dcookie(struct path *path, unsigned long *cookie)
102 *cookie = dcookie_value(dcs);
105 - mutex_unlock(&dcookie_mutex);
106 + spin_unlock(&dcookie_hash_write_lock);
110 @@ -209,7 +228,7 @@ SYSCALL_ALIAS(sys_lookup_dcookie, SyS_lookup_dcookie);
111 static int dcookie_init(void)
113 struct list_head * d;
114 - unsigned int i, hash_bits;
115 + unsigned int i, j, hash_bits;
118 dcookie_cache = kmem_cache_create("dcookie_cache",
119 @@ -219,9 +238,11 @@ static int dcookie_init(void)
123 - dcookie_hashtable = kmalloc(PAGE_SIZE, GFP_KERNEL);
124 - if (!dcookie_hashtable)
125 + for (i=0; i<3; i++) {
126 + dcookie_hashtable[i] = kmalloc(PAGE_SIZE, GFP_KERNEL);
127 + if (!dcookie_hashtable[i])
133 @@ -244,13 +265,15 @@ static int dcookie_init(void)
134 hash_size = 1UL << hash_bits;
136 /* And initialize the newly allocated array */
137 - d = dcookie_hashtable;
139 + for (i=0; i<3; i++) {
140 + d = dcookie_hashtable[i];
153 @@ -272,17 +295,31 @@ static void free_dcookie(struct dcookie_struct * dcs)
154 kmem_cache_free(dcookie_cache, dcs);
157 +int dcookie_swap(void) {
161 + old_hash=current_hash;
162 + current_hash = (current_hash + 1) % 3;
166 -static void dcookie_exit(void)
168 +/* Switch to the second hash */
169 +int dcookie_garbage_collect(void) {
170 struct list_head * list;
171 struct list_head * pos;
172 struct list_head * pos2;
173 struct dcookie_struct * dcs;
176 + int next_hash=(current_hash + 1) % 3;
181 + /* XXX consider the consequence of dcookie allocation concurring with this cleanup */
182 for (i = 0; i < hash_size; ++i) {
183 - list = dcookie_hashtable + i;
184 + list = dcookie_hashtable[next_hash] + i;
185 list_for_each_safe(pos, pos2, list) {
186 dcs = list_entry(pos, struct dcookie_struct, hash_list);
187 list_del(&dcs->hash_list);
188 @@ -290,7 +327,29 @@ static void dcookie_exit(void)
192 - kfree(dcookie_hashtable);
196 +static void dcookie_exit(void)
198 + struct list_head * list;
199 + struct list_head * pos;
200 + struct list_head * pos2;
201 + struct dcookie_struct * dcs;
205 + for (i = 0; i < 3; ++i) {
206 + for (j = 0; j < hash_size; ++j) {
207 + list = dcookie_hashtable[i] + j;
208 + list_for_each_safe(pos, pos2, list) {
209 + dcs = list_entry(pos, struct dcookie_struct, hash_list);
210 + list_del(&dcs->hash_list);
214 + kfree(dcookie_hashtable[i]);
216 kmem_cache_destroy(dcookie_cache);
219 @@ -340,3 +399,5 @@ void dcookie_unregister(struct dcookie_user * user)
220 EXPORT_SYMBOL_GPL(dcookie_register);
221 EXPORT_SYMBOL_GPL(dcookie_unregister);
222 EXPORT_SYMBOL_GPL(get_dcookie);
223 +EXPORT_SYMBOL_GPL(dcookie_garbage_collect);
224 +EXPORT_SYMBOL_GPL(dcookie_swap);
225 diff --git a/include/linux/dcookies.h b/include/linux/dcookies.h
226 index 24c806f..3c1d2b2 100644
227 --- a/include/linux/dcookies.h
228 +++ b/include/linux/dcookies.h
229 @@ -46,6 +46,27 @@ void dcookie_unregister(struct dcookie_user * user);
231 int get_dcookie(struct path *path, unsigned long *cookie);
234 + * dcookie_swap - switch to the next dcookie epoch
236 + * Deactivate the current dcookie hash table and activate
239 + * Returns 0 on success
242 +int dcookie_swap(void);
245 + * dcookie_garbage_collect - clear the hash table next in line
247 + * Clear the hash table to be activated in the next epoch.
249 + * Returns 0 on success
252 +int dcookie_garbage_collect(void);
256 static inline struct dcookie_user * dcookie_register(void)