cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cell.c (23973B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* AFS cell and server record management
      3 *
      4 * Copyright (C) 2002, 2017 Red Hat, Inc. All Rights Reserved.
      5 * Written by David Howells (dhowells@redhat.com)
      6 */
      7
      8#include <linux/slab.h>
      9#include <linux/key.h>
     10#include <linux/ctype.h>
     11#include <linux/dns_resolver.h>
     12#include <linux/sched.h>
     13#include <linux/inet.h>
     14#include <linux/namei.h>
     15#include <keys/rxrpc-type.h>
     16#include "internal.h"
     17
     18static unsigned __read_mostly afs_cell_gc_delay = 10;
     19static unsigned __read_mostly afs_cell_min_ttl = 10 * 60;
     20static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60;
     21static atomic_t cell_debug_id;
     22
     23static void afs_queue_cell_manager(struct afs_net *);
     24static void afs_manage_cell_work(struct work_struct *);
     25
     26static void afs_dec_cells_outstanding(struct afs_net *net)
     27{
     28	if (atomic_dec_and_test(&net->cells_outstanding))
     29		wake_up_var(&net->cells_outstanding);
     30}
     31
     32/*
     33 * Set the cell timer to fire after a given delay, assuming it's not already
     34 * set for an earlier time.
     35 */
     36static void afs_set_cell_timer(struct afs_net *net, time64_t delay)
     37{
     38	if (net->live) {
     39		atomic_inc(&net->cells_outstanding);
     40		if (timer_reduce(&net->cells_timer, jiffies + delay * HZ))
     41			afs_dec_cells_outstanding(net);
     42	} else {
     43		afs_queue_cell_manager(net);
     44	}
     45}
     46
     47/*
     48 * Look up and get an activation reference on a cell record.  The caller must
     49 * hold net->cells_lock at least read-locked.
     50 */
     51static struct afs_cell *afs_find_cell_locked(struct afs_net *net,
     52					     const char *name, unsigned int namesz,
     53					     enum afs_cell_trace reason)
     54{
     55	struct afs_cell *cell = NULL;
     56	struct rb_node *p;
     57	int n;
     58
     59	_enter("%*.*s", namesz, namesz, name);
     60
     61	if (name && namesz == 0)
     62		return ERR_PTR(-EINVAL);
     63	if (namesz > AFS_MAXCELLNAME)
     64		return ERR_PTR(-ENAMETOOLONG);
     65
     66	if (!name) {
     67		cell = net->ws_cell;
     68		if (!cell)
     69			return ERR_PTR(-EDESTADDRREQ);
     70		goto found;
     71	}
     72
     73	p = net->cells.rb_node;
     74	while (p) {
     75		cell = rb_entry(p, struct afs_cell, net_node);
     76
     77		n = strncasecmp(cell->name, name,
     78				min_t(size_t, cell->name_len, namesz));
     79		if (n == 0)
     80			n = cell->name_len - namesz;
     81		if (n < 0)
     82			p = p->rb_left;
     83		else if (n > 0)
     84			p = p->rb_right;
     85		else
     86			goto found;
     87	}
     88
     89	return ERR_PTR(-ENOENT);
     90
     91found:
     92	return afs_use_cell(cell, reason);
     93}
     94
     95/*
     96 * Look up and get an activation reference on a cell record.
     97 */
     98struct afs_cell *afs_find_cell(struct afs_net *net,
     99			       const char *name, unsigned int namesz,
    100			       enum afs_cell_trace reason)
    101{
    102	struct afs_cell *cell;
    103
    104	down_read(&net->cells_lock);
    105	cell = afs_find_cell_locked(net, name, namesz, reason);
    106	up_read(&net->cells_lock);
    107	return cell;
    108}
    109
    110/*
    111 * Set up a cell record and fill in its name, VL server address list and
    112 * allocate an anonymous key
    113 */
    114static struct afs_cell *afs_alloc_cell(struct afs_net *net,
    115				       const char *name, unsigned int namelen,
    116				       const char *addresses)
    117{
    118	struct afs_vlserver_list *vllist;
    119	struct afs_cell *cell;
    120	int i, ret;
    121
    122	ASSERT(name);
    123	if (namelen == 0)
    124		return ERR_PTR(-EINVAL);
    125	if (namelen > AFS_MAXCELLNAME) {
    126		_leave(" = -ENAMETOOLONG");
    127		return ERR_PTR(-ENAMETOOLONG);
    128	}
    129
    130	/* Prohibit cell names that contain unprintable chars, '/' and '@' or
    131	 * that begin with a dot.  This also precludes "@cell".
    132	 */
    133	if (name[0] == '.')
    134		return ERR_PTR(-EINVAL);
    135	for (i = 0; i < namelen; i++) {
    136		char ch = name[i];
    137		if (!isprint(ch) || ch == '/' || ch == '@')
    138			return ERR_PTR(-EINVAL);
    139	}
    140
    141	_enter("%*.*s,%s", namelen, namelen, name, addresses);
    142
    143	cell = kzalloc(sizeof(struct afs_cell), GFP_KERNEL);
    144	if (!cell) {
    145		_leave(" = -ENOMEM");
    146		return ERR_PTR(-ENOMEM);
    147	}
    148
    149	cell->name = kmalloc(namelen + 1, GFP_KERNEL);
    150	if (!cell->name) {
    151		kfree(cell);
    152		return ERR_PTR(-ENOMEM);
    153	}
    154
    155	cell->net = net;
    156	cell->name_len = namelen;
    157	for (i = 0; i < namelen; i++)
    158		cell->name[i] = tolower(name[i]);
    159	cell->name[i] = 0;
    160
    161	atomic_set(&cell->ref, 1);
    162	atomic_set(&cell->active, 0);
    163	INIT_WORK(&cell->manager, afs_manage_cell_work);
    164	cell->volumes = RB_ROOT;
    165	INIT_HLIST_HEAD(&cell->proc_volumes);
    166	seqlock_init(&cell->volume_lock);
    167	cell->fs_servers = RB_ROOT;
    168	seqlock_init(&cell->fs_lock);
    169	INIT_LIST_HEAD(&cell->fs_open_mmaps);
    170	init_rwsem(&cell->fs_open_mmaps_lock);
    171	rwlock_init(&cell->vl_servers_lock);
    172	cell->flags = (1 << AFS_CELL_FL_CHECK_ALIAS);
    173
    174	/* Provide a VL server list, filling it in if we were given a list of
    175	 * addresses to use.
    176	 */
    177	if (addresses) {
    178		vllist = afs_parse_text_addrs(net,
    179					      addresses, strlen(addresses), ':',
    180					      VL_SERVICE, AFS_VL_PORT);
    181		if (IS_ERR(vllist)) {
    182			ret = PTR_ERR(vllist);
    183			goto parse_failed;
    184		}
    185
    186		vllist->source = DNS_RECORD_FROM_CONFIG;
    187		vllist->status = DNS_LOOKUP_NOT_DONE;
    188		cell->dns_expiry = TIME64_MAX;
    189	} else {
    190		ret = -ENOMEM;
    191		vllist = afs_alloc_vlserver_list(0);
    192		if (!vllist)
    193			goto error;
    194		vllist->source = DNS_RECORD_UNAVAILABLE;
    195		vllist->status = DNS_LOOKUP_NOT_DONE;
    196		cell->dns_expiry = ktime_get_real_seconds();
    197	}
    198
    199	rcu_assign_pointer(cell->vl_servers, vllist);
    200
    201	cell->dns_source = vllist->source;
    202	cell->dns_status = vllist->status;
    203	smp_store_release(&cell->dns_lookup_count, 1); /* vs source/status */
    204	atomic_inc(&net->cells_outstanding);
    205	cell->debug_id = atomic_inc_return(&cell_debug_id);
    206	trace_afs_cell(cell->debug_id, 1, 0, afs_cell_trace_alloc);
    207
    208	_leave(" = %p", cell);
    209	return cell;
    210
    211parse_failed:
    212	if (ret == -EINVAL)
    213		printk(KERN_ERR "kAFS: bad VL server IP address\n");
    214error:
    215	kfree(cell->name);
    216	kfree(cell);
    217	_leave(" = %d", ret);
    218	return ERR_PTR(ret);
    219}
    220
    221/*
    222 * afs_lookup_cell - Look up or create a cell record.
    223 * @net:	The network namespace
    224 * @name:	The name of the cell.
    225 * @namesz:	The strlen of the cell name.
    226 * @vllist:	A colon/comma separated list of numeric IP addresses or NULL.
    227 * @excl:	T if an error should be given if the cell name already exists.
    228 *
    229 * Look up a cell record by name and query the DNS for VL server addresses if
    230 * needed.  Note that that actual DNS query is punted off to the manager thread
    231 * so that this function can return immediately if interrupted whilst allowing
    232 * cell records to be shared even if not yet fully constructed.
    233 */
    234struct afs_cell *afs_lookup_cell(struct afs_net *net,
    235				 const char *name, unsigned int namesz,
    236				 const char *vllist, bool excl)
    237{
    238	struct afs_cell *cell, *candidate, *cursor;
    239	struct rb_node *parent, **pp;
    240	enum afs_cell_state state;
    241	int ret, n;
    242
    243	_enter("%s,%s", name, vllist);
    244
    245	if (!excl) {
    246		cell = afs_find_cell(net, name, namesz, afs_cell_trace_use_lookup);
    247		if (!IS_ERR(cell))
    248			goto wait_for_cell;
    249	}
    250
    251	/* Assume we're probably going to create a cell and preallocate and
    252	 * mostly set up a candidate record.  We can then use this to stash the
    253	 * name, the net namespace and VL server addresses.
    254	 *
    255	 * We also want to do this before we hold any locks as it may involve
    256	 * upcalling to userspace to make DNS queries.
    257	 */
    258	candidate = afs_alloc_cell(net, name, namesz, vllist);
    259	if (IS_ERR(candidate)) {
    260		_leave(" = %ld", PTR_ERR(candidate));
    261		return candidate;
    262	}
    263
    264	/* Find the insertion point and check to see if someone else added a
    265	 * cell whilst we were allocating.
    266	 */
    267	down_write(&net->cells_lock);
    268
    269	pp = &net->cells.rb_node;
    270	parent = NULL;
    271	while (*pp) {
    272		parent = *pp;
    273		cursor = rb_entry(parent, struct afs_cell, net_node);
    274
    275		n = strncasecmp(cursor->name, name,
    276				min_t(size_t, cursor->name_len, namesz));
    277		if (n == 0)
    278			n = cursor->name_len - namesz;
    279		if (n < 0)
    280			pp = &(*pp)->rb_left;
    281		else if (n > 0)
    282			pp = &(*pp)->rb_right;
    283		else
    284			goto cell_already_exists;
    285	}
    286
    287	cell = candidate;
    288	candidate = NULL;
    289	atomic_set(&cell->active, 2);
    290	trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 2, afs_cell_trace_insert);
    291	rb_link_node_rcu(&cell->net_node, parent, pp);
    292	rb_insert_color(&cell->net_node, &net->cells);
    293	up_write(&net->cells_lock);
    294
    295	afs_queue_cell(cell, afs_cell_trace_get_queue_new);
    296
    297wait_for_cell:
    298	trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), atomic_read(&cell->active),
    299		       afs_cell_trace_wait);
    300	_debug("wait_for_cell");
    301	wait_var_event(&cell->state,
    302		       ({
    303			       state = smp_load_acquire(&cell->state); /* vs error */
    304			       state == AFS_CELL_ACTIVE || state == AFS_CELL_REMOVED;
    305		       }));
    306
    307	/* Check the state obtained from the wait check. */
    308	if (state == AFS_CELL_REMOVED) {
    309		ret = cell->error;
    310		goto error;
    311	}
    312
    313	_leave(" = %p [cell]", cell);
    314	return cell;
    315
    316cell_already_exists:
    317	_debug("cell exists");
    318	cell = cursor;
    319	if (excl) {
    320		ret = -EEXIST;
    321	} else {
    322		afs_use_cell(cursor, afs_cell_trace_use_lookup);
    323		ret = 0;
    324	}
    325	up_write(&net->cells_lock);
    326	if (candidate)
    327		afs_put_cell(candidate, afs_cell_trace_put_candidate);
    328	if (ret == 0)
    329		goto wait_for_cell;
    330	goto error_noput;
    331error:
    332	afs_unuse_cell(net, cell, afs_cell_trace_unuse_lookup);
    333error_noput:
    334	_leave(" = %d [error]", ret);
    335	return ERR_PTR(ret);
    336}
    337
    338/*
    339 * set the root cell information
    340 * - can be called with a module parameter string
    341 * - can be called from a write to /proc/fs/afs/rootcell
    342 */
    343int afs_cell_init(struct afs_net *net, const char *rootcell)
    344{
    345	struct afs_cell *old_root, *new_root;
    346	const char *cp, *vllist;
    347	size_t len;
    348
    349	_enter("");
    350
    351	if (!rootcell) {
    352		/* module is loaded with no parameters, or built statically.
    353		 * - in the future we might initialize cell DB here.
    354		 */
    355		_leave(" = 0 [no root]");
    356		return 0;
    357	}
    358
    359	cp = strchr(rootcell, ':');
    360	if (!cp) {
    361		_debug("kAFS: no VL server IP addresses specified");
    362		vllist = NULL;
    363		len = strlen(rootcell);
    364	} else {
    365		vllist = cp + 1;
    366		len = cp - rootcell;
    367	}
    368
    369	/* allocate a cell record for the root cell */
    370	new_root = afs_lookup_cell(net, rootcell, len, vllist, false);
    371	if (IS_ERR(new_root)) {
    372		_leave(" = %ld", PTR_ERR(new_root));
    373		return PTR_ERR(new_root);
    374	}
    375
    376	if (!test_and_set_bit(AFS_CELL_FL_NO_GC, &new_root->flags))
    377		afs_use_cell(new_root, afs_cell_trace_use_pin);
    378
    379	/* install the new cell */
    380	down_write(&net->cells_lock);
    381	afs_see_cell(new_root, afs_cell_trace_see_ws);
    382	old_root = net->ws_cell;
    383	net->ws_cell = new_root;
    384	up_write(&net->cells_lock);
    385
    386	afs_unuse_cell(net, old_root, afs_cell_trace_unuse_ws);
    387	_leave(" = 0");
    388	return 0;
    389}
    390
    391/*
    392 * Update a cell's VL server address list from the DNS.
    393 */
    394static int afs_update_cell(struct afs_cell *cell)
    395{
    396	struct afs_vlserver_list *vllist, *old = NULL, *p;
    397	unsigned int min_ttl = READ_ONCE(afs_cell_min_ttl);
    398	unsigned int max_ttl = READ_ONCE(afs_cell_max_ttl);
    399	time64_t now, expiry = 0;
    400	int ret = 0;
    401
    402	_enter("%s", cell->name);
    403
    404	vllist = afs_dns_query(cell, &expiry);
    405	if (IS_ERR(vllist)) {
    406		ret = PTR_ERR(vllist);
    407
    408		_debug("%s: fail %d", cell->name, ret);
    409		if (ret == -ENOMEM)
    410			goto out_wake;
    411
    412		ret = -ENOMEM;
    413		vllist = afs_alloc_vlserver_list(0);
    414		if (!vllist)
    415			goto out_wake;
    416
    417		switch (ret) {
    418		case -ENODATA:
    419		case -EDESTADDRREQ:
    420			vllist->status = DNS_LOOKUP_GOT_NOT_FOUND;
    421			break;
    422		case -EAGAIN:
    423		case -ECONNREFUSED:
    424			vllist->status = DNS_LOOKUP_GOT_TEMP_FAILURE;
    425			break;
    426		default:
    427			vllist->status = DNS_LOOKUP_GOT_LOCAL_FAILURE;
    428			break;
    429		}
    430	}
    431
    432	_debug("%s: got list %d %d", cell->name, vllist->source, vllist->status);
    433	cell->dns_status = vllist->status;
    434
    435	now = ktime_get_real_seconds();
    436	if (min_ttl > max_ttl)
    437		max_ttl = min_ttl;
    438	if (expiry < now + min_ttl)
    439		expiry = now + min_ttl;
    440	else if (expiry > now + max_ttl)
    441		expiry = now + max_ttl;
    442
    443	_debug("%s: status %d", cell->name, vllist->status);
    444	if (vllist->source == DNS_RECORD_UNAVAILABLE) {
    445		switch (vllist->status) {
    446		case DNS_LOOKUP_GOT_NOT_FOUND:
    447			/* The DNS said that the cell does not exist or there
    448			 * weren't any addresses to be had.
    449			 */
    450			cell->dns_expiry = expiry;
    451			break;
    452
    453		case DNS_LOOKUP_BAD:
    454		case DNS_LOOKUP_GOT_LOCAL_FAILURE:
    455		case DNS_LOOKUP_GOT_TEMP_FAILURE:
    456		case DNS_LOOKUP_GOT_NS_FAILURE:
    457		default:
    458			cell->dns_expiry = now + 10;
    459			break;
    460		}
    461	} else {
    462		cell->dns_expiry = expiry;
    463	}
    464
    465	/* Replace the VL server list if the new record has servers or the old
    466	 * record doesn't.
    467	 */
    468	write_lock(&cell->vl_servers_lock);
    469	p = rcu_dereference_protected(cell->vl_servers, true);
    470	if (vllist->nr_servers > 0 || p->nr_servers == 0) {
    471		rcu_assign_pointer(cell->vl_servers, vllist);
    472		cell->dns_source = vllist->source;
    473		old = p;
    474	}
    475	write_unlock(&cell->vl_servers_lock);
    476	afs_put_vlserverlist(cell->net, old);
    477
    478out_wake:
    479	smp_store_release(&cell->dns_lookup_count,
    480			  cell->dns_lookup_count + 1); /* vs source/status */
    481	wake_up_var(&cell->dns_lookup_count);
    482	_leave(" = %d", ret);
    483	return ret;
    484}
    485
    486/*
    487 * Destroy a cell record
    488 */
    489static void afs_cell_destroy(struct rcu_head *rcu)
    490{
    491	struct afs_cell *cell = container_of(rcu, struct afs_cell, rcu);
    492	struct afs_net *net = cell->net;
    493	int u;
    494
    495	_enter("%p{%s}", cell, cell->name);
    496
    497	u = atomic_read(&cell->ref);
    498	ASSERTCMP(u, ==, 0);
    499	trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), afs_cell_trace_free);
    500
    501	afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers));
    502	afs_unuse_cell(net, cell->alias_of, afs_cell_trace_unuse_alias);
    503	key_put(cell->anonymous_key);
    504	kfree(cell->name);
    505	kfree(cell);
    506
    507	afs_dec_cells_outstanding(net);
    508	_leave(" [destroyed]");
    509}
    510
    511/*
    512 * Queue the cell manager.
    513 */
    514static void afs_queue_cell_manager(struct afs_net *net)
    515{
    516	int outstanding = atomic_inc_return(&net->cells_outstanding);
    517
    518	_enter("%d", outstanding);
    519
    520	if (!queue_work(afs_wq, &net->cells_manager))
    521		afs_dec_cells_outstanding(net);
    522}
    523
    524/*
    525 * Cell management timer.  We have an increment on cells_outstanding that we
    526 * need to pass along to the work item.
    527 */
    528void afs_cells_timer(struct timer_list *timer)
    529{
    530	struct afs_net *net = container_of(timer, struct afs_net, cells_timer);
    531
    532	_enter("");
    533	if (!queue_work(afs_wq, &net->cells_manager))
    534		afs_dec_cells_outstanding(net);
    535}
    536
    537/*
    538 * Get a reference on a cell record.
    539 */
    540struct afs_cell *afs_get_cell(struct afs_cell *cell, enum afs_cell_trace reason)
    541{
    542	int u;
    543
    544	if (atomic_read(&cell->ref) <= 0)
    545		BUG();
    546
    547	u = atomic_inc_return(&cell->ref);
    548	trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), reason);
    549	return cell;
    550}
    551
    552/*
    553 * Drop a reference on a cell record.
    554 */
    555void afs_put_cell(struct afs_cell *cell, enum afs_cell_trace reason)
    556{
    557	if (cell) {
    558		unsigned int debug_id = cell->debug_id;
    559		unsigned int u, a;
    560
    561		a = atomic_read(&cell->active);
    562		u = atomic_dec_return(&cell->ref);
    563		trace_afs_cell(debug_id, u, a, reason);
    564		if (u == 0) {
    565			a = atomic_read(&cell->active);
    566			WARN(a != 0, "Cell active count %u > 0\n", a);
    567			call_rcu(&cell->rcu, afs_cell_destroy);
    568		}
    569	}
    570}
    571
    572/*
    573 * Note a cell becoming more active.
    574 */
    575struct afs_cell *afs_use_cell(struct afs_cell *cell, enum afs_cell_trace reason)
    576{
    577	int u, a;
    578
    579	if (atomic_read(&cell->ref) <= 0)
    580		BUG();
    581
    582	u = atomic_read(&cell->ref);
    583	a = atomic_inc_return(&cell->active);
    584	trace_afs_cell(cell->debug_id, u, a, reason);
    585	return cell;
    586}
    587
    588/*
    589 * Record a cell becoming less active.  When the active counter reaches 1, it
    590 * is scheduled for destruction, but may get reactivated.
    591 */
    592void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_trace reason)
    593{
    594	unsigned int debug_id;
    595	time64_t now, expire_delay;
    596	int u, a;
    597
    598	if (!cell)
    599		return;
    600
    601	_enter("%s", cell->name);
    602
    603	now = ktime_get_real_seconds();
    604	cell->last_inactive = now;
    605	expire_delay = 0;
    606	if (cell->vl_servers->nr_servers)
    607		expire_delay = afs_cell_gc_delay;
    608
    609	debug_id = cell->debug_id;
    610	u = atomic_read(&cell->ref);
    611	a = atomic_dec_return(&cell->active);
    612	trace_afs_cell(debug_id, u, a, reason);
    613	WARN_ON(a == 0);
    614	if (a == 1)
    615		/* 'cell' may now be garbage collected. */
    616		afs_set_cell_timer(net, expire_delay);
    617}
    618
    619/*
    620 * Note that a cell has been seen.
    621 */
    622void afs_see_cell(struct afs_cell *cell, enum afs_cell_trace reason)
    623{
    624	int u, a;
    625
    626	u = atomic_read(&cell->ref);
    627	a = atomic_read(&cell->active);
    628	trace_afs_cell(cell->debug_id, u, a, reason);
    629}
    630
    631/*
    632 * Queue a cell for management, giving the workqueue a ref to hold.
    633 */
    634void afs_queue_cell(struct afs_cell *cell, enum afs_cell_trace reason)
    635{
    636	afs_get_cell(cell, reason);
    637	if (!queue_work(afs_wq, &cell->manager))
    638		afs_put_cell(cell, afs_cell_trace_put_queue_fail);
    639}
    640
    641/*
    642 * Allocate a key to use as a placeholder for anonymous user security.
    643 */
    644static int afs_alloc_anon_key(struct afs_cell *cell)
    645{
    646	struct key *key;
    647	char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp;
    648
    649	/* Create a key to represent an anonymous user. */
    650	memcpy(keyname, "afs@", 4);
    651	dp = keyname + 4;
    652	cp = cell->name;
    653	do {
    654		*dp++ = tolower(*cp);
    655	} while (*cp++);
    656
    657	key = rxrpc_get_null_key(keyname);
    658	if (IS_ERR(key))
    659		return PTR_ERR(key);
    660
    661	cell->anonymous_key = key;
    662
    663	_debug("anon key %p{%x}",
    664	       cell->anonymous_key, key_serial(cell->anonymous_key));
    665	return 0;
    666}
    667
    668/*
    669 * Activate a cell.
    670 */
    671static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell)
    672{
    673	struct hlist_node **p;
    674	struct afs_cell *pcell;
    675	int ret;
    676
    677	if (!cell->anonymous_key) {
    678		ret = afs_alloc_anon_key(cell);
    679		if (ret < 0)
    680			return ret;
    681	}
    682
    683	ret = afs_proc_cell_setup(cell);
    684	if (ret < 0)
    685		return ret;
    686
    687	mutex_lock(&net->proc_cells_lock);
    688	for (p = &net->proc_cells.first; *p; p = &(*p)->next) {
    689		pcell = hlist_entry(*p, struct afs_cell, proc_link);
    690		if (strcmp(cell->name, pcell->name) < 0)
    691			break;
    692	}
    693
    694	cell->proc_link.pprev = p;
    695	cell->proc_link.next = *p;
    696	rcu_assign_pointer(*p, &cell->proc_link.next);
    697	if (cell->proc_link.next)
    698		cell->proc_link.next->pprev = &cell->proc_link.next;
    699
    700	afs_dynroot_mkdir(net, cell);
    701	mutex_unlock(&net->proc_cells_lock);
    702	return 0;
    703}
    704
    705/*
    706 * Deactivate a cell.
    707 */
    708static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell)
    709{
    710	_enter("%s", cell->name);
    711
    712	afs_proc_cell_remove(cell);
    713
    714	mutex_lock(&net->proc_cells_lock);
    715	hlist_del_rcu(&cell->proc_link);
    716	afs_dynroot_rmdir(net, cell);
    717	mutex_unlock(&net->proc_cells_lock);
    718
    719	_leave("");
    720}
    721
    722/*
    723 * Manage a cell record, initialising and destroying it, maintaining its DNS
    724 * records.
    725 */
    726static void afs_manage_cell(struct afs_cell *cell)
    727{
    728	struct afs_net *net = cell->net;
    729	int ret, active;
    730
    731	_enter("%s", cell->name);
    732
    733again:
    734	_debug("state %u", cell->state);
    735	switch (cell->state) {
    736	case AFS_CELL_INACTIVE:
    737	case AFS_CELL_FAILED:
    738		down_write(&net->cells_lock);
    739		active = 1;
    740		if (atomic_try_cmpxchg_relaxed(&cell->active, &active, 0)) {
    741			rb_erase(&cell->net_node, &net->cells);
    742			trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 0,
    743				       afs_cell_trace_unuse_delete);
    744			smp_store_release(&cell->state, AFS_CELL_REMOVED);
    745		}
    746		up_write(&net->cells_lock);
    747		if (cell->state == AFS_CELL_REMOVED) {
    748			wake_up_var(&cell->state);
    749			goto final_destruction;
    750		}
    751		if (cell->state == AFS_CELL_FAILED)
    752			goto done;
    753		smp_store_release(&cell->state, AFS_CELL_UNSET);
    754		wake_up_var(&cell->state);
    755		goto again;
    756
    757	case AFS_CELL_UNSET:
    758		smp_store_release(&cell->state, AFS_CELL_ACTIVATING);
    759		wake_up_var(&cell->state);
    760		goto again;
    761
    762	case AFS_CELL_ACTIVATING:
    763		ret = afs_activate_cell(net, cell);
    764		if (ret < 0)
    765			goto activation_failed;
    766
    767		smp_store_release(&cell->state, AFS_CELL_ACTIVE);
    768		wake_up_var(&cell->state);
    769		goto again;
    770
    771	case AFS_CELL_ACTIVE:
    772		if (atomic_read(&cell->active) > 1) {
    773			if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) {
    774				ret = afs_update_cell(cell);
    775				if (ret < 0)
    776					cell->error = ret;
    777			}
    778			goto done;
    779		}
    780		smp_store_release(&cell->state, AFS_CELL_DEACTIVATING);
    781		wake_up_var(&cell->state);
    782		goto again;
    783
    784	case AFS_CELL_DEACTIVATING:
    785		if (atomic_read(&cell->active) > 1)
    786			goto reverse_deactivation;
    787		afs_deactivate_cell(net, cell);
    788		smp_store_release(&cell->state, AFS_CELL_INACTIVE);
    789		wake_up_var(&cell->state);
    790		goto again;
    791
    792	case AFS_CELL_REMOVED:
    793		goto done;
    794
    795	default:
    796		break;
    797	}
    798	_debug("bad state %u", cell->state);
    799	BUG(); /* Unhandled state */
    800
    801activation_failed:
    802	cell->error = ret;
    803	afs_deactivate_cell(net, cell);
    804
    805	smp_store_release(&cell->state, AFS_CELL_FAILED); /* vs error */
    806	wake_up_var(&cell->state);
    807	goto again;
    808
    809reverse_deactivation:
    810	smp_store_release(&cell->state, AFS_CELL_ACTIVE);
    811	wake_up_var(&cell->state);
    812	_leave(" [deact->act]");
    813	return;
    814
    815done:
    816	_leave(" [done %u]", cell->state);
    817	return;
    818
    819final_destruction:
    820	/* The root volume is pinning the cell */
    821	afs_put_volume(cell->net, cell->root_volume, afs_volume_trace_put_cell_root);
    822	cell->root_volume = NULL;
    823	afs_put_cell(cell, afs_cell_trace_put_destroy);
    824}
    825
    826static void afs_manage_cell_work(struct work_struct *work)
    827{
    828	struct afs_cell *cell = container_of(work, struct afs_cell, manager);
    829
    830	afs_manage_cell(cell);
    831	afs_put_cell(cell, afs_cell_trace_put_queue_work);
    832}
    833
    834/*
    835 * Manage the records of cells known to a network namespace.  This includes
    836 * updating the DNS records and garbage collecting unused cells that were
    837 * automatically added.
    838 *
    839 * Note that constructed cell records may only be removed from net->cells by
    840 * this work item, so it is safe for this work item to stash a cursor pointing
    841 * into the tree and then return to caller (provided it skips cells that are
    842 * still under construction).
    843 *
    844 * Note also that we were given an increment on net->cells_outstanding by
    845 * whoever queued us that we need to deal with before returning.
    846 */
    847void afs_manage_cells(struct work_struct *work)
    848{
    849	struct afs_net *net = container_of(work, struct afs_net, cells_manager);
    850	struct rb_node *cursor;
    851	time64_t now = ktime_get_real_seconds(), next_manage = TIME64_MAX;
    852	bool purging = !net->live;
    853
    854	_enter("");
    855
    856	/* Trawl the cell database looking for cells that have expired from
    857	 * lack of use and cells whose DNS results have expired and dispatch
    858	 * their managers.
    859	 */
    860	down_read(&net->cells_lock);
    861
    862	for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) {
    863		struct afs_cell *cell =
    864			rb_entry(cursor, struct afs_cell, net_node);
    865		unsigned active;
    866		bool sched_cell = false;
    867
    868		active = atomic_read(&cell->active);
    869		trace_afs_cell(cell->debug_id, atomic_read(&cell->ref),
    870			       active, afs_cell_trace_manage);
    871
    872		ASSERTCMP(active, >=, 1);
    873
    874		if (purging) {
    875			if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags)) {
    876				active = atomic_dec_return(&cell->active);
    877				trace_afs_cell(cell->debug_id, atomic_read(&cell->ref),
    878					       active, afs_cell_trace_unuse_pin);
    879			}
    880		}
    881
    882		if (active == 1) {
    883			struct afs_vlserver_list *vllist;
    884			time64_t expire_at = cell->last_inactive;
    885
    886			read_lock(&cell->vl_servers_lock);
    887			vllist = rcu_dereference_protected(
    888				cell->vl_servers,
    889				lockdep_is_held(&cell->vl_servers_lock));
    890			if (vllist->nr_servers > 0)
    891				expire_at += afs_cell_gc_delay;
    892			read_unlock(&cell->vl_servers_lock);
    893			if (purging || expire_at <= now)
    894				sched_cell = true;
    895			else if (expire_at < next_manage)
    896				next_manage = expire_at;
    897		}
    898
    899		if (!purging) {
    900			if (test_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags))
    901				sched_cell = true;
    902		}
    903
    904		if (sched_cell)
    905			afs_queue_cell(cell, afs_cell_trace_get_queue_manage);
    906	}
    907
    908	up_read(&net->cells_lock);
    909
    910	/* Update the timer on the way out.  We have to pass an increment on
    911	 * cells_outstanding in the namespace that we are in to the timer or
    912	 * the work scheduler.
    913	 */
    914	if (!purging && next_manage < TIME64_MAX) {
    915		now = ktime_get_real_seconds();
    916
    917		if (next_manage - now <= 0) {
    918			if (queue_work(afs_wq, &net->cells_manager))
    919				atomic_inc(&net->cells_outstanding);
    920		} else {
    921			afs_set_cell_timer(net, next_manage - now);
    922		}
    923	}
    924
    925	afs_dec_cells_outstanding(net);
    926	_leave(" [%d]", atomic_read(&net->cells_outstanding));
    927}
    928
    929/*
    930 * Purge in-memory cell database.
    931 */
    932void afs_cell_purge(struct afs_net *net)
    933{
    934	struct afs_cell *ws;
    935
    936	_enter("");
    937
    938	down_write(&net->cells_lock);
    939	ws = net->ws_cell;
    940	net->ws_cell = NULL;
    941	up_write(&net->cells_lock);
    942	afs_unuse_cell(net, ws, afs_cell_trace_unuse_ws);
    943
    944	_debug("del timer");
    945	if (del_timer_sync(&net->cells_timer))
    946		atomic_dec(&net->cells_outstanding);
    947
    948	_debug("kick mgr");
    949	afs_queue_cell_manager(net);
    950
    951	_debug("wait");
    952	wait_var_event(&net->cells_outstanding,
    953		       !atomic_read(&net->cells_outstanding));
    954	_leave("");
    955}