---- linux-2.6.22.19-chopstix/fs/dcookies.c 2009-02-28 03:10:05.000000000 -0500
-+++ linux-2.6.22.19-chopstix/fs/dcookies.c.orig 2008-02-25 18:59:40.000000000 -0500
-@@ -38,19 +38,14 @@
+diff -Nurb linux-2.6.22.19/fs/dcookies.c linux-2.6.22.19-dcookies/fs/dcookies.c
+--- linux-2.6.22.19/fs/dcookies.c 2008-02-25 18:59:40.000000000 -0500
++++ linux-2.6.22.19-dcookies/fs/dcookies.c 2009-03-16 14:44:24.000000000 -0400
+@@ -38,14 +38,19 @@
static LIST_HEAD(dcookie_users);
static DEFINE_MUTEX(dcookie_mutex);
static struct kmem_cache *dcookie_cache __read_mostly;
--static struct list_head *dcookie_hashtable[2] __read_mostly;
-+static struct list_head *dcookie_hashtable __read_mostly;
+-static struct list_head *dcookie_hashtable __read_mostly;
++static struct list_head *dcookie_hashtable[3] __read_mostly;
static size_t hash_size __read_mostly;
--unsigned int current_hash = 0;
++unsigned int current_hash = 0, old_hash = -1;
static inline int is_live(void)
{
return !(list_empty(&dcookie_users));
}
--static inline int is_shared(void)
--{
-- return !(list_empty(&dcookie_users)) && !(list_empty(dcookie_users.next));
--}
++static inline int is_shared(void)
++{
++ return !(list_empty(&dcookie_users)) && !(list_empty(dcookie_users.next));
++}
/* The dentry is locked, its address will do for the cookie */
static inline unsigned long dcookie_value(struct dcookie_struct * dcs)
-@@ -72,7 +67,7 @@
+@@ -67,7 +72,7 @@
struct list_head * pos;
struct list_head * list;
-- list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie);
-+ list = dcookie_hashtable + dcookie_hash(dcookie);
+- list = dcookie_hashtable + dcookie_hash(dcookie);
++ list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie);
list_for_each(pos, list) {
dcs = list_entry(pos, struct dcookie_struct, hash_list);
-@@ -88,7 +83,7 @@
+@@ -77,13 +82,26 @@
+ }
+ }
+
++ if (!found && (old_hash!=-1)) {
++ list = dcookie_hashtable[old_hash] + dcookie_hash(dcookie);
++
++ list_for_each(pos, list) {
++ dcs = list_entry(pos, struct dcookie_struct, hash_list);
++ if (dcookie_value(dcs) == dcookie) {
++ found = dcs;
++ break;
++ }
++ }
++
++ }
++
+ return found;
+ }
+
static void hash_dcookie(struct dcookie_struct * dcs)
{
-- struct list_head * list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie_value(dcs));
-+ struct list_head * list = dcookie_hashtable + dcookie_hash(dcookie_value(dcs));
+- struct list_head * list = dcookie_hashtable + dcookie_hash(dcookie_value(dcs));
++ struct list_head * list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie_value(dcs));
list_add(&dcs->hash_list, list);
}
-@@ -96,7 +91,7 @@
+@@ -91,7 +109,7 @@
static struct dcookie_struct * alloc_dcookie(struct dentry * dentry,
struct vfsmount * vfsmnt)
{
-- struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_ATOMIC);
-+ struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_KERNEL);
+- struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_KERNEL);
++ struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_ATOMIC);
if (!dcs)
return NULL;
-@@ -215,12 +210,8 @@
+@@ -210,10 +228,19 @@
if (!dcookie_cache)
goto out;
-- dcookie_hashtable[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
-- if (!dcookie_hashtable[0])
-- goto out_kmem;
--
-- dcookie_hashtable[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
-- if (!dcookie_hashtable[1])
-+ dcookie_hashtable = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+ if (!dcookie_hashtable)
+- dcookie_hashtable = kmalloc(PAGE_SIZE, GFP_KERNEL);
+- if (!dcookie_hashtable)
++ dcookie_hashtable[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ if (!dcookie_hashtable[0])
++ goto out_kmem;
++
++ dcookie_hashtable[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ if (!dcookie_hashtable[1])
goto out_kmem;
++ dcookie_hashtable[2] = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ if (!dcookie_hashtable[0])
++ goto out_kmem;
++
++
err = 0;
-@@ -244,15 +235,7 @@
+
+ /*
+@@ -235,7 +262,24 @@
hash_size = 1UL << hash_bits;
/* And initialize the newly allocated array */
-- d = dcookie_hashtable[0];
-- i = hash_size;
-- do {
-- INIT_LIST_HEAD(d);
-- d++;
-- i--;
-- } while (i);
--
-- d = dcookie_hashtable[1];
-+ d = dcookie_hashtable;
+- d = dcookie_hashtable;
++
++ d = dcookie_hashtable[0];
++ i = hash_size;
++ do {
++ INIT_LIST_HEAD(d);
++ d++;
++ i--;
++ } while (i);
++
++ d = dcookie_hashtable[1];
++ i = hash_size;
++ do {
++ INIT_LIST_HEAD(d);
++ d++;
++ i--;
++ } while (i);
++
++ d = dcookie_hashtable[2];
i = hash_size;
do {
INIT_LIST_HEAD(d);
-@@ -276,30 +259,6 @@
+@@ -259,6 +303,39 @@
kmem_cache_free(dcookie_cache, dcs);
}
--/* Switch to the second hash */
--int garbage_collect(void) {
-- struct list_head * list;
-- struct list_head * pos;
-- struct list_head * pos2;
-- struct dcookie_struct * dcs;
-- size_t i;
--
-- if (is_shared())
-- return -EAGAIN;
--
-- for (i = 0; i < hash_size; ++i) {
-- list = dcookie_hashtable[current_hash] + i;
-- list_for_each_safe(pos, pos2, list) {
-- dcs = list_entry(pos, struct dcookie_struct, hash_list);
-- list_del(&dcs->hash_list);
-- free_dcookie(dcs);
-- }
-- }
--
-- current_hash = (current_hash & 1) ^ 1;
--
-- return 0;
--}
++int dcookie_swap(void) {
++ if (is_shared())
++ return -EAGAIN;
++
++ old_hash=current_hash;
++ current_hash = (current_hash + 1) % 3;
++ return 0;
++}
++
++/* Switch to the second hash */
++int dcookie_garbage_collect(void) {
++ struct list_head * list;
++ struct list_head * pos;
++ struct list_head * pos2;
++ struct dcookie_struct * dcs;
++ size_t i;
++ int next_hash=(current_hash + 1) % 3;
++
++ if (is_shared())
++ return -EAGAIN;
++
++ /* XXX consider the consequence of dcookie allocation concurring with this cleanup */
++ for (i = 0; i < hash_size; ++i) {
++ list = dcookie_hashtable[next_hash] + i;
++ list_for_each_safe(pos, pos2, list) {
++ dcs = list_entry(pos, struct dcookie_struct, hash_list);
++ list_del(&dcs->hash_list);
++ free_dcookie(dcs);
++ }
++ }
++
++ return 0;
++}
static void dcookie_exit(void)
{
-@@ -310,14 +269,7 @@
+@@ -269,7 +346,14 @@
size_t i;
for (i = 0; i < hash_size; ++i) {
-- list = dcookie_hashtable[0] + i;
-- list_for_each_safe(pos, pos2, list) {
-- dcs = list_entry(pos, struct dcookie_struct, hash_list);
-- list_del(&dcs->hash_list);
-- free_dcookie(dcs);
-- }
--
-- list = dcookie_hashtable[1] + i;
-+ list = dcookie_hashtable + i;
+- list = dcookie_hashtable + i;
++ list = dcookie_hashtable[0] + i;
++ list_for_each_safe(pos, pos2, list) {
++ dcs = list_entry(pos, struct dcookie_struct, hash_list);
++ list_del(&dcs->hash_list);
++ free_dcookie(dcs);
++ }
++
++ list = dcookie_hashtable[1] + i;
list_for_each_safe(pos, pos2, list) {
dcs = list_entry(pos, struct dcookie_struct, hash_list);
list_del(&dcs->hash_list);
-@@ -325,8 +277,7 @@
+@@ -277,7 +361,8 @@
}
}
-- kfree(dcookie_hashtable[0]);
-- kfree(dcookie_hashtable[1]);
-+ kfree(dcookie_hashtable);
+- kfree(dcookie_hashtable);
++ kfree(dcookie_hashtable[0]);
++ kfree(dcookie_hashtable[1]);
kmem_cache_destroy(dcookie_cache);
}
+@@ -327,3 +412,5 @@
+ EXPORT_SYMBOL_GPL(dcookie_register);
+ EXPORT_SYMBOL_GPL(dcookie_unregister);
+ EXPORT_SYMBOL_GPL(get_dcookie);
++EXPORT_SYMBOL_GPL(dcookie_garbage_collect);
++EXPORT_SYMBOL_GPL(dcookie_swap);