xref: /openbmc/linux/fs/afs/cell.c (revision e868d61272caa648214046a096e5a6bfc068dc8c)
1 /* 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 <linux/key.h>
15 #include <linux/ctype.h>
16 #include <keys/rxrpc-type.h>
17 #include "internal.h"
18 
19 DECLARE_RWSEM(afs_proc_cells_sem);
20 LIST_HEAD(afs_proc_cells);
21 
22 static struct list_head afs_cells = LIST_HEAD_INIT(afs_cells);
23 static DEFINE_RWLOCK(afs_cells_lock);
24 static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */
25 static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq);
26 static struct afs_cell *afs_cell_root;
27 
28 /*
29  * allocate a cell record and fill in its name, VL server address list and
30  * allocate an anonymous key
31  */
32 static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
33 {
34 	struct afs_cell *cell;
35 	size_t namelen;
36 	char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
37 	int ret;
38 
39 	_enter("%s,%s", name, vllist);
40 
41 	BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */
42 
43 	namelen = strlen(name);
44 	if (namelen > AFS_MAXCELLNAME)
45 		return ERR_PTR(-ENAMETOOLONG);
46 
47 	/* allocate and initialise a cell record */
48 	cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL);
49 	if (!cell) {
50 		_leave(" = -ENOMEM");
51 		return ERR_PTR(-ENOMEM);
52 	}
53 
54 	memcpy(cell->name, name, namelen);
55 	cell->name[namelen] = 0;
56 
57 	atomic_set(&cell->usage, 1);
58 	INIT_LIST_HEAD(&cell->link);
59 	rwlock_init(&cell->servers_lock);
60 	INIT_LIST_HEAD(&cell->servers);
61 	init_rwsem(&cell->vl_sem);
62 	INIT_LIST_HEAD(&cell->vl_list);
63 	spin_lock_init(&cell->vl_lock);
64 
65 	/* fill in the VL server list from the rest of the string */
66 	do {
67 		unsigned a, b, c, d;
68 
69 		next = strchr(vllist, ':');
70 		if (next)
71 			*next++ = 0;
72 
73 		if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
74 			goto bad_address;
75 
76 		if (a > 255 || b > 255 || c > 255 || d > 255)
77 			goto bad_address;
78 
79 		cell->vl_addrs[cell->vl_naddrs++].s_addr =
80 			htonl((a << 24) | (b << 16) | (c << 8) | d);
81 
82 	} while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next));
83 
84 	/* create a key to represent an anonymous user */
85 	memcpy(keyname, "afs@", 4);
86 	dp = keyname + 4;
87 	cp = cell->name;
88 	do {
89 		*dp++ = toupper(*cp);
90 	} while (*cp++);
91 	cell->anonymous_key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current,
92 					KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
93 	if (IS_ERR(cell->anonymous_key)) {
94 		_debug("no key");
95 		ret = PTR_ERR(cell->anonymous_key);
96 		goto error;
97 	}
98 
99 	ret = key_instantiate_and_link(cell->anonymous_key, NULL, 0,
100 				       NULL, NULL);
101 	if (ret < 0) {
102 		_debug("instantiate failed");
103 		goto error;
104 	}
105 
106 	_debug("anon key %p{%x}",
107 	       cell->anonymous_key, key_serial(cell->anonymous_key));
108 
109 	_leave(" = %p", cell);
110 	return cell;
111 
112 bad_address:
113 	printk(KERN_ERR "kAFS: bad VL server IP address\n");
114 	ret = -EINVAL;
115 error:
116 	key_put(cell->anonymous_key);
117 	kfree(cell);
118 	_leave(" = %d", ret);
119 	return ERR_PTR(ret);
120 }
121 
122 /*
123  * create a cell record
124  * - "name" is the name of the cell
125  * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format
126  */
127 struct afs_cell *afs_cell_create(const char *name, char *vllist)
128 {
129 	struct afs_cell *cell;
130 	int ret;
131 
132 	_enter("%s,%s", name, vllist);
133 
134 	cell = afs_cell_alloc(name, vllist);
135 	if (IS_ERR(cell)) {
136 		_leave(" = %ld", PTR_ERR(cell));
137 		return cell;
138 	}
139 
140 	down_write(&afs_cells_sem);
141 
142 	/* add a proc directory for this cell */
143 	ret = afs_proc_cell_setup(cell);
144 	if (ret < 0)
145 		goto error;
146 
147 #ifdef AFS_CACHING_SUPPORT
148 	/* put it up for caching */
149 	cachefs_acquire_cookie(afs_cache_netfs.primary_index,
150 			       &afs_vlocation_cache_index_def,
151 			       cell,
152 			       &cell->cache);
153 #endif
154 
155 	/* add to the cell lists */
156 	write_lock(&afs_cells_lock);
157 	list_add_tail(&cell->link, &afs_cells);
158 	write_unlock(&afs_cells_lock);
159 
160 	down_write(&afs_proc_cells_sem);
161 	list_add_tail(&cell->proc_link, &afs_proc_cells);
162 	up_write(&afs_proc_cells_sem);
163 	up_write(&afs_cells_sem);
164 
165 	_leave(" = %p", cell);
166 	return cell;
167 
168 error:
169 	up_write(&afs_cells_sem);
170 	key_put(cell->anonymous_key);
171 	kfree(cell);
172 	_leave(" = %d", ret);
173 	return ERR_PTR(ret);
174 }
175 
176 /*
177  * set the root cell information
178  * - can be called with a module parameter string
179  * - can be called from a write to /proc/fs/afs/rootcell
180  */
181 int afs_cell_init(char *rootcell)
182 {
183 	struct afs_cell *old_root, *new_root;
184 	char *cp;
185 
186 	_enter("");
187 
188 	if (!rootcell) {
189 		/* module is loaded with no parameters, or built statically.
190 		 * - in the future we might initialize cell DB here.
191 		 */
192 		_leave(" = 0 [no root]");
193 		return 0;
194 	}
195 
196 	cp = strchr(rootcell, ':');
197 	if (!cp) {
198 		printk(KERN_ERR "kAFS: no VL server IP addresses specified\n");
199 		_leave(" = -EINVAL");
200 		return -EINVAL;
201 	}
202 
203 	/* allocate a cell record for the root cell */
204 	*cp++ = 0;
205 	new_root = afs_cell_create(rootcell, cp);
206 	if (IS_ERR(new_root)) {
207 		_leave(" = %ld", PTR_ERR(new_root));
208 		return PTR_ERR(new_root);
209 	}
210 
211 	/* install the new cell */
212 	write_lock(&afs_cells_lock);
213 	old_root = afs_cell_root;
214 	afs_cell_root = new_root;
215 	write_unlock(&afs_cells_lock);
216 	afs_put_cell(old_root);
217 
218 	_leave(" = 0");
219 	return 0;
220 }
221 
222 /*
223  * lookup a cell record
224  */
225 struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz)
226 {
227 	struct afs_cell *cell;
228 
229 	_enter("\"%*.*s\",", namesz, namesz, name ? name : "");
230 
231 	down_read(&afs_cells_sem);
232 	read_lock(&afs_cells_lock);
233 
234 	if (name) {
235 		/* if the cell was named, look for it in the cell record list */
236 		list_for_each_entry(cell, &afs_cells, link) {
237 			if (strncmp(cell->name, name, namesz) == 0) {
238 				afs_get_cell(cell);
239 				goto found;
240 			}
241 		}
242 		cell = ERR_PTR(-ENOENT);
243 	found:
244 		;
245 	} else {
246 		cell = afs_cell_root;
247 		if (!cell) {
248 			/* this should not happen unless user tries to mount
249 			 * when root cell is not set. Return an impossibly
250 			 * bizzare errno to alert the user. Things like
251 			 * ENOENT might be "more appropriate" but they happen
252 			 * for other reasons.
253 			 */
254 			cell = ERR_PTR(-EDESTADDRREQ);
255 		} else {
256 			afs_get_cell(cell);
257 		}
258 
259 	}
260 
261 	read_unlock(&afs_cells_lock);
262 	up_read(&afs_cells_sem);
263 	_leave(" = %p", cell);
264 	return cell;
265 }
266 
267 /*
268  * try and get a cell record
269  */
270 struct afs_cell *afs_get_cell_maybe(struct afs_cell *cell)
271 {
272 	write_lock(&afs_cells_lock);
273 
274 	if (cell && !list_empty(&cell->link))
275 		afs_get_cell(cell);
276 	else
277 		cell = NULL;
278 
279 	write_unlock(&afs_cells_lock);
280 	return cell;
281 }
282 
283 /*
284  * destroy a cell record
285  */
286 void afs_put_cell(struct afs_cell *cell)
287 {
288 	if (!cell)
289 		return;
290 
291 	_enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name);
292 
293 	ASSERTCMP(atomic_read(&cell->usage), >, 0);
294 
295 	/* to prevent a race, the decrement and the dequeue must be effectively
296 	 * atomic */
297 	write_lock(&afs_cells_lock);
298 
299 	if (likely(!atomic_dec_and_test(&cell->usage))) {
300 		write_unlock(&afs_cells_lock);
301 		_leave("");
302 		return;
303 	}
304 
305 	ASSERT(list_empty(&cell->servers));
306 	ASSERT(list_empty(&cell->vl_list));
307 
308 	write_unlock(&afs_cells_lock);
309 
310 	wake_up(&afs_cells_freeable_wq);
311 
312 	_leave(" [unused]");
313 }
314 
315 /*
316  * destroy a cell record
317  * - must be called with the afs_cells_sem write-locked
318  * - cell->link should have been broken by the caller
319  */
320 static void afs_cell_destroy(struct afs_cell *cell)
321 {
322 	_enter("%p{%d,%s}", cell, atomic_read(&cell->usage), cell->name);
323 
324 	ASSERTCMP(atomic_read(&cell->usage), >=, 0);
325 	ASSERT(list_empty(&cell->link));
326 
327 	/* wait for everyone to stop using the cell */
328 	if (atomic_read(&cell->usage) > 0) {
329 		DECLARE_WAITQUEUE(myself, current);
330 
331 		_debug("wait for cell %s", cell->name);
332 		set_current_state(TASK_UNINTERRUPTIBLE);
333 		add_wait_queue(&afs_cells_freeable_wq, &myself);
334 
335 		while (atomic_read(&cell->usage) > 0) {
336 			schedule();
337 			set_current_state(TASK_UNINTERRUPTIBLE);
338 		}
339 
340 		remove_wait_queue(&afs_cells_freeable_wq, &myself);
341 		set_current_state(TASK_RUNNING);
342 	}
343 
344 	_debug("cell dead");
345 	ASSERTCMP(atomic_read(&cell->usage), ==, 0);
346 	ASSERT(list_empty(&cell->servers));
347 	ASSERT(list_empty(&cell->vl_list));
348 
349 	afs_proc_cell_remove(cell);
350 
351 	down_write(&afs_proc_cells_sem);
352 	list_del_init(&cell->proc_link);
353 	up_write(&afs_proc_cells_sem);
354 
355 #ifdef AFS_CACHING_SUPPORT
356 	cachefs_relinquish_cookie(cell->cache, 0);
357 #endif
358 
359 	key_put(cell->anonymous_key);
360 	kfree(cell);
361 
362 	_leave(" [destroyed]");
363 }
364 
365 /*
366  * purge in-memory cell database on module unload or afs_init() failure
367  * - the timeout daemon is stopped before calling this
368  */
369 void afs_cell_purge(void)
370 {
371 	struct afs_cell *cell;
372 
373 	_enter("");
374 
375 	afs_put_cell(afs_cell_root);
376 
377 	down_write(&afs_cells_sem);
378 
379 	while (!list_empty(&afs_cells)) {
380 		cell = NULL;
381 
382 		/* remove the next cell from the front of the list */
383 		write_lock(&afs_cells_lock);
384 
385 		if (!list_empty(&afs_cells)) {
386 			cell = list_entry(afs_cells.next,
387 					  struct afs_cell, link);
388 			list_del_init(&cell->link);
389 		}
390 
391 		write_unlock(&afs_cells_lock);
392 
393 		if (cell) {
394 			_debug("PURGING CELL %s (%d)",
395 			       cell->name, atomic_read(&cell->usage));
396 
397 			/* now the cell should be left with no references */
398 			afs_cell_destroy(cell);
399 		}
400 	}
401 
402 	up_write(&afs_cells_sem);
403 	_leave("");
404 }
405