diff options
author | David Howells <dhowells@redhat.com> | 2007-04-26 18:55:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-04-26 18:55:03 -0400 |
commit | 08e0e7c82eeadec6f4871a386b86bf0f0fbcb4eb (patch) | |
tree | 1c4f7e91e20e56ff2ec755e988a6ee828b1a21c0 /fs/afs/cell.c | |
parent | 651350d10f93bed7003c9a66e24cf25e0f8eed3d (diff) |
[AF_RXRPC]: Make the in-kernel AFS filesystem use AF_RXRPC.
Make the in-kernel AFS filesystem use AF_RXRPC instead of the old RxRPC code.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs/afs/cell.c')
-rw-r--r-- | fs/afs/cell.c | 344 |
1 files changed, 70 insertions, 274 deletions
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 28ed84ec8ff7..733c60246ab0 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -11,15 +11,6 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <rxrpc/peer.h> | ||
15 | #include <rxrpc/connection.h> | ||
16 | #include "volume.h" | ||
17 | #include "cell.h" | ||
18 | #include "server.h" | ||
19 | #include "transport.h" | ||
20 | #include "vlclient.h" | ||
21 | #include "kafstimod.h" | ||
22 | #include "super.h" | ||
23 | #include "internal.h" | 14 | #include "internal.h" |
24 | 15 | ||
25 | DECLARE_RWSEM(afs_proc_cells_sem); | 16 | DECLARE_RWSEM(afs_proc_cells_sem); |
@@ -28,34 +19,21 @@ LIST_HEAD(afs_proc_cells); | |||
28 | static struct list_head afs_cells = LIST_HEAD_INIT(afs_cells); | 19 | static struct list_head afs_cells = LIST_HEAD_INIT(afs_cells); |
29 | static DEFINE_RWLOCK(afs_cells_lock); | 20 | static DEFINE_RWLOCK(afs_cells_lock); |
30 | static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */ | 21 | static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */ |
22 | static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq); | ||
31 | static struct afs_cell *afs_cell_root; | 23 | static struct afs_cell *afs_cell_root; |
32 | 24 | ||
33 | #ifdef AFS_CACHING_SUPPORT | ||
34 | static cachefs_match_val_t afs_cell_cache_match(void *target, | ||
35 | const void *entry); | ||
36 | static void afs_cell_cache_update(void *source, void *entry); | ||
37 | |||
38 | struct cachefs_index_def afs_cache_cell_index_def = { | ||
39 | .name = "cell_ix", | ||
40 | .data_size = sizeof(struct afs_cache_cell), | ||
41 | .keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 }, | ||
42 | .match = afs_cell_cache_match, | ||
43 | .update = afs_cell_cache_update, | ||
44 | }; | ||
45 | #endif | ||
46 | |||
47 | /* | 25 | /* |
48 | * create a cell record | 26 | * create a cell record |
49 | * - "name" is the name of the cell | 27 | * - "name" is the name of the cell |
50 | * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format | 28 | * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format |
51 | */ | 29 | */ |
52 | int afs_cell_create(const char *name, char *vllist, struct afs_cell **_cell) | 30 | struct afs_cell *afs_cell_create(const char *name, char *vllist) |
53 | { | 31 | { |
54 | struct afs_cell *cell; | 32 | struct afs_cell *cell; |
55 | char *next; | 33 | char *next; |
56 | int ret; | 34 | int ret; |
57 | 35 | ||
58 | _enter("%s", name); | 36 | _enter("%s,%s", name, vllist); |
59 | 37 | ||
60 | BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ | 38 | BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ |
61 | 39 | ||
@@ -63,27 +41,24 @@ int afs_cell_create(const char *name, char *vllist, struct afs_cell **_cell) | |||
63 | cell = kmalloc(sizeof(struct afs_cell) + strlen(name) + 1, GFP_KERNEL); | 41 | cell = kmalloc(sizeof(struct afs_cell) + strlen(name) + 1, GFP_KERNEL); |
64 | if (!cell) { | 42 | if (!cell) { |
65 | _leave(" = -ENOMEM"); | 43 | _leave(" = -ENOMEM"); |
66 | return -ENOMEM; | 44 | return ERR_PTR(-ENOMEM); |
67 | } | 45 | } |
68 | 46 | ||
69 | down_write(&afs_cells_sem); | 47 | down_write(&afs_cells_sem); |
70 | 48 | ||
71 | memset(cell, 0, sizeof(struct afs_cell)); | 49 | memset(cell, 0, sizeof(struct afs_cell)); |
72 | atomic_set(&cell->usage, 0); | 50 | atomic_set(&cell->usage, 1); |
73 | 51 | ||
74 | INIT_LIST_HEAD(&cell->link); | 52 | INIT_LIST_HEAD(&cell->link); |
75 | 53 | ||
76 | rwlock_init(&cell->sv_lock); | 54 | rwlock_init(&cell->servers_lock); |
77 | INIT_LIST_HEAD(&cell->sv_list); | 55 | INIT_LIST_HEAD(&cell->servers); |
78 | INIT_LIST_HEAD(&cell->sv_graveyard); | ||
79 | spin_lock_init(&cell->sv_gylock); | ||
80 | 56 | ||
81 | init_rwsem(&cell->vl_sem); | 57 | init_rwsem(&cell->vl_sem); |
82 | INIT_LIST_HEAD(&cell->vl_list); | 58 | INIT_LIST_HEAD(&cell->vl_list); |
83 | INIT_LIST_HEAD(&cell->vl_graveyard); | 59 | spin_lock_init(&cell->vl_lock); |
84 | spin_lock_init(&cell->vl_gylock); | ||
85 | 60 | ||
86 | strcpy(cell->name,name); | 61 | strcpy(cell->name, name); |
87 | 62 | ||
88 | /* fill in the VL server list from the rest of the string */ | 63 | /* fill in the VL server list from the rest of the string */ |
89 | ret = -EINVAL; | 64 | ret = -EINVAL; |
@@ -106,9 +81,9 @@ int afs_cell_create(const char *name, char *vllist, struct afs_cell **_cell) | |||
106 | if (cell->vl_naddrs >= AFS_CELL_MAX_ADDRS) | 81 | if (cell->vl_naddrs >= AFS_CELL_MAX_ADDRS) |
107 | break; | 82 | break; |
108 | 83 | ||
109 | } while(vllist = next, vllist); | 84 | } while ((vllist = next)); |
110 | 85 | ||
111 | /* add a proc dir for this cell */ | 86 | /* add a proc directory for this cell */ |
112 | ret = afs_proc_cell_setup(cell); | 87 | ret = afs_proc_cell_setup(cell); |
113 | if (ret < 0) | 88 | if (ret < 0) |
114 | goto error; | 89 | goto error; |
@@ -129,30 +104,29 @@ int afs_cell_create(const char *name, char *vllist, struct afs_cell **_cell) | |||
129 | down_write(&afs_proc_cells_sem); | 104 | down_write(&afs_proc_cells_sem); |
130 | list_add_tail(&cell->proc_link, &afs_proc_cells); | 105 | list_add_tail(&cell->proc_link, &afs_proc_cells); |
131 | up_write(&afs_proc_cells_sem); | 106 | up_write(&afs_proc_cells_sem); |
132 | |||
133 | *_cell = cell; | ||
134 | up_write(&afs_cells_sem); | 107 | up_write(&afs_cells_sem); |
135 | 108 | ||
136 | _leave(" = 0 (%p)", cell); | 109 | _leave(" = %p", cell); |
137 | return 0; | 110 | return cell; |
138 | 111 | ||
139 | badaddr: | 112 | badaddr: |
140 | printk(KERN_ERR "kAFS: bad VL server IP address: '%s'\n", vllist); | 113 | printk(KERN_ERR "kAFS: bad VL server IP address\n"); |
141 | error: | 114 | error: |
142 | up_write(&afs_cells_sem); | 115 | up_write(&afs_cells_sem); |
143 | kfree(cell); | 116 | kfree(cell); |
144 | _leave(" = %d", ret); | 117 | _leave(" = %d", ret); |
145 | return ret; | 118 | return ERR_PTR(ret); |
146 | } | 119 | } |
147 | 120 | ||
148 | /* | 121 | /* |
149 | * initialise the cell database from module parameters | 122 | * set the root cell information |
123 | * - can be called with a module parameter string | ||
124 | * - can be called from a write to /proc/fs/afs/rootcell | ||
150 | */ | 125 | */ |
151 | int afs_cell_init(char *rootcell) | 126 | int afs_cell_init(char *rootcell) |
152 | { | 127 | { |
153 | struct afs_cell *old_root, *new_root; | 128 | struct afs_cell *old_root, *new_root; |
154 | char *cp; | 129 | char *cp; |
155 | int ret; | ||
156 | 130 | ||
157 | _enter(""); | 131 | _enter(""); |
158 | 132 | ||
@@ -160,79 +134,60 @@ int afs_cell_init(char *rootcell) | |||
160 | /* module is loaded with no parameters, or built statically. | 134 | /* module is loaded with no parameters, or built statically. |
161 | * - in the future we might initialize cell DB here. | 135 | * - in the future we might initialize cell DB here. |
162 | */ | 136 | */ |
163 | _leave(" = 0 (but no root)"); | 137 | _leave(" = 0 [no root]"); |
164 | return 0; | 138 | return 0; |
165 | } | 139 | } |
166 | 140 | ||
167 | cp = strchr(rootcell, ':'); | 141 | cp = strchr(rootcell, ':'); |
168 | if (!cp) { | 142 | if (!cp) { |
169 | printk(KERN_ERR "kAFS: no VL server IP addresses specified\n"); | 143 | printk(KERN_ERR "kAFS: no VL server IP addresses specified\n"); |
170 | _leave(" = %d (no colon)", -EINVAL); | 144 | _leave(" = -EINVAL"); |
171 | return -EINVAL; | 145 | return -EINVAL; |
172 | } | 146 | } |
173 | 147 | ||
174 | /* allocate a cell record for the root cell */ | 148 | /* allocate a cell record for the root cell */ |
175 | *cp++ = 0; | 149 | *cp++ = 0; |
176 | ret = afs_cell_create(rootcell, cp, &new_root); | 150 | new_root = afs_cell_create(rootcell, cp); |
177 | if (ret < 0) { | 151 | if (IS_ERR(new_root)) { |
178 | _leave(" = %d", ret); | 152 | _leave(" = %ld", PTR_ERR(new_root)); |
179 | return ret; | 153 | return PTR_ERR(new_root); |
180 | } | 154 | } |
181 | 155 | ||
182 | /* as afs_put_cell() takes locks by itself, we have to do | 156 | /* install the new cell */ |
183 | * a little gymnastics to be race-free. | ||
184 | */ | ||
185 | afs_get_cell(new_root); | ||
186 | |||
187 | write_lock(&afs_cells_lock); | 157 | write_lock(&afs_cells_lock); |
188 | while (afs_cell_root) { | 158 | old_root = afs_cell_root; |
189 | old_root = afs_cell_root; | ||
190 | afs_cell_root = NULL; | ||
191 | write_unlock(&afs_cells_lock); | ||
192 | afs_put_cell(old_root); | ||
193 | write_lock(&afs_cells_lock); | ||
194 | } | ||
195 | afs_cell_root = new_root; | 159 | afs_cell_root = new_root; |
196 | write_unlock(&afs_cells_lock); | 160 | write_unlock(&afs_cells_lock); |
161 | afs_put_cell(old_root); | ||
197 | 162 | ||
198 | _leave(" = %d", ret); | 163 | _leave(" = 0"); |
199 | return ret; | 164 | return 0; |
200 | } | 165 | } |
201 | 166 | ||
202 | /* | 167 | /* |
203 | * lookup a cell record | 168 | * lookup a cell record |
204 | */ | 169 | */ |
205 | int afs_cell_lookup(const char *name, unsigned namesz, struct afs_cell **_cell) | 170 | struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz) |
206 | { | 171 | { |
207 | struct afs_cell *cell; | 172 | struct afs_cell *cell; |
208 | int ret; | ||
209 | 173 | ||
210 | _enter("\"%*.*s\",", namesz, namesz, name ? name : ""); | 174 | _enter("\"%*.*s\",", namesz, namesz, name ? name : ""); |
211 | 175 | ||
212 | *_cell = NULL; | 176 | down_read(&afs_cells_sem); |
177 | read_lock(&afs_cells_lock); | ||
213 | 178 | ||
214 | if (name) { | 179 | if (name) { |
215 | /* if the cell was named, look for it in the cell record list */ | 180 | /* if the cell was named, look for it in the cell record list */ |
216 | ret = -ENOENT; | ||
217 | cell = NULL; | ||
218 | read_lock(&afs_cells_lock); | ||
219 | |||
220 | list_for_each_entry(cell, &afs_cells, link) { | 181 | list_for_each_entry(cell, &afs_cells, link) { |
221 | if (strncmp(cell->name, name, namesz) == 0) { | 182 | if (strncmp(cell->name, name, namesz) == 0) { |
222 | afs_get_cell(cell); | 183 | afs_get_cell(cell); |
223 | goto found; | 184 | goto found; |
224 | } | 185 | } |
225 | } | 186 | } |
226 | cell = NULL; | 187 | cell = ERR_PTR(-ENOENT); |
227 | found: | 188 | found: |
228 | 189 | ; | |
229 | read_unlock(&afs_cells_lock); | ||
230 | |||
231 | if (cell) | ||
232 | ret = 0; | ||
233 | } else { | 190 | } else { |
234 | read_lock(&afs_cells_lock); | ||
235 | |||
236 | cell = afs_cell_root; | 191 | cell = afs_cell_root; |
237 | if (!cell) { | 192 | if (!cell) { |
238 | /* this should not happen unless user tries to mount | 193 | /* this should not happen unless user tries to mount |
@@ -241,37 +196,32 @@ int afs_cell_lookup(const char *name, unsigned namesz, struct afs_cell **_cell) | |||
241 | * ENOENT might be "more appropriate" but they happen | 196 | * ENOENT might be "more appropriate" but they happen |
242 | * for other reasons. | 197 | * for other reasons. |
243 | */ | 198 | */ |
244 | ret = -EDESTADDRREQ; | 199 | cell = ERR_PTR(-EDESTADDRREQ); |
245 | } else { | 200 | } else { |
246 | afs_get_cell(cell); | 201 | afs_get_cell(cell); |
247 | ret = 0; | ||
248 | } | 202 | } |
249 | 203 | ||
250 | read_unlock(&afs_cells_lock); | ||
251 | } | 204 | } |
252 | 205 | ||
253 | *_cell = cell; | 206 | read_unlock(&afs_cells_lock); |
254 | _leave(" = %d (%p)", ret, cell); | 207 | up_read(&afs_cells_sem); |
255 | return ret; | 208 | _leave(" = %p", cell); |
209 | return cell; | ||
256 | } | 210 | } |
257 | 211 | ||
258 | /* | 212 | /* |
259 | * try and get a cell record | 213 | * try and get a cell record |
260 | */ | 214 | */ |
261 | struct afs_cell *afs_get_cell_maybe(struct afs_cell **_cell) | 215 | struct afs_cell *afs_get_cell_maybe(struct afs_cell *cell) |
262 | { | 216 | { |
263 | struct afs_cell *cell; | ||
264 | |||
265 | write_lock(&afs_cells_lock); | 217 | write_lock(&afs_cells_lock); |
266 | 218 | ||
267 | cell = *_cell; | ||
268 | if (cell && !list_empty(&cell->link)) | 219 | if (cell && !list_empty(&cell->link)) |
269 | afs_get_cell(cell); | 220 | afs_get_cell(cell); |
270 | else | 221 | else |
271 | cell = NULL; | 222 | cell = NULL; |
272 | 223 | ||
273 | write_unlock(&afs_cells_lock); | 224 | write_unlock(&afs_cells_lock); |
274 | |||
275 | return cell; | 225 | return cell; |
276 | } | 226 | } |
277 | 227 | ||
@@ -285,8 +235,7 @@ void afs_put_cell(struct afs_cell *cell) | |||
285 | 235 | ||
286 | _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name); | 236 | _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name); |
287 | 237 | ||
288 | /* sanity check */ | 238 | ASSERTCMP(atomic_read(&cell->usage), >, 0); |
289 | BUG_ON(atomic_read(&cell->usage) <= 0); | ||
290 | 239 | ||
291 | /* to prevent a race, the decrement and the dequeue must be effectively | 240 | /* to prevent a race, the decrement and the dequeue must be effectively |
292 | * atomic */ | 241 | * atomic */ |
@@ -298,35 +247,49 @@ void afs_put_cell(struct afs_cell *cell) | |||
298 | return; | 247 | return; |
299 | } | 248 | } |
300 | 249 | ||
250 | ASSERT(list_empty(&cell->servers)); | ||
251 | ASSERT(list_empty(&cell->vl_list)); | ||
252 | |||
301 | write_unlock(&afs_cells_lock); | 253 | write_unlock(&afs_cells_lock); |
302 | 254 | ||
303 | BUG_ON(!list_empty(&cell->sv_list)); | 255 | wake_up(&afs_cells_freeable_wq); |
304 | BUG_ON(!list_empty(&cell->sv_graveyard)); | ||
305 | BUG_ON(!list_empty(&cell->vl_list)); | ||
306 | BUG_ON(!list_empty(&cell->vl_graveyard)); | ||
307 | 256 | ||
308 | _leave(" [unused]"); | 257 | _leave(" [unused]"); |
309 | } | 258 | } |
310 | 259 | ||
311 | /* | 260 | /* |
312 | * destroy a cell record | 261 | * destroy a cell record |
262 | * - must be called with the afs_cells_sem write-locked | ||
263 | * - cell->link should have been broken by the caller | ||
313 | */ | 264 | */ |
314 | static void afs_cell_destroy(struct afs_cell *cell) | 265 | static void afs_cell_destroy(struct afs_cell *cell) |
315 | { | 266 | { |
316 | _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name); | 267 | _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name); |
317 | 268 | ||
318 | /* to prevent a race, the decrement and the dequeue must be effectively | 269 | ASSERTCMP(atomic_read(&cell->usage), >=, 0); |
319 | * atomic */ | 270 | ASSERT(list_empty(&cell->link)); |
320 | write_lock(&afs_cells_lock); | ||
321 | 271 | ||
322 | /* sanity check */ | 272 | /* wait for everyone to stop using the cell */ |
323 | BUG_ON(atomic_read(&cell->usage) != 0); | 273 | if (atomic_read(&cell->usage) > 0) { |
274 | DECLARE_WAITQUEUE(myself, current); | ||
324 | 275 | ||
325 | list_del_init(&cell->link); | 276 | _debug("wait for cell %s", cell->name); |
277 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
278 | add_wait_queue(&afs_cells_freeable_wq, &myself); | ||
326 | 279 | ||
327 | write_unlock(&afs_cells_lock); | 280 | while (atomic_read(&cell->usage) > 0) { |
281 | schedule(); | ||
282 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
283 | } | ||
328 | 284 | ||
329 | down_write(&afs_cells_sem); | 285 | remove_wait_queue(&afs_cells_freeable_wq, &myself); |
286 | set_current_state(TASK_RUNNING); | ||
287 | } | ||
288 | |||
289 | _debug("cell dead"); | ||
290 | ASSERTCMP(atomic_read(&cell->usage), ==, 0); | ||
291 | ASSERT(list_empty(&cell->servers)); | ||
292 | ASSERT(list_empty(&cell->vl_list)); | ||
330 | 293 | ||
331 | afs_proc_cell_remove(cell); | 294 | afs_proc_cell_remove(cell); |
332 | 295 | ||
@@ -338,101 +301,25 @@ static void afs_cell_destroy(struct afs_cell *cell) | |||
338 | cachefs_relinquish_cookie(cell->cache, 0); | 301 | cachefs_relinquish_cookie(cell->cache, 0); |
339 | #endif | 302 | #endif |
340 | 303 | ||
341 | up_write(&afs_cells_sem); | ||
342 | |||
343 | BUG_ON(!list_empty(&cell->sv_list)); | ||
344 | BUG_ON(!list_empty(&cell->sv_graveyard)); | ||
345 | BUG_ON(!list_empty(&cell->vl_list)); | ||
346 | BUG_ON(!list_empty(&cell->vl_graveyard)); | ||
347 | |||
348 | /* finish cleaning up the cell */ | ||
349 | kfree(cell); | 304 | kfree(cell); |
350 | 305 | ||
351 | _leave(" [destroyed]"); | 306 | _leave(" [destroyed]"); |
352 | } | 307 | } |
353 | 308 | ||
354 | /* | 309 | /* |
355 | * lookup the server record corresponding to an Rx RPC peer | ||
356 | */ | ||
357 | int afs_server_find_by_peer(const struct rxrpc_peer *peer, | ||
358 | struct afs_server **_server) | ||
359 | { | ||
360 | struct afs_server *server; | ||
361 | struct afs_cell *cell; | ||
362 | |||
363 | _enter("%p{a=%08x},", peer, ntohl(peer->addr.s_addr)); | ||
364 | |||
365 | /* search the cell list */ | ||
366 | read_lock(&afs_cells_lock); | ||
367 | |||
368 | list_for_each_entry(cell, &afs_cells, link) { | ||
369 | |||
370 | _debug("? cell %s",cell->name); | ||
371 | |||
372 | write_lock(&cell->sv_lock); | ||
373 | |||
374 | /* check the active list */ | ||
375 | list_for_each_entry(server, &cell->sv_list, link) { | ||
376 | _debug("?? server %08x", ntohl(server->addr.s_addr)); | ||
377 | |||
378 | if (memcmp(&server->addr, &peer->addr, | ||
379 | sizeof(struct in_addr)) == 0) | ||
380 | goto found_server; | ||
381 | } | ||
382 | |||
383 | /* check the inactive list */ | ||
384 | spin_lock(&cell->sv_gylock); | ||
385 | list_for_each_entry(server, &cell->sv_graveyard, link) { | ||
386 | _debug("?? dead server %08x", | ||
387 | ntohl(server->addr.s_addr)); | ||
388 | |||
389 | if (memcmp(&server->addr, &peer->addr, | ||
390 | sizeof(struct in_addr)) == 0) | ||
391 | goto found_dead_server; | ||
392 | } | ||
393 | spin_unlock(&cell->sv_gylock); | ||
394 | |||
395 | write_unlock(&cell->sv_lock); | ||
396 | } | ||
397 | read_unlock(&afs_cells_lock); | ||
398 | |||
399 | _leave(" = -ENOENT"); | ||
400 | return -ENOENT; | ||
401 | |||
402 | /* we found it in the graveyard - resurrect it */ | ||
403 | found_dead_server: | ||
404 | list_move_tail(&server->link, &cell->sv_list); | ||
405 | afs_get_server(server); | ||
406 | afs_kafstimod_del_timer(&server->timeout); | ||
407 | spin_unlock(&cell->sv_gylock); | ||
408 | goto success; | ||
409 | |||
410 | /* we found it - increment its ref count and return it */ | ||
411 | found_server: | ||
412 | afs_get_server(server); | ||
413 | |||
414 | success: | ||
415 | write_unlock(&cell->sv_lock); | ||
416 | read_unlock(&afs_cells_lock); | ||
417 | |||
418 | *_server = server; | ||
419 | _leave(" = 0 (s=%p c=%p)", server, cell); | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * purge in-memory cell database on module unload or afs_init() failure | 310 | * purge in-memory cell database on module unload or afs_init() failure |
425 | * - the timeout daemon is stopped before calling this | 311 | * - the timeout daemon is stopped before calling this |
426 | */ | 312 | */ |
427 | void afs_cell_purge(void) | 313 | void afs_cell_purge(void) |
428 | { | 314 | { |
429 | struct afs_vlocation *vlocation; | ||
430 | struct afs_cell *cell; | 315 | struct afs_cell *cell; |
431 | 316 | ||
432 | _enter(""); | 317 | _enter(""); |
433 | 318 | ||
434 | afs_put_cell(afs_cell_root); | 319 | afs_put_cell(afs_cell_root); |
435 | 320 | ||
321 | down_write(&afs_cells_sem); | ||
322 | |||
436 | while (!list_empty(&afs_cells)) { | 323 | while (!list_empty(&afs_cells)) { |
437 | cell = NULL; | 324 | cell = NULL; |
438 | 325 | ||
@@ -451,102 +338,11 @@ void afs_cell_purge(void) | |||
451 | _debug("PURGING CELL %s (%d)", | 338 | _debug("PURGING CELL %s (%d)", |
452 | cell->name, atomic_read(&cell->usage)); | 339 | cell->name, atomic_read(&cell->usage)); |
453 | 340 | ||
454 | BUG_ON(!list_empty(&cell->sv_list)); | ||
455 | BUG_ON(!list_empty(&cell->vl_list)); | ||
456 | |||
457 | /* purge the cell's VL graveyard list */ | ||
458 | _debug(" - clearing VL graveyard"); | ||
459 | |||
460 | spin_lock(&cell->vl_gylock); | ||
461 | |||
462 | while (!list_empty(&cell->vl_graveyard)) { | ||
463 | vlocation = list_entry(cell->vl_graveyard.next, | ||
464 | struct afs_vlocation, | ||
465 | link); | ||
466 | list_del_init(&vlocation->link); | ||
467 | |||
468 | afs_kafstimod_del_timer(&vlocation->timeout); | ||
469 | |||
470 | spin_unlock(&cell->vl_gylock); | ||
471 | |||
472 | afs_vlocation_do_timeout(vlocation); | ||
473 | /* TODO: race if move to use krxtimod instead | ||
474 | * of kafstimod */ | ||
475 | |||
476 | spin_lock(&cell->vl_gylock); | ||
477 | } | ||
478 | |||
479 | spin_unlock(&cell->vl_gylock); | ||
480 | |||
481 | /* purge the cell's server graveyard list */ | ||
482 | _debug(" - clearing server graveyard"); | ||
483 | |||
484 | spin_lock(&cell->sv_gylock); | ||
485 | |||
486 | while (!list_empty(&cell->sv_graveyard)) { | ||
487 | struct afs_server *server; | ||
488 | |||
489 | server = list_entry(cell->sv_graveyard.next, | ||
490 | struct afs_server, link); | ||
491 | list_del_init(&server->link); | ||
492 | |||
493 | afs_kafstimod_del_timer(&server->timeout); | ||
494 | |||
495 | spin_unlock(&cell->sv_gylock); | ||
496 | |||
497 | afs_server_do_timeout(server); | ||
498 | |||
499 | spin_lock(&cell->sv_gylock); | ||
500 | } | ||
501 | |||
502 | spin_unlock(&cell->sv_gylock); | ||
503 | |||
504 | /* now the cell should be left with no references */ | 341 | /* now the cell should be left with no references */ |
505 | afs_cell_destroy(cell); | 342 | afs_cell_destroy(cell); |
506 | } | 343 | } |
507 | } | 344 | } |
508 | 345 | ||
346 | up_write(&afs_cells_sem); | ||
509 | _leave(""); | 347 | _leave(""); |
510 | } | 348 | } |
511 | |||
512 | /* | ||
513 | * match a cell record obtained from the cache | ||
514 | */ | ||
515 | #ifdef AFS_CACHING_SUPPORT | ||
516 | static cachefs_match_val_t afs_cell_cache_match(void *target, | ||
517 | const void *entry) | ||
518 | { | ||
519 | const struct afs_cache_cell *ccell = entry; | ||
520 | struct afs_cell *cell = target; | ||
521 | |||
522 | _enter("{%s},{%s}", ccell->name, cell->name); | ||
523 | |||
524 | if (strncmp(ccell->name, cell->name, sizeof(ccell->name)) == 0) { | ||
525 | _leave(" = SUCCESS"); | ||
526 | return CACHEFS_MATCH_SUCCESS; | ||
527 | } | ||
528 | |||
529 | _leave(" = FAILED"); | ||
530 | return CACHEFS_MATCH_FAILED; | ||
531 | } | ||
532 | #endif | ||
533 | |||
534 | /* | ||
535 | * update a cell record in the cache | ||
536 | */ | ||
537 | #ifdef AFS_CACHING_SUPPORT | ||
538 | static void afs_cell_cache_update(void *source, void *entry) | ||
539 | { | ||
540 | struct afs_cache_cell *ccell = entry; | ||
541 | struct afs_cell *cell = source; | ||
542 | |||
543 | _enter("%p,%p", source, entry); | ||
544 | |||
545 | strncpy(ccell->name, cell->name, sizeof(ccell->name)); | ||
546 | |||
547 | memcpy(ccell->vl_servers, | ||
548 | cell->vl_addrs, | ||
549 | min(sizeof(ccell->vl_servers), sizeof(cell->vl_addrs))); | ||
550 | |||
551 | } | ||
552 | #endif | ||