Blame view

fs/afs/cell.c 10.3 KB
ec26815ad   David Howells   [AFS]: Clean up t...
1
  /* AFS cell and server record management
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
13
  #include <linux/slab.h>
00d3b7a45   David Howells   [AFS]: Add securi...
14
15
  #include <linux/key.h>
  #include <linux/ctype.h>
07567a550   Wang Lei   DNS: Make AFS go ...
16
  #include <linux/dns_resolver.h>
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
17
  #include <linux/sched.h>
00d3b7a45   David Howells   [AFS]: Add securi...
18
  #include <keys/rxrpc-type.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
  #include "internal.h"
  
  DECLARE_RWSEM(afs_proc_cells_sem);
  LIST_HEAD(afs_proc_cells);
0ae52d6fb   Robert P. J. Day   afs: use the shor...
23
  static LIST_HEAD(afs_cells);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
  static DEFINE_RWLOCK(afs_cells_lock);
  static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
26
  static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  static struct afs_cell *afs_cell_root;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  /*
00d3b7a45   David Howells   [AFS]: Add securi...
29
30
   * allocate a cell record and fill in its name, VL server address list and
   * allocate an anonymous key
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
   */
bec5eb614   wanglei   AFS: Implement an...
32
33
  static struct afs_cell *afs_cell_alloc(const char *name, unsigned namelen,
  				       char *vllist)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
  {
  	struct afs_cell *cell;
76181c134   David Howells   KEYS: Make reques...
36
  	struct key *key;
00d3b7a45   David Howells   [AFS]: Add securi...
37
  	char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
07567a550   Wang Lei   DNS: Make AFS go ...
38
39
  	char  *dvllist = NULL, *_vllist = NULL;
  	char  delimiter = ':';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  	int ret;
bec5eb614   wanglei   AFS: Implement an...
41
  	_enter("%*.*s,%s", namelen, namelen, name ?: "", vllist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
  
  	BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */
07567a550   Wang Lei   DNS: Make AFS go ...
44
45
  	if (namelen > AFS_MAXCELLNAME) {
  		_leave(" = -ENAMETOOLONG");
00d3b7a45   David Howells   [AFS]: Add securi...
46
  		return ERR_PTR(-ENAMETOOLONG);
07567a550   Wang Lei   DNS: Make AFS go ...
47
  	}
00d3b7a45   David Howells   [AFS]: Add securi...
48

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  	/* allocate and initialise a cell record */
00d3b7a45   David Howells   [AFS]: Add securi...
50
  	cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  	if (!cell) {
  		_leave(" = -ENOMEM");
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
53
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  	}
00d3b7a45   David Howells   [AFS]: Add securi...
55
56
  	memcpy(cell->name, name, namelen);
  	cell->name[namelen] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
58
  	atomic_set(&cell->usage, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  	INIT_LIST_HEAD(&cell->link);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
60
61
  	rwlock_init(&cell->servers_lock);
  	INIT_LIST_HEAD(&cell->servers);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
  	init_rwsem(&cell->vl_sem);
  	INIT_LIST_HEAD(&cell->vl_list);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
64
  	spin_lock_init(&cell->vl_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65

07567a550   Wang Lei   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   Wang Lei   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   Wang Lei   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   Linus Torvalds   Linux-2.6.12-rc2
85
  	/* fill in the VL server list from the rest of the string */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
  	do {
  		unsigned a, b, c, d;
07567a550   Wang Lei   DNS: Make AFS go ...
88
  		next = strchr(_vllist, delimiter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
  		if (next)
  			*next++ = 0;
07567a550   Wang Lei   DNS: Make AFS go ...
91
  		if (sscanf(_vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
00d3b7a45   David Howells   [AFS]: Add securi...
92
  			goto bad_address;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
  
  		if (a > 255 || b > 255 || c > 255 || d > 255)
00d3b7a45   David Howells   [AFS]: Add securi...
95
  			goto bad_address;
1da177e4c   Linus Torvalds   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   Wang Lei   DNS: Make AFS go ...
99
  	} while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (_vllist = next));
00d3b7a45   David Howells   [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   David Howells   [AFS]: Add securi...
108

76181c134   David Howells   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   David Howells   [AFS]: Add securi...
113
114
  		goto error;
  	}
76181c134   David Howells   KEYS: Make reques...
115
  	cell->anonymous_key = key;
00d3b7a45   David Howells   [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   Wang Lei   DNS: Make AFS go ...
129
  	kfree(dvllist);
00d3b7a45   David Howells   [AFS]: Add securi...
130
131
132
133
  	kfree(cell);
  	_leave(" = %d", ret);
  	return ERR_PTR(ret);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134

00d3b7a45   David Howells   [AFS]: Add securi...
135
  /*
bec5eb614   wanglei   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   David Howells   [AFS]: Add securi...
141
   */
bec5eb614   wanglei   AFS: Implement an...
142
143
  struct afs_cell *afs_cell_create(const char *name, unsigned namesz,
  				 char *vllist, bool retref)
00d3b7a45   David Howells   [AFS]: Add securi...
144
145
146
  {
  	struct afs_cell *cell;
  	int ret;
bec5eb614   wanglei   AFS: Implement an...
147
  	_enter("%*.*s,%s", namesz, namesz, name ?: "", vllist);
00d3b7a45   David Howells   [AFS]: Add securi...
148

5214b729e   Sven Schnelle   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   wanglei   AFS: Implement an...
152
  		if (strncasecmp(cell->name, name, namesz) == 0)
5214b729e   Sven Schnelle   afs: prevent doub...
153
154
155
  			goto duplicate_name;
  	}
  	read_unlock(&afs_cells_lock);
bec5eb614   wanglei   AFS: Implement an...
156
  	cell = afs_cell_alloc(name, namesz, vllist);
00d3b7a45   David Howells   [AFS]: Add securi...
157
158
  	if (IS_ERR(cell)) {
  		_leave(" = %ld", PTR_ERR(cell));
a5f37c325   Sven Schnelle   afs: add missing ...
159
  		up_write(&afs_cells_sem);
00d3b7a45   David Howells   [AFS]: Add securi...
160
161
  		return cell;
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
162
  	/* add a proc directory for this cell */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
  	ret = afs_proc_cell_setup(cell);
  	if (ret < 0)
  		goto error;
9b3f26c91   David Howells   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   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
181
  	up_write(&afs_cells_sem);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
182
183
  	_leave(" = %p", cell);
  	return cell;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184

ec26815ad   David Howells   [AFS]: Clean up t...
185
  error:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  	up_write(&afs_cells_sem);
00d3b7a45   David Howells   [AFS]: Add securi...
187
  	key_put(cell->anonymous_key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
  	kfree(cell);
  	_leave(" = %d", ret);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
190
  	return ERR_PTR(ret);
5214b729e   Sven Schnelle   afs: prevent doub...
191
192
  
  duplicate_name:
bec5eb614   wanglei   AFS: Implement an...
193
194
  	if (retref && !IS_ERR(cell))
  		afs_get_cell(cell);
5214b729e   Sven Schnelle   afs: prevent doub...
195
196
  	read_unlock(&afs_cells_lock);
  	up_write(&afs_cells_sem);
bec5eb614   wanglei   AFS: Implement an...
197
198
199
200
201
202
203
  
  	if (retref) {
  		_leave(" = %p", cell);
  		return cell;
  	}
  
  	_leave(" = -EEXIST");
5214b729e   Sven Schnelle   afs: prevent doub...
204
  	return ERR_PTR(-EEXIST);
ec26815ad   David Howells   [AFS]: Clean up t...
205
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  /*
08e0e7c82   David Howells   [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   Linus Torvalds   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   Linus Torvalds   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   David Howells   [AF_RXRPC]: Make ...
223
  		_leave(" = 0 [no root]");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
  		return 0;
  	}
  
  	cp = strchr(rootcell, ':');
07567a550   Wang Lei   DNS: Make AFS go ...
228
229
230
231
  	if (!cp)
  		_debug("kAFS: no VL server IP addresses specified");
  	else
  		*cp++ = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
  
  	/* allocate a cell record for the root cell */
bec5eb614   wanglei   AFS: Implement an...
234
  	new_root = afs_cell_create(rootcell, strlen(rootcell), cp, false);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
235
236
237
  	if (IS_ERR(new_root)) {
  		_leave(" = %ld", PTR_ERR(new_root));
  		return PTR_ERR(new_root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
239
  	/* install the new cell */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
  	write_lock(&afs_cells_lock);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
241
  	old_root = afs_cell_root;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
  	afs_cell_root = new_root;
  	write_unlock(&afs_cells_lock);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
244
  	afs_put_cell(old_root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
246
247
  	_leave(" = 0");
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
248
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
252
  /*
   * lookup a cell record
   */
bec5eb614   wanglei   AFS: Implement an...
253
254
  struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz,
  				 bool dns_cell)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
  {
  	struct afs_cell *cell;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257

bec5eb614   wanglei   AFS: Implement an...
258
  	_enter("\"%*.*s\",", namesz, namesz, name ?: "");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
260
261
  	down_read(&afs_cells_sem);
  	read_lock(&afs_cells_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
  
  	if (name) {
  		/* if the cell was named, look for it in the cell record list */
1da177e4c   Linus Torvalds   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   David Howells   [AF_RXRPC]: Make ...
271
  		cell = ERR_PTR(-ENOENT);
bec5eb614   wanglei   AFS: Implement an...
272
273
  		if (dns_cell)
  			goto create_cell;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  	found:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
275
  		;
ec26815ad   David Howells   [AFS]: Clean up t...
276
  	} else {
1da177e4c   Linus Torvalds   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   Lucas De Marchi   Fix common misspe...
281
  			 * bizarre errno to alert the user. Things like
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
  			 * ENOENT might be "more appropriate" but they happen
  			 * for other reasons.
  			 */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
285
  			cell = ERR_PTR(-EDESTADDRREQ);
ec26815ad   David Howells   [AFS]: Clean up t...
286
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  			afs_get_cell(cell);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
290
291
292
293
  	read_unlock(&afs_cells_lock);
  	up_read(&afs_cells_sem);
  	_leave(" = %p", cell);
  	return cell;
bec5eb614   wanglei   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   David Howells   [AFS]: Clean up t...
303
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304

c1206a2c6   Adrian Bunk   fs/afs/: possible...
305
  #if 0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
307
308
  /*
   * try and get a cell record
   */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
309
  struct afs_cell *afs_get_cell_maybe(struct afs_cell *cell)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  	write_lock(&afs_cells_lock);
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
318
  	return cell;
ec26815ad   David Howells   [AFS]: Clean up t...
319
  }
c1206a2c6   Adrian Bunk   fs/afs/: possible...
320
  #endif  /*  0  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321

1da177e4c   Linus Torvalds   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   David Howells   [AF_RXRPC]: Make ...
331
  	ASSERTCMP(atomic_read(&cell->usage), >, 0);
1da177e4c   Linus Torvalds   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   David Howells   [AF_RXRPC]: Make ...
342
343
  	ASSERT(list_empty(&cell->servers));
  	ASSERT(list_empty(&cell->vl_list));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  	write_unlock(&afs_cells_lock);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
345
  	wake_up(&afs_cells_freeable_wq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
  
  	_leave(" [unused]");
ec26815ad   David Howells   [AFS]: Clean up t...
348
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
  /*
   * destroy a cell record
08e0e7c82   David Howells   [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   Linus Torvalds   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   David Howells   [AF_RXRPC]: Make ...
358
359
  	ASSERTCMP(atomic_read(&cell->usage), >=, 0);
  	ASSERT(list_empty(&cell->link));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360

08e0e7c82   David Howells   [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   Linus Torvalds   Linux-2.6.12-rc2
364

08e0e7c82   David Howells   [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   Linus Torvalds   Linux-2.6.12-rc2
368

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
369
370
371
372
  		while (atomic_read(&cell->usage) > 0) {
  			schedule();
  			set_current_state(TASK_UNINTERRUPTIBLE);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373

08e0e7c82   David Howells   [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   Linus Torvalds   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   David Howells   FS-Cache: Make kA...
388
389
  #ifdef CONFIG_AFS_FSCACHE
  	fscache_relinquish_cookie(cell->cache, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
  #endif
00d3b7a45   David Howells   [AFS]: Add securi...
391
  	key_put(cell->anonymous_key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
  	kfree(cell);
  
  	_leave(" [destroyed]");
ec26815ad   David Howells   [AFS]: Clean up t...
395
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  /*
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
407
  	struct afs_cell *cell;
  
  	_enter("");
  
  	afs_put_cell(afs_cell_root);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
408
  	down_write(&afs_cells_sem);
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
426
427
428
429
  			/* now the cell should be left with no references */
  			afs_cell_destroy(cell);
  		}
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
430
  	up_write(&afs_cells_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  	_leave("");
ec26815ad   David Howells   [AFS]: Clean up t...
432
  }