Blame view
fs/afs/cell.c
10.3 KB
ec26815ad [AFS]: Clean up t... |
1 |
/* AFS cell and server record management |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 8 9 10 11 12 |
* * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
13 |
#include <linux/slab.h> |
00d3b7a45 [AFS]: Add securi... |
14 15 |
#include <linux/key.h> #include <linux/ctype.h> |
07567a550 DNS: Make AFS go ... |
16 |
#include <linux/dns_resolver.h> |
e8edc6e03 Detach sched.h fr... |
17 |
#include <linux/sched.h> |
00d3b7a45 [AFS]: Add securi... |
18 |
#include <keys/rxrpc-type.h> |
1da177e4c Linux-2.6.12-rc2 |
19 20 21 22 |
#include "internal.h" DECLARE_RWSEM(afs_proc_cells_sem); LIST_HEAD(afs_proc_cells); |
0ae52d6fb afs: use the shor... |
23 |
static LIST_HEAD(afs_cells); |
1da177e4c Linux-2.6.12-rc2 |
24 25 |
static DEFINE_RWLOCK(afs_cells_lock); static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */ |
08e0e7c82 [AF_RXRPC]: Make ... |
26 |
static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq); |
1da177e4c Linux-2.6.12-rc2 |
27 |
static struct afs_cell *afs_cell_root; |
1da177e4c Linux-2.6.12-rc2 |
28 |
/* |
00d3b7a45 [AFS]: Add securi... |
29 30 |
* allocate a cell record and fill in its name, VL server address list and * allocate an anonymous key |
1da177e4c Linux-2.6.12-rc2 |
31 |
*/ |
bec5eb614 AFS: Implement an... |
32 33 |
static struct afs_cell *afs_cell_alloc(const char *name, unsigned namelen, char *vllist) |
1da177e4c Linux-2.6.12-rc2 |
34 35 |
{ struct afs_cell *cell; |
76181c134 KEYS: Make reques... |
36 |
struct key *key; |
00d3b7a45 [AFS]: Add securi... |
37 |
char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next; |
07567a550 DNS: Make AFS go ... |
38 39 |
char *dvllist = NULL, *_vllist = NULL; char delimiter = ':'; |
1da177e4c Linux-2.6.12-rc2 |
40 |
int ret; |
bec5eb614 AFS: Implement an... |
41 |
_enter("%*.*s,%s", namelen, namelen, name ?: "", vllist); |
1da177e4c Linux-2.6.12-rc2 |
42 43 |
BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ |
07567a550 DNS: Make AFS go ... |
44 45 |
if (namelen > AFS_MAXCELLNAME) { _leave(" = -ENAMETOOLONG"); |
00d3b7a45 [AFS]: Add securi... |
46 |
return ERR_PTR(-ENAMETOOLONG); |
07567a550 DNS: Make AFS go ... |
47 |
} |
00d3b7a45 [AFS]: Add securi... |
48 |
|
1da177e4c Linux-2.6.12-rc2 |
49 |
/* allocate and initialise a cell record */ |
00d3b7a45 [AFS]: Add securi... |
50 |
cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
51 52 |
if (!cell) { _leave(" = -ENOMEM"); |
08e0e7c82 [AF_RXRPC]: Make ... |
53 |
return ERR_PTR(-ENOMEM); |
1da177e4c Linux-2.6.12-rc2 |
54 |
} |
00d3b7a45 [AFS]: Add securi... |
55 56 |
memcpy(cell->name, name, namelen); cell->name[namelen] = 0; |
1da177e4c Linux-2.6.12-rc2 |
57 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
58 |
atomic_set(&cell->usage, 1); |
1da177e4c Linux-2.6.12-rc2 |
59 |
INIT_LIST_HEAD(&cell->link); |
08e0e7c82 [AF_RXRPC]: Make ... |
60 61 |
rwlock_init(&cell->servers_lock); INIT_LIST_HEAD(&cell->servers); |
1da177e4c Linux-2.6.12-rc2 |
62 63 |
init_rwsem(&cell->vl_sem); INIT_LIST_HEAD(&cell->vl_list); |
08e0e7c82 [AF_RXRPC]: Make ... |
64 |
spin_lock_init(&cell->vl_lock); |
1da177e4c Linux-2.6.12-rc2 |
65 |
|
07567a550 DNS: Make AFS go ... |
66 67 68 69 |
/* if the ip address is invalid, try dns query */ if (!vllist || strlen(vllist) < 7) { ret = dns_query("afsdb", name, namelen, "ipv4", &dvllist, NULL); if (ret < 0) { |
4a2d78926 DNS: If the DNS s... |
70 71 72 73 |
if (ret == -ENODATA || ret == -EAGAIN || ret == -ENOKEY) /* translate these errors into something * userspace might understand */ ret = -EDESTADDRREQ; |
07567a550 DNS: Make AFS go ... |
74 75 76 77 78 79 80 81 82 83 84 |
_leave(" = %d", ret); return ERR_PTR(ret); } _vllist = dvllist; /* change the delimiter for user-space reply */ delimiter = ','; } else { _vllist = vllist; } |
1da177e4c Linux-2.6.12-rc2 |
85 |
/* fill in the VL server list from the rest of the string */ |
1da177e4c Linux-2.6.12-rc2 |
86 87 |
do { unsigned a, b, c, d; |
07567a550 DNS: Make AFS go ... |
88 |
next = strchr(_vllist, delimiter); |
1da177e4c Linux-2.6.12-rc2 |
89 90 |
if (next) *next++ = 0; |
07567a550 DNS: Make AFS go ... |
91 |
if (sscanf(_vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) |
00d3b7a45 [AFS]: Add securi... |
92 |
goto bad_address; |
1da177e4c Linux-2.6.12-rc2 |
93 94 |
if (a > 255 || b > 255 || c > 255 || d > 255) |
00d3b7a45 [AFS]: Add securi... |
95 |
goto bad_address; |
1da177e4c Linux-2.6.12-rc2 |
96 97 98 |
cell->vl_addrs[cell->vl_naddrs++].s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d); |
07567a550 DNS: Make AFS go ... |
99 |
} while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (_vllist = next)); |
00d3b7a45 [AFS]: Add securi... |
100 101 102 103 104 105 106 107 |
/* create a key to represent an anonymous user */ memcpy(keyname, "afs@", 4); dp = keyname + 4; cp = cell->name; do { *dp++ = toupper(*cp); } while (*cp++); |
00d3b7a45 [AFS]: Add securi... |
108 |
|
76181c134 KEYS: Make reques... |
109 110 111 112 |
key = rxrpc_get_null_key(keyname); if (IS_ERR(key)) { _debug("no key"); ret = PTR_ERR(key); |
00d3b7a45 [AFS]: Add securi... |
113 114 |
goto error; } |
76181c134 KEYS: Make reques... |
115 |
cell->anonymous_key = key; |
00d3b7a45 [AFS]: Add securi... |
116 117 118 119 120 121 122 123 124 125 126 127 128 |
_debug("anon key %p{%x}", cell->anonymous_key, key_serial(cell->anonymous_key)); _leave(" = %p", cell); return cell; bad_address: printk(KERN_ERR "kAFS: bad VL server IP address "); ret = -EINVAL; error: key_put(cell->anonymous_key); |
07567a550 DNS: Make AFS go ... |
129 |
kfree(dvllist); |
00d3b7a45 [AFS]: Add securi... |
130 131 132 133 |
kfree(cell); _leave(" = %d", ret); return ERR_PTR(ret); } |
1da177e4c Linux-2.6.12-rc2 |
134 |
|
00d3b7a45 [AFS]: Add securi... |
135 |
/* |
bec5eb614 AFS: Implement an... |
136 137 138 139 140 |
* afs_cell_crate() - create a cell record * @name: is the name of the cell. * @namsesz: is the strlen of the cell name. * @vllist: is a colon separated list of IP addresses in "a.b.c.d" format. * @retref: is T to return the cell reference when the cell exists. |
00d3b7a45 [AFS]: Add securi... |
141 |
*/ |
bec5eb614 AFS: Implement an... |
142 143 |
struct afs_cell *afs_cell_create(const char *name, unsigned namesz, char *vllist, bool retref) |
00d3b7a45 [AFS]: Add securi... |
144 145 146 |
{ struct afs_cell *cell; int ret; |
bec5eb614 AFS: Implement an... |
147 |
_enter("%*.*s,%s", namesz, namesz, name ?: "", vllist); |
00d3b7a45 [AFS]: Add securi... |
148 |
|
5214b729e afs: prevent doub... |
149 150 151 |
down_write(&afs_cells_sem); read_lock(&afs_cells_lock); list_for_each_entry(cell, &afs_cells, link) { |
bec5eb614 AFS: Implement an... |
152 |
if (strncasecmp(cell->name, name, namesz) == 0) |
5214b729e afs: prevent doub... |
153 154 155 |
goto duplicate_name; } read_unlock(&afs_cells_lock); |
bec5eb614 AFS: Implement an... |
156 |
cell = afs_cell_alloc(name, namesz, vllist); |
00d3b7a45 [AFS]: Add securi... |
157 158 |
if (IS_ERR(cell)) { _leave(" = %ld", PTR_ERR(cell)); |
a5f37c325 afs: add missing ... |
159 |
up_write(&afs_cells_sem); |
00d3b7a45 [AFS]: Add securi... |
160 161 |
return cell; } |
08e0e7c82 [AF_RXRPC]: Make ... |
162 |
/* add a proc directory for this cell */ |
1da177e4c Linux-2.6.12-rc2 |
163 164 165 |
ret = afs_proc_cell_setup(cell); if (ret < 0) goto error; |
9b3f26c91 FS-Cache: Make kA... |
166 167 168 169 170 |
#ifdef CONFIG_AFS_FSCACHE /* put it up for caching (this never returns an error) */ cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index, &afs_cell_cache_index_def, cell); |
1da177e4c Linux-2.6.12-rc2 |
171 172 173 174 175 176 177 178 179 180 |
#endif /* add to the cell lists */ write_lock(&afs_cells_lock); list_add_tail(&cell->link, &afs_cells); write_unlock(&afs_cells_lock); down_write(&afs_proc_cells_sem); list_add_tail(&cell->proc_link, &afs_proc_cells); up_write(&afs_proc_cells_sem); |
1da177e4c Linux-2.6.12-rc2 |
181 |
up_write(&afs_cells_sem); |
08e0e7c82 [AF_RXRPC]: Make ... |
182 183 |
_leave(" = %p", cell); return cell; |
1da177e4c Linux-2.6.12-rc2 |
184 |
|
ec26815ad [AFS]: Clean up t... |
185 |
error: |
1da177e4c Linux-2.6.12-rc2 |
186 |
up_write(&afs_cells_sem); |
00d3b7a45 [AFS]: Add securi... |
187 |
key_put(cell->anonymous_key); |
1da177e4c Linux-2.6.12-rc2 |
188 189 |
kfree(cell); _leave(" = %d", ret); |
08e0e7c82 [AF_RXRPC]: Make ... |
190 |
return ERR_PTR(ret); |
5214b729e afs: prevent doub... |
191 192 |
duplicate_name: |
bec5eb614 AFS: Implement an... |
193 194 |
if (retref && !IS_ERR(cell)) afs_get_cell(cell); |
5214b729e afs: prevent doub... |
195 196 |
read_unlock(&afs_cells_lock); up_write(&afs_cells_sem); |
bec5eb614 AFS: Implement an... |
197 198 199 200 201 202 203 |
if (retref) { _leave(" = %p", cell); return cell; } _leave(" = -EEXIST"); |
5214b729e afs: prevent doub... |
204 |
return ERR_PTR(-EEXIST); |
ec26815ad [AFS]: Clean up t... |
205 |
} |
1da177e4c Linux-2.6.12-rc2 |
206 |
|
1da177e4c Linux-2.6.12-rc2 |
207 |
/* |
08e0e7c82 [AF_RXRPC]: Make ... |
208 209 210 |
* set the root cell information * - can be called with a module parameter string * - can be called from a write to /proc/fs/afs/rootcell |
1da177e4c Linux-2.6.12-rc2 |
211 212 213 214 215 |
*/ int afs_cell_init(char *rootcell) { struct afs_cell *old_root, *new_root; char *cp; |
1da177e4c Linux-2.6.12-rc2 |
216 217 218 219 220 221 222 |
_enter(""); if (!rootcell) { /* module is loaded with no parameters, or built statically. * - in the future we might initialize cell DB here. */ |
08e0e7c82 [AF_RXRPC]: Make ... |
223 |
_leave(" = 0 [no root]"); |
1da177e4c Linux-2.6.12-rc2 |
224 225 226 227 |
return 0; } cp = strchr(rootcell, ':'); |
07567a550 DNS: Make AFS go ... |
228 229 230 231 |
if (!cp) _debug("kAFS: no VL server IP addresses specified"); else *cp++ = 0; |
1da177e4c Linux-2.6.12-rc2 |
232 233 |
/* allocate a cell record for the root cell */ |
bec5eb614 AFS: Implement an... |
234 |
new_root = afs_cell_create(rootcell, strlen(rootcell), cp, false); |
08e0e7c82 [AF_RXRPC]: Make ... |
235 236 237 |
if (IS_ERR(new_root)) { _leave(" = %ld", PTR_ERR(new_root)); return PTR_ERR(new_root); |
1da177e4c Linux-2.6.12-rc2 |
238 |
} |
08e0e7c82 [AF_RXRPC]: Make ... |
239 |
/* install the new cell */ |
1da177e4c Linux-2.6.12-rc2 |
240 |
write_lock(&afs_cells_lock); |
08e0e7c82 [AF_RXRPC]: Make ... |
241 |
old_root = afs_cell_root; |
1da177e4c Linux-2.6.12-rc2 |
242 243 |
afs_cell_root = new_root; write_unlock(&afs_cells_lock); |
08e0e7c82 [AF_RXRPC]: Make ... |
244 |
afs_put_cell(old_root); |
1da177e4c Linux-2.6.12-rc2 |
245 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
246 247 |
_leave(" = 0"); return 0; |
ec26815ad [AFS]: Clean up t... |
248 |
} |
1da177e4c Linux-2.6.12-rc2 |
249 |
|
1da177e4c Linux-2.6.12-rc2 |
250 251 252 |
/* * lookup a cell record */ |
bec5eb614 AFS: Implement an... |
253 254 |
struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz, bool dns_cell) |
1da177e4c Linux-2.6.12-rc2 |
255 256 |
{ struct afs_cell *cell; |
1da177e4c Linux-2.6.12-rc2 |
257 |
|
bec5eb614 AFS: Implement an... |
258 |
_enter("\"%*.*s\",", namesz, namesz, name ?: ""); |
1da177e4c Linux-2.6.12-rc2 |
259 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
260 261 |
down_read(&afs_cells_sem); read_lock(&afs_cells_lock); |
1da177e4c Linux-2.6.12-rc2 |
262 263 264 |
if (name) { /* if the cell was named, look for it in the cell record list */ |
1da177e4c Linux-2.6.12-rc2 |
265 266 267 268 269 270 |
list_for_each_entry(cell, &afs_cells, link) { if (strncmp(cell->name, name, namesz) == 0) { afs_get_cell(cell); goto found; } } |
08e0e7c82 [AF_RXRPC]: Make ... |
271 |
cell = ERR_PTR(-ENOENT); |
bec5eb614 AFS: Implement an... |
272 273 |
if (dns_cell) goto create_cell; |
1da177e4c Linux-2.6.12-rc2 |
274 |
found: |
08e0e7c82 [AF_RXRPC]: Make ... |
275 |
; |
ec26815ad [AFS]: Clean up t... |
276 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
277 278 279 280 |
cell = afs_cell_root; if (!cell) { /* this should not happen unless user tries to mount * when root cell is not set. Return an impossibly |
25985edce Fix common misspe... |
281 |
* bizarre errno to alert the user. Things like |
1da177e4c Linux-2.6.12-rc2 |
282 283 284 |
* ENOENT might be "more appropriate" but they happen * for other reasons. */ |
08e0e7c82 [AF_RXRPC]: Make ... |
285 |
cell = ERR_PTR(-EDESTADDRREQ); |
ec26815ad [AFS]: Clean up t... |
286 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
287 |
afs_get_cell(cell); |
1da177e4c Linux-2.6.12-rc2 |
288 |
} |
1da177e4c Linux-2.6.12-rc2 |
289 |
} |
08e0e7c82 [AF_RXRPC]: Make ... |
290 291 292 293 |
read_unlock(&afs_cells_lock); up_read(&afs_cells_sem); _leave(" = %p", cell); return cell; |
bec5eb614 AFS: Implement an... |
294 295 296 297 298 299 300 301 302 |
create_cell: read_unlock(&afs_cells_lock); up_read(&afs_cells_sem); cell = afs_cell_create(name, namesz, NULL, true); _leave(" = %p", cell); return cell; |
ec26815ad [AFS]: Clean up t... |
303 |
} |
1da177e4c Linux-2.6.12-rc2 |
304 |
|
c1206a2c6 fs/afs/: possible... |
305 |
#if 0 |
1da177e4c Linux-2.6.12-rc2 |
306 307 308 |
/* * try and get a cell record */ |
08e0e7c82 [AF_RXRPC]: Make ... |
309 |
struct afs_cell *afs_get_cell_maybe(struct afs_cell *cell) |
1da177e4c Linux-2.6.12-rc2 |
310 |
{ |
1da177e4c Linux-2.6.12-rc2 |
311 |
write_lock(&afs_cells_lock); |
1da177e4c Linux-2.6.12-rc2 |
312 313 314 315 316 317 |
if (cell && !list_empty(&cell->link)) afs_get_cell(cell); else cell = NULL; write_unlock(&afs_cells_lock); |
1da177e4c Linux-2.6.12-rc2 |
318 |
return cell; |
ec26815ad [AFS]: Clean up t... |
319 |
} |
c1206a2c6 fs/afs/: possible... |
320 |
#endif /* 0 */ |
1da177e4c Linux-2.6.12-rc2 |
321 |
|
1da177e4c Linux-2.6.12-rc2 |
322 323 324 325 326 327 328 329 330 |
/* * destroy a cell record */ void afs_put_cell(struct afs_cell *cell) { if (!cell) return; _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name); |
08e0e7c82 [AF_RXRPC]: Make ... |
331 |
ASSERTCMP(atomic_read(&cell->usage), >, 0); |
1da177e4c Linux-2.6.12-rc2 |
332 333 334 335 336 337 338 339 340 341 |
/* to prevent a race, the decrement and the dequeue must be effectively * atomic */ write_lock(&afs_cells_lock); if (likely(!atomic_dec_and_test(&cell->usage))) { write_unlock(&afs_cells_lock); _leave(""); return; } |
08e0e7c82 [AF_RXRPC]: Make ... |
342 343 |
ASSERT(list_empty(&cell->servers)); ASSERT(list_empty(&cell->vl_list)); |
1da177e4c Linux-2.6.12-rc2 |
344 |
write_unlock(&afs_cells_lock); |
08e0e7c82 [AF_RXRPC]: Make ... |
345 |
wake_up(&afs_cells_freeable_wq); |
1da177e4c Linux-2.6.12-rc2 |
346 347 |
_leave(" [unused]"); |
ec26815ad [AFS]: Clean up t... |
348 |
} |
1da177e4c Linux-2.6.12-rc2 |
349 |
|
1da177e4c Linux-2.6.12-rc2 |
350 351 |
/* * destroy a cell record |
08e0e7c82 [AF_RXRPC]: Make ... |
352 353 |
* - must be called with the afs_cells_sem write-locked * - cell->link should have been broken by the caller |
1da177e4c Linux-2.6.12-rc2 |
354 355 356 357 |
*/ static void afs_cell_destroy(struct afs_cell *cell) { _enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name); |
08e0e7c82 [AF_RXRPC]: Make ... |
358 359 |
ASSERTCMP(atomic_read(&cell->usage), >=, 0); ASSERT(list_empty(&cell->link)); |
1da177e4c Linux-2.6.12-rc2 |
360 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
361 362 363 |
/* wait for everyone to stop using the cell */ if (atomic_read(&cell->usage) > 0) { DECLARE_WAITQUEUE(myself, current); |
1da177e4c Linux-2.6.12-rc2 |
364 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
365 366 367 |
_debug("wait for cell %s", cell->name); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&afs_cells_freeable_wq, &myself); |
1da177e4c Linux-2.6.12-rc2 |
368 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
369 370 371 372 |
while (atomic_read(&cell->usage) > 0) { schedule(); set_current_state(TASK_UNINTERRUPTIBLE); } |
1da177e4c Linux-2.6.12-rc2 |
373 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
374 375 376 377 378 379 380 381 |
remove_wait_queue(&afs_cells_freeable_wq, &myself); set_current_state(TASK_RUNNING); } _debug("cell dead"); ASSERTCMP(atomic_read(&cell->usage), ==, 0); ASSERT(list_empty(&cell->servers)); ASSERT(list_empty(&cell->vl_list)); |
1da177e4c Linux-2.6.12-rc2 |
382 383 384 385 386 387 |
afs_proc_cell_remove(cell); down_write(&afs_proc_cells_sem); list_del_init(&cell->proc_link); up_write(&afs_proc_cells_sem); |
9b3f26c91 FS-Cache: Make kA... |
388 389 |
#ifdef CONFIG_AFS_FSCACHE fscache_relinquish_cookie(cell->cache, 0); |
1da177e4c Linux-2.6.12-rc2 |
390 |
#endif |
00d3b7a45 [AFS]: Add securi... |
391 |
key_put(cell->anonymous_key); |
1da177e4c Linux-2.6.12-rc2 |
392 393 394 |
kfree(cell); _leave(" [destroyed]"); |
ec26815ad [AFS]: Clean up t... |
395 |
} |
1da177e4c Linux-2.6.12-rc2 |
396 |
|
1da177e4c Linux-2.6.12-rc2 |
397 |
/* |
1da177e4c Linux-2.6.12-rc2 |
398 399 400 401 402 |
* purge in-memory cell database on module unload or afs_init() failure * - the timeout daemon is stopped before calling this */ void afs_cell_purge(void) { |
1da177e4c Linux-2.6.12-rc2 |
403 404 405 406 407 |
struct afs_cell *cell; _enter(""); afs_put_cell(afs_cell_root); |
08e0e7c82 [AF_RXRPC]: Make ... |
408 |
down_write(&afs_cells_sem); |
1da177e4c Linux-2.6.12-rc2 |
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
while (!list_empty(&afs_cells)) { cell = NULL; /* remove the next cell from the front of the list */ write_lock(&afs_cells_lock); if (!list_empty(&afs_cells)) { cell = list_entry(afs_cells.next, struct afs_cell, link); list_del_init(&cell->link); } write_unlock(&afs_cells_lock); if (cell) { _debug("PURGING CELL %s (%d)", cell->name, atomic_read(&cell->usage)); |
1da177e4c Linux-2.6.12-rc2 |
426 427 428 429 |
/* now the cell should be left with no references */ afs_cell_destroy(cell); } } |
08e0e7c82 [AF_RXRPC]: Make ... |
430 |
up_write(&afs_cells_sem); |
1da177e4c Linux-2.6.12-rc2 |
431 |
_leave(""); |
ec26815ad [AFS]: Clean up t... |
432 |
} |