xref: /linux/fs/afs/cell.c (revision c537b994505099b7197e7d3125b942ecbcc51eb6)
1 /* cell.c: AFS cell and server record management
2  *
3  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11 
12 #include <linux/module.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"
24 
25 DECLARE_RWSEM(afs_proc_cells_sem);
26 LIST_HEAD(afs_proc_cells);
27 
28 static struct list_head afs_cells = LIST_HEAD_INIT(afs_cells);
29 static DEFINE_RWLOCK(afs_cells_lock);
30 static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */
31 static struct afs_cell *afs_cell_root;
32 
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 /*****************************************************************************/
48 /*
49  * create a cell record
50  * - "name" is the name of the cell
51  * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format
52  */
53 int afs_cell_create(const char *name, char *vllist, struct afs_cell **_cell)
54 {
55 	struct afs_cell *cell;
56 	char *next;
57 	int ret;
58 
59 	_enter("%s", name);
60 
61 	BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */
62 
63 	/* allocate and initialise a cell record */
64 	cell = kmalloc(sizeof(struct afs_cell) + strlen(name) + 1, GFP_KERNEL);
65 	if (!cell) {
66 		_leave(" = -ENOMEM");
67 		return -ENOMEM;
68 	}
69 
70 	down_write(&afs_cells_sem);
71 
72 	memset(cell, 0, sizeof(struct afs_cell));
73 	atomic_set(&cell->usage, 0);
74 
75 	INIT_LIST_HEAD(&cell->link);
76 
77 	rwlock_init(&cell->sv_lock);
78 	INIT_LIST_HEAD(&cell->sv_list);
79 	INIT_LIST_HEAD(&cell->sv_graveyard);
80 	spin_lock_init(&cell->sv_gylock);
81 
82 	init_rwsem(&cell->vl_sem);
83 	INIT_LIST_HEAD(&cell->vl_list);
84 	INIT_LIST_HEAD(&cell->vl_graveyard);
85 	spin_lock_init(&cell->vl_gylock);
86 
87 	strcpy(cell->name,name);
88 
89 	/* fill in the VL server list from the rest of the string */
90 	ret = -EINVAL;
91 	do {
92 		unsigned a, b, c, d;
93 
94 		next = strchr(vllist, ':');
95 		if (next)
96 			*next++ = 0;
97 
98 		if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
99 			goto badaddr;
100 
101 		if (a > 255 || b > 255 || c > 255 || d > 255)
102 			goto badaddr;
103 
104 		cell->vl_addrs[cell->vl_naddrs++].s_addr =
105 			htonl((a << 24) | (b << 16) | (c << 8) | d);
106 
107 		if (cell->vl_naddrs >= AFS_CELL_MAX_ADDRS)
108 			break;
109 
110 	} while(vllist = next, vllist);
111 
112 	/* add a proc dir for this cell */
113 	ret = afs_proc_cell_setup(cell);
114 	if (ret < 0)
115 		goto error;
116 
117 #ifdef AFS_CACHING_SUPPORT
118 	/* put it up for caching */
119 	cachefs_acquire_cookie(afs_cache_netfs.primary_index,
120 			       &afs_vlocation_cache_index_def,
121 			       cell,
122 			       &cell->cache);
123 #endif
124 
125 	/* add to the cell lists */
126 	write_lock(&afs_cells_lock);
127 	list_add_tail(&cell->link, &afs_cells);
128 	write_unlock(&afs_cells_lock);
129 
130 	down_write(&afs_proc_cells_sem);
131 	list_add_tail(&cell->proc_link, &afs_proc_cells);
132 	up_write(&afs_proc_cells_sem);
133 
134 	*_cell = cell;
135 	up_write(&afs_cells_sem);
136 
137 	_leave(" = 0 (%p)", cell);
138 	return 0;
139 
140  badaddr:
141 	printk(KERN_ERR "kAFS: bad VL server IP address: '%s'\n", vllist);
142  error:
143 	up_write(&afs_cells_sem);
144 	kfree(cell);
145 	_leave(" = %d", ret);
146 	return ret;
147 } /* end afs_cell_create() */
148 
149 /*****************************************************************************/
150 /*
151  * initialise the cell database from module parameters
152  */
153 int afs_cell_init(char *rootcell)
154 {
155 	struct afs_cell *old_root, *new_root;
156 	char *cp;
157 	int ret;
158 
159 	_enter("");
160 
161 	if (!rootcell) {
162 		/* module is loaded with no parameters, or built statically.
163 		 * - in the future we might initialize cell DB here.
164 		 */
165 		_leave(" = 0 (but no root)");
166 		return 0;
167 	}
168 
169 	cp = strchr(rootcell, ':');
170 	if (!cp) {
171 		printk(KERN_ERR "kAFS: no VL server IP addresses specified\n");
172 		_leave(" = %d (no colon)", -EINVAL);
173 		return -EINVAL;
174 	}
175 
176 	/* allocate a cell record for the root cell */
177 	*cp++ = 0;
178 	ret = afs_cell_create(rootcell, cp, &new_root);
179 	if (ret < 0) {
180 		_leave(" = %d", ret);
181 		return ret;
182 	}
183 
184 	/* as afs_put_cell() takes locks by itself, we have to do
185 	 * a little gymnastics to be race-free.
186 	 */
187 	afs_get_cell(new_root);
188 
189 	write_lock(&afs_cells_lock);
190 	while (afs_cell_root) {
191 		old_root = afs_cell_root;
192 		afs_cell_root = NULL;
193 		write_unlock(&afs_cells_lock);
194 		afs_put_cell(old_root);
195 		write_lock(&afs_cells_lock);
196 	}
197 	afs_cell_root = new_root;
198 	write_unlock(&afs_cells_lock);
199 
200 	_leave(" = %d", ret);
201 	return ret;
202 
203 } /* end afs_cell_init() */
204 
205 /*****************************************************************************/
206 /*
207  * lookup a cell record
208  */
209 int afs_cell_lookup(const char *name, unsigned namesz, struct afs_cell **_cell)
210 {
211 	struct afs_cell *cell;
212 	int ret;
213 
214 	_enter("\"%*.*s\",", namesz, namesz, name ? name : "");
215 
216 	*_cell = NULL;
217 
218 	if (name) {
219 		/* if the cell was named, look for it in the cell record list */
220 		ret = -ENOENT;
221 		cell = NULL;
222 		read_lock(&afs_cells_lock);
223 
224 		list_for_each_entry(cell, &afs_cells, link) {
225 			if (strncmp(cell->name, name, namesz) == 0) {
226 				afs_get_cell(cell);
227 				goto found;
228 			}
229 		}
230 		cell = NULL;
231 	found:
232 
233 		read_unlock(&afs_cells_lock);
234 
235 		if (cell)
236 			ret = 0;
237 	}
238 	else {
239 		read_lock(&afs_cells_lock);
240 
241 		cell = afs_cell_root;
242 		if (!cell) {
243 			/* this should not happen unless user tries to mount
244 			 * when root cell is not set. Return an impossibly
245 			 * bizzare errno to alert the user. Things like
246 			 * ENOENT might be "more appropriate" but they happen
247 			 * for other reasons.
248 			 */
249 			ret = -EDESTADDRREQ;
250 		}
251 		else {
252 			afs_get_cell(cell);
253 			ret = 0;
254 		}
255 
256 		read_unlock(&afs_cells_lock);
257 	}
258 
259 	*_cell = cell;
260 	_leave(" = %d (%p)", ret, cell);
261 	return ret;
262 
263 } /* end afs_cell_lookup() */
264 
265 /*****************************************************************************/
266 /*
267  * try and get a cell record
268  */
269 struct afs_cell *afs_get_cell_maybe(struct afs_cell **_cell)
270 {
271 	struct afs_cell *cell;
272 
273 	write_lock(&afs_cells_lock);
274 
275 	cell = *_cell;
276 	if (cell && !list_empty(&cell->link))
277 		afs_get_cell(cell);
278 	else
279 		cell = NULL;
280 
281 	write_unlock(&afs_cells_lock);
282 
283 	return cell;
284 } /* end afs_get_cell_maybe() */
285 
286 /*****************************************************************************/
287 /*
288  * destroy a cell record
289  */
290 void afs_put_cell(struct afs_cell *cell)
291 {
292 	if (!cell)
293 		return;
294 
295 	_enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name);
296 
297 	/* sanity check */
298 	BUG_ON(atomic_read(&cell->usage) <= 0);
299 
300 	/* to prevent a race, the decrement and the dequeue must be effectively
301 	 * atomic */
302 	write_lock(&afs_cells_lock);
303 
304 	if (likely(!atomic_dec_and_test(&cell->usage))) {
305 		write_unlock(&afs_cells_lock);
306 		_leave("");
307 		return;
308 	}
309 
310 	write_unlock(&afs_cells_lock);
311 
312 	BUG_ON(!list_empty(&cell->sv_list));
313 	BUG_ON(!list_empty(&cell->sv_graveyard));
314 	BUG_ON(!list_empty(&cell->vl_list));
315 	BUG_ON(!list_empty(&cell->vl_graveyard));
316 
317 	_leave(" [unused]");
318 } /* end afs_put_cell() */
319 
320 /*****************************************************************************/
321 /*
322  * destroy a cell record
323  */
324 static void afs_cell_destroy(struct afs_cell *cell)
325 {
326 	_enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name);
327 
328 	/* to prevent a race, the decrement and the dequeue must be effectively
329 	 * atomic */
330 	write_lock(&afs_cells_lock);
331 
332 	/* sanity check */
333 	BUG_ON(atomic_read(&cell->usage) != 0);
334 
335 	list_del_init(&cell->link);
336 
337 	write_unlock(&afs_cells_lock);
338 
339 	down_write(&afs_cells_sem);
340 
341 	afs_proc_cell_remove(cell);
342 
343 	down_write(&afs_proc_cells_sem);
344 	list_del_init(&cell->proc_link);
345 	up_write(&afs_proc_cells_sem);
346 
347 #ifdef AFS_CACHING_SUPPORT
348 	cachefs_relinquish_cookie(cell->cache, 0);
349 #endif
350 
351 	up_write(&afs_cells_sem);
352 
353 	BUG_ON(!list_empty(&cell->sv_list));
354 	BUG_ON(!list_empty(&cell->sv_graveyard));
355 	BUG_ON(!list_empty(&cell->vl_list));
356 	BUG_ON(!list_empty(&cell->vl_graveyard));
357 
358 	/* finish cleaning up the cell */
359 	kfree(cell);
360 
361 	_leave(" [destroyed]");
362 } /* end afs_cell_destroy() */
363 
364 /*****************************************************************************/
365 /*
366  * lookup the server record corresponding to an Rx RPC peer
367  */
368 int afs_server_find_by_peer(const struct rxrpc_peer *peer,
369 			    struct afs_server **_server)
370 {
371 	struct afs_server *server;
372 	struct afs_cell *cell;
373 
374 	_enter("%p{a=%08x},", peer, ntohl(peer->addr.s_addr));
375 
376 	/* search the cell list */
377 	read_lock(&afs_cells_lock);
378 
379 	list_for_each_entry(cell, &afs_cells, link) {
380 
381 		_debug("? cell %s",cell->name);
382 
383 		write_lock(&cell->sv_lock);
384 
385 		/* check the active list */
386 		list_for_each_entry(server, &cell->sv_list, link) {
387 			_debug("?? server %08x", ntohl(server->addr.s_addr));
388 
389 			if (memcmp(&server->addr, &peer->addr,
390 				   sizeof(struct in_addr)) == 0)
391 				goto found_server;
392 		}
393 
394 		/* check the inactive list */
395 		spin_lock(&cell->sv_gylock);
396 		list_for_each_entry(server, &cell->sv_graveyard, link) {
397 			_debug("?? dead server %08x",
398 			       ntohl(server->addr.s_addr));
399 
400 			if (memcmp(&server->addr, &peer->addr,
401 				   sizeof(struct in_addr)) == 0)
402 				goto found_dead_server;
403 		}
404 		spin_unlock(&cell->sv_gylock);
405 
406 		write_unlock(&cell->sv_lock);
407 	}
408 	read_unlock(&afs_cells_lock);
409 
410 	_leave(" = -ENOENT");
411 	return -ENOENT;
412 
413 	/* we found it in the graveyard - resurrect it */
414  found_dead_server:
415 	list_move_tail(&server->link, &cell->sv_list);
416 	afs_get_server(server);
417 	afs_kafstimod_del_timer(&server->timeout);
418 	spin_unlock(&cell->sv_gylock);
419 	goto success;
420 
421 	/* we found it - increment its ref count and return it */
422  found_server:
423 	afs_get_server(server);
424 
425  success:
426 	write_unlock(&cell->sv_lock);
427 	read_unlock(&afs_cells_lock);
428 
429 	*_server = server;
430 	_leave(" = 0 (s=%p c=%p)", server, cell);
431 	return 0;
432 
433 } /* end afs_server_find_by_peer() */
434 
435 /*****************************************************************************/
436 /*
437  * purge in-memory cell database on module unload or afs_init() failure
438  * - the timeout daemon is stopped before calling this
439  */
440 void afs_cell_purge(void)
441 {
442 	struct afs_vlocation *vlocation;
443 	struct afs_cell *cell;
444 
445 	_enter("");
446 
447 	afs_put_cell(afs_cell_root);
448 
449 	while (!list_empty(&afs_cells)) {
450 		cell = NULL;
451 
452 		/* remove the next cell from the front of the list */
453 		write_lock(&afs_cells_lock);
454 
455 		if (!list_empty(&afs_cells)) {
456 			cell = list_entry(afs_cells.next,
457 					  struct afs_cell, link);
458 			list_del_init(&cell->link);
459 		}
460 
461 		write_unlock(&afs_cells_lock);
462 
463 		if (cell) {
464 			_debug("PURGING CELL %s (%d)",
465 			       cell->name, atomic_read(&cell->usage));
466 
467 			BUG_ON(!list_empty(&cell->sv_list));
468 			BUG_ON(!list_empty(&cell->vl_list));
469 
470 			/* purge the cell's VL graveyard list */
471 			_debug(" - clearing VL graveyard");
472 
473 			spin_lock(&cell->vl_gylock);
474 
475 			while (!list_empty(&cell->vl_graveyard)) {
476 				vlocation = list_entry(cell->vl_graveyard.next,
477 						       struct afs_vlocation,
478 						       link);
479 				list_del_init(&vlocation->link);
480 
481 				afs_kafstimod_del_timer(&vlocation->timeout);
482 
483 				spin_unlock(&cell->vl_gylock);
484 
485 				afs_vlocation_do_timeout(vlocation);
486 				/* TODO: race if move to use krxtimod instead
487 				 * of kafstimod */
488 
489 				spin_lock(&cell->vl_gylock);
490 			}
491 
492 			spin_unlock(&cell->vl_gylock);
493 
494 			/* purge the cell's server graveyard list */
495 			_debug(" - clearing server graveyard");
496 
497 			spin_lock(&cell->sv_gylock);
498 
499 			while (!list_empty(&cell->sv_graveyard)) {
500 				struct afs_server *server;
501 
502 				server = list_entry(cell->sv_graveyard.next,
503 						    struct afs_server, link);
504 				list_del_init(&server->link);
505 
506 				afs_kafstimod_del_timer(&server->timeout);
507 
508 				spin_unlock(&cell->sv_gylock);
509 
510 				afs_server_do_timeout(server);
511 
512 				spin_lock(&cell->sv_gylock);
513 			}
514 
515 			spin_unlock(&cell->sv_gylock);
516 
517 			/* now the cell should be left with no references */
518 			afs_cell_destroy(cell);
519 		}
520 	}
521 
522 	_leave("");
523 } /* end afs_cell_purge() */
524 
525 /*****************************************************************************/
526 /*
527  * match a cell record obtained from the cache
528  */
529 #ifdef AFS_CACHING_SUPPORT
530 static cachefs_match_val_t afs_cell_cache_match(void *target,
531 						const void *entry)
532 {
533 	const struct afs_cache_cell *ccell = entry;
534 	struct afs_cell *cell = target;
535 
536 	_enter("{%s},{%s}", ccell->name, cell->name);
537 
538 	if (strncmp(ccell->name, cell->name, sizeof(ccell->name)) == 0) {
539 		_leave(" = SUCCESS");
540 		return CACHEFS_MATCH_SUCCESS;
541 	}
542 
543 	_leave(" = FAILED");
544 	return CACHEFS_MATCH_FAILED;
545 } /* end afs_cell_cache_match() */
546 #endif
547 
548 /*****************************************************************************/
549 /*
550  * update a cell record in the cache
551  */
552 #ifdef AFS_CACHING_SUPPORT
553 static void afs_cell_cache_update(void *source, void *entry)
554 {
555 	struct afs_cache_cell *ccell = entry;
556 	struct afs_cell *cell = source;
557 
558 	_enter("%p,%p", source, entry);
559 
560 	strncpy(ccell->name, cell->name, sizeof(ccell->name));
561 
562 	memcpy(ccell->vl_servers,
563 	       cell->vl_addrs,
564 	       min(sizeof(ccell->vl_servers), sizeof(cell->vl_addrs)));
565 
566 } /* end afs_cell_cache_update() */
567 #endif
568