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