trying to fix following warning: 'override: reassigning to symbol SYSFS_DEPRECATED_V2'
[linux-2.6.git] / linux-2.6-590-dcookies-mm.patch
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
5
6 ---
7  fs/dcookies.c            |   97 +++++++++++++++++++++++++++++++++++++--------
8  include/linux/dcookies.h |   21 ++++++++++
9  2 files changed, 100 insertions(+), 18 deletions(-)
10
11 diff --git a/fs/dcookies.c b/fs/dcookies.c
12 index a21cabd..1e95c94 100644
13 --- a/fs/dcookies.c
14 +++ b/fs/dcookies.c
15 @@ -25,6 +25,7 @@
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>
21  
22  /* The dcookies are allocated from a kmem_cache and
23 @@ -38,15 +39,21 @@ struct dcookie_struct {
24  
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;
33  
34  static inline int is_live(void)
35  {
36         return !(list_empty(&dcookie_users));
37  }
38  
39 +static inline int is_shared(void)
40 +{
41 +       return !(list_empty(&dcookie_users)) && !(list_empty(dcookie_users.next));
42 +}
43  
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;
49  
50 -       list = dcookie_hashtable + dcookie_hash(dcookie);
51 +       list = dcookie_hashtable[current_hash] + dcookie_hash(dcookie);
52  
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)
56                 }
57         }
58  
59 +       if (!found) {
60 +               list = dcookie_hashtable[old_hash] + dcookie_hash(dcookie);
61 +
62 +               list_for_each(pos, list) {
63 +                       dcs = list_entry(pos, struct dcookie_struct, hash_list);
64 +                       if (dcookie_value(dcs) == dcookie) {
65 +                               found = dcs;
66 +                               break;
67 +                       }
68 +               }
69 +       }
70 +
71         return found;
72  }
73  
74  
75  static void hash_dcookie(struct dcookie_struct * dcs)
76  {
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);
80  }
81  
82  
83  static struct dcookie_struct *alloc_dcookie(struct path *path)
84  {
85 -       struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache,
86 -                                                       GFP_KERNEL);
87 +       struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache, GFP_ATOMIC);
88 +       
89         struct dentry *d;
90         if (!dcs)
91                 return NULL;
92 @@ -117,7 +136,7 @@ int get_dcookie(struct path *path, unsigned long *cookie)
93         int err = 0;
94         struct dcookie_struct * dcs;
95  
96 -       mutex_lock(&dcookie_mutex);
97 +       spin_lock(&dcookie_hash_write_lock);
98  
99         if (!is_live()) {
100                 err = -EINVAL;
101 @@ -137,7 +156,7 @@ int get_dcookie(struct path *path, unsigned long *cookie)
102         *cookie = dcookie_value(dcs);
103  
104  out:
105 -       mutex_unlock(&dcookie_mutex);
106 +       spin_unlock(&dcookie_hash_write_lock);
107         return err;
108  }
109  
110 @@ -209,7 +228,7 @@ SYSCALL_ALIAS(sys_lookup_dcookie, SyS_lookup_dcookie);
111  static int dcookie_init(void)
112  {
113         struct list_head * d;
114 -       unsigned int i, hash_bits;
115 +       unsigned int i, j, hash_bits;
116         int err = -ENOMEM;
117  
118         dcookie_cache = kmem_cache_create("dcookie_cache",
119 @@ -219,9 +238,11 @@ static int dcookie_init(void)
120         if (!dcookie_cache)
121                 goto out;
122  
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])
128                 goto out_kmem;
129 +       }
130  
131         err = 0;
132  
133 @@ -244,13 +265,15 @@ static int dcookie_init(void)
134         hash_size = 1UL << hash_bits;
135  
136         /* And initialize the newly allocated array */
137 -       d = dcookie_hashtable;
138 -       i = hash_size;
139 +       for (i=0; i<3; i++) {
140 +               d = dcookie_hashtable[i];
141 +               j = hash_size;
142         do {
143                 INIT_LIST_HEAD(d);
144                 d++;
145 -               i--;
146 -       } while (i);
147 +               j--;
148 +               } while (j);
149 +       }
150  
151  out:
152         return err;
153 @@ -272,17 +295,31 @@ static void free_dcookie(struct dcookie_struct * dcs)
154         kmem_cache_free(dcookie_cache, dcs);
155  }
156  
157 +int dcookie_swap(void) {
158 +       if (is_shared())
159 +               return -EAGAIN;
160 +       
161 +       old_hash=current_hash;
162 +       current_hash = (current_hash + 1) % 3;
163 +       return 0;
164 +}
165  
166 -static void dcookie_exit(void)
167 -{
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;
174         size_t i;
175 +       
176 +       int next_hash=(current_hash + 1) % 3;
177 +       
178 +       if (is_shared())
179 +               return -EAGAIN;
180  
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)
189                 }
190         }
191  
192 -       kfree(dcookie_hashtable);
193 +       return 0;
194 +}
195 +
196 +static void dcookie_exit(void)
197 +{
198 +       struct list_head * list;
199 +       struct list_head * pos;
200 +       struct list_head * pos2;
201 +       struct dcookie_struct * dcs;
202 +       size_t j;
203 +       unsigned int i;
204 +
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);
211 +                               free_dcookie(dcs);
212 +                       }
213 +               }
214 +               kfree(dcookie_hashtable[i]);
215 +       }
216         kmem_cache_destroy(dcookie_cache);
217  }
218  
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);
230   */
231  int get_dcookie(struct path *path, unsigned long *cookie);
232  
233 +/**
234 + * dcookie_swap - switch to the next dcookie epoch
235 + *
236 + * Deactivate the current dcookie hash table and activate
237 + * the next one
238 + *
239 + * Returns 0 on success
240 + */
241 +
242 +int dcookie_swap(void);
243 +
244 +/**
245 + * dcookie_garbage_collect - clear the hash table next in line
246 + *
247 + * Clear the hash table to be activated in the next epoch.
248 + *
249 + * Returns 0 on success
250 + */
251 +
252 +int dcookie_garbage_collect(void);
253 +
254  #else
255  
256  static inline struct dcookie_user * dcookie_register(void)
257 -- 
258 1.5.4.3
259