c7d1409381dc449af0a191dc7dcc93f1db10b679
[linux-2.6.git] / linux-2.6-590-GC-dcookies.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-03-16 15:18:40.000000000 -0400
33 @@ -38,14 +38,19 @@
34  static LIST_HEAD(dcookie_users);
35  static DEFINE_MUTEX(dcookie_mutex);
36  static struct kmem_cache *dcookie_cache __read_mostly;
37 -static struct list_head *dcookie_hashtable __read_mostly;
38 +static struct list_head *dcookie_hashtable[3] __read_mostly;
39  static size_t hash_size __read_mostly;
40 +unsigned int current_hash = 1, old_hash = 0;
41  
42  static inline int is_live(void)
43  {
44         return !(list_empty(&dcookie_users));
45  }
46  
47 +static inline int is_shared(void)
48 +{
49 +       return !(list_empty(&dcookie_users)) && !(list_empty(dcookie_users.next));
50 +}
51  
52  /* The dentry is locked, its address will do for the cookie */
53  static inline unsigned long dcookie_value(struct dcookie_struct * dcs)
54 @@ -67,7 +72,7 @@
55         struct list_head * pos;
56         struct list_head * list;
57  
58 -       list = dcookie_hashtable + dcookie_hash(dcookie);
59 +       list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie);
60  
61         list_for_each(pos, list) {
62                 dcs = list_entry(pos, struct dcookie_struct, hash_list);
63 @@ -77,13 +82,26 @@
64                 }
65         }
66  
67 +    if (!found) {
68 +        list = dcookie_hashtable[old_hash] + dcookie_hash(dcookie);
69 +
70 +        list_for_each(pos, list) {
71 +            dcs = list_entry(pos, struct dcookie_struct, hash_list);
72 +            if (dcookie_value(dcs) == dcookie) {
73 +                found = dcs;
74 +                break;
75 +            }
76 +        }
77 +
78 +    }
79 +
80         return found;
81  }
82  
83  
84  static void hash_dcookie(struct dcookie_struct * dcs)
85  {
86 -       struct list_head * list = dcookie_hashtable + dcookie_hash(dcookie_value(dcs));
87 +       struct list_head * list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie_value(dcs));
88         list_add(&dcs->hash_list, list);
89  }
90  
91 @@ -91,7 +109,7 @@
92  static struct dcookie_struct * alloc_dcookie(struct dentry * dentry,
93         struct vfsmount * vfsmnt)
94  {
95 -       struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_KERNEL);
96 +       struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_ATOMIC);
97         if (!dcs)
98                 return NULL;
99  
100 @@ -210,9 +228,18 @@
101         if (!dcookie_cache)
102                 goto out;
103  
104 -       dcookie_hashtable = kmalloc(PAGE_SIZE, GFP_KERNEL);
105 -       if (!dcookie_hashtable)
106 +       dcookie_hashtable[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
107 +       if (!dcookie_hashtable[0])
108 +               goto out_kmem;
109 +    
110 +    dcookie_hashtable[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
111 +       if (!dcookie_hashtable[1])
112 +               goto out_kmem;
113 +
114 +    dcookie_hashtable[2] = kmalloc(PAGE_SIZE, GFP_KERNEL);
115 +       if (!dcookie_hashtable[0])
116                 goto out_kmem;
117 +    
118  
119         err = 0;
120  
121 @@ -235,7 +262,24 @@
122         hash_size = 1UL << hash_bits;
123  
124         /* And initialize the newly allocated array */
125 -       d = dcookie_hashtable;
126 +
127 +       d = dcookie_hashtable[0];
128 +       i = hash_size;
129 +       do {
130 +               INIT_LIST_HEAD(d);
131 +               d++;
132 +               i--;
133 +       } while (i);
134 +
135 +    d = dcookie_hashtable[1];
136 +       i = hash_size;
137 +       do {
138 +               INIT_LIST_HEAD(d);
139 +               d++;
140 +               i--;
141 +       } while (i);
142 +
143 +    d = dcookie_hashtable[2];
144         i = hash_size;
145         do {
146                 INIT_LIST_HEAD(d);
147 @@ -259,6 +303,39 @@
148         kmem_cache_free(dcookie_cache, dcs);
149  }
150  
151 +int dcookie_swap(void) {
152 +    if (is_shared())
153 +        return -EAGAIN;
154 +
155 +    old_hash=current_hash;
156 +    current_hash = (current_hash + 1) % 3;
157 +    return 0;
158 +}
159 +
160 +/* Switch to the second hash */
161 +int dcookie_garbage_collect(void) {
162 +    struct list_head * list;
163 +       struct list_head * pos;
164 +       struct list_head * pos2;
165 +       struct dcookie_struct * dcs;
166 +       size_t i;
167 +    int next_hash=(current_hash + 1) % 3;
168 +
169 +    if (is_shared())
170 +        return -EAGAIN;
171 +
172 +    /* XXX consider the consequence of dcookie allocation concurring with this cleanup */
173 +       for (i = 0; i < hash_size; ++i) {
174 +               list = dcookie_hashtable[next_hash] + i;
175 +               list_for_each_safe(pos, pos2, list) {
176 +                       dcs = list_entry(pos, struct dcookie_struct, hash_list);
177 +                       list_del(&dcs->hash_list);
178 +                       free_dcookie(dcs);
179 +               }
180 +       }
181 +
182 +    return 0;
183 +}
184  
185  static void dcookie_exit(void)
186  {
187 @@ -269,7 +346,14 @@
188         size_t i;
189  
190         for (i = 0; i < hash_size; ++i) {
191 -               list = dcookie_hashtable + i;
192 +               list = dcookie_hashtable[0] + i;
193 +               list_for_each_safe(pos, pos2, list) {
194 +                       dcs = list_entry(pos, struct dcookie_struct, hash_list);
195 +                       list_del(&dcs->hash_list);
196 +                       free_dcookie(dcs);
197 +               }
198 +
199 +        list = dcookie_hashtable[1] + i;
200                 list_for_each_safe(pos, pos2, list) {
201                         dcs = list_entry(pos, struct dcookie_struct, hash_list);
202                         list_del(&dcs->hash_list);
203 @@ -277,7 +361,8 @@
204                 }
205         }
206  
207 -       kfree(dcookie_hashtable);
208 +       kfree(dcookie_hashtable[0]);
209 +       kfree(dcookie_hashtable[1]);
210         kmem_cache_destroy(dcookie_cache);
211  }
212  
213 @@ -327,3 +412,5 @@
214  EXPORT_SYMBOL_GPL(dcookie_register);
215  EXPORT_SYMBOL_GPL(dcookie_unregister);
216  EXPORT_SYMBOL_GPL(get_dcookie);
217 +EXPORT_SYMBOL_GPL(dcookie_garbage_collect);