// SPDX-License-Identifier: GPL-2.0-or-later
/* AFS fileserver list management.
 *
 * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include "internal.h"

void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist)
{
	int i;

	if (slist && refcount_dec_and_test(&slist->usage)) {
		for (i = 0; i < slist->nr_servers; i++)
			afs_unuse_server(net, slist->servers[i].server,
					 afs_server_trace_unuse_slist);
		kfree_rcu(slist, rcu);
	}
}

/*
 * Build a server list from a VLDB record.
 */
struct afs_server_list *afs_alloc_server_list(struct afs_volume *volume,
					      struct key *key,
					      struct afs_vldb_entry *vldb)
{
	struct afs_server_list *slist;
	struct afs_server *server;
	unsigned int type_mask = 1 << volume->type;
	bool use_newrepsites = false;
	int ret = -ENOMEM, nr_servers = 0, newrep = 0, i, j, usable = 0;

	/* Work out if we're going to restrict to NEWREPSITE-marked servers or
	 * not.  If at least one site is marked as NEWREPSITE, then it's likely
	 * that "vos release" is busy updating RO sites.  We cut over from one
	 * to the other when >=50% of the sites have been updated.  Sites that
	 * are in the process of being updated are marked DONTUSE.
	 */
	for (i = 0; i < vldb->nr_servers; i++) {
		if (!(vldb->fs_mask[i] & type_mask))
			continue;
		nr_servers++;
		if (vldb->vlsf_flags[i] & AFS_VLSF_DONTUSE)
			continue;
		usable++;
		if (vldb->vlsf_flags[i] & AFS_VLSF_NEWREPSITE)
			newrep++;
	}

	slist = kzalloc_flex(*slist, servers, nr_servers);
	if (!slist)
		goto error;

	if (newrep) {
		if (newrep < usable / 2) {
			slist->ro_replicating = AFS_RO_REPLICATING_USE_OLD;
		} else {
			slist->ro_replicating = AFS_RO_REPLICATING_USE_NEW;
			use_newrepsites = true;
		}
	}

	refcount_set(&slist->usage, 1);
	rwlock_init(&slist->lock);

	/* Make sure a records exists for each server in the list. */
	for (i = 0; i < vldb->nr_servers; i++) {
		unsigned long se_flags = 0;
		bool newrepsite = vldb->vlsf_flags[i] & AFS_VLSF_NEWREPSITE;

		if (!(vldb->fs_mask[i] & type_mask))
			continue;
		if (vldb->vlsf_flags[i] & AFS_VLSF_DONTUSE)
			__set_bit(AFS_SE_EXCLUDED, &se_flags);
		if (newrep && (newrepsite ^ use_newrepsites))
			__set_bit(AFS_SE_EXCLUDED, &se_flags);

		server = afs_lookup_server(volume->cell, key, &vldb->fs_server[i],
					   vldb->addr_version[i]);
		if (IS_ERR(server)) {
			ret = PTR_ERR(server);
			if (ret == -ENOENT ||
			    ret == -ENOMEDIUM)
				continue;
			goto error_2;
		}

		/* Insertion-sort by UUID */
		for (j = 0; j < slist->nr_servers; j++)
			if (memcmp(&slist->servers[j].server->uuid,
				   &server->uuid,
				   sizeof(server->uuid)) >= 0)
				break;
		if (j < slist->nr_servers) {
			if (slist->servers[j].server == server) {
				afs_unuse_server_notime(volume->cell->net, server,
							afs_server_trace_unuse_slist_isort);
				continue;
			}

			memmove(slist->servers + j + 1,
				slist->servers + j,
				(slist->nr_servers - j) * sizeof(struct afs_server_entry));
		}

		slist->servers[j].server = server;
		slist->servers[j].volume = volume;
		slist->servers[j].flags = se_flags;
		slist->servers[j].cb_expires_at = AFS_NO_CB_PROMISE;
		slist->nr_servers++;
	}

	if (slist->nr_servers == 0) {
		ret = -EDESTADDRREQ;
		goto error_2;
	}

	return slist;

error_2:
	afs_put_serverlist(volume->cell->net, slist);
error:
	return ERR_PTR(ret);
}

/*
 * Copy the annotations from an old server list to its potential replacement.
 */
bool afs_annotate_server_list(struct afs_server_list *new,
			      struct afs_server_list *old)
{
	unsigned long mask = 1UL << AFS_SE_EXCLUDED;
	int i;

	if (old->nr_servers != new->nr_servers ||
	    old->ro_replicating != new->ro_replicating)
		goto changed;

	for (i = 0; i < old->nr_servers; i++) {
		if (old->servers[i].server != new->servers[i].server)
			goto changed;
		if ((old->servers[i].flags & mask) != (new->servers[i].flags & mask))
			goto changed;
	}
	return false;
changed:
	return true;
}

/*
 * Attach a volume to the servers it is going to use.
 */
void afs_attach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *slist)
{
	struct afs_server_entry *se, *pe;
	struct afs_server *server;
	struct list_head *p;
	unsigned int i;

	down_write(&volume->cell->vs_lock);

	for (i = 0; i < slist->nr_servers; i++) {
		se = &slist->servers[i];
		server = se->server;

		list_for_each(p, &server->volumes) {
			pe = list_entry(p, struct afs_server_entry, slink);
			if (volume->vid <= pe->volume->vid)
				break;
		}
		list_add_tail(&se->slink, p);
	}

	slist->attached = true;
	up_write(&volume->cell->vs_lock);
}

/*
 * Reattach a volume to the servers it is going to use when server list is
 * replaced.  We try to switch the attachment points to avoid rewalking the
 * lists.
 */
void afs_reattach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *new,
				    struct afs_server_list *old)
{
	unsigned int n = 0, o = 0;

	down_write(&volume->cell->vs_lock);

	while (n < new->nr_servers || o < old->nr_servers) {
		struct afs_server_entry *pn = n < new->nr_servers ? &new->servers[n] : NULL;
		struct afs_server_entry *po = o < old->nr_servers ? &old->servers[o] : NULL;
		struct afs_server_entry *s;
		struct list_head *p;
		int diff;

		if (pn && po && pn->server == po->server) {
			pn->cb_expires_at = po->cb_expires_at;
			list_replace(&po->slink, &pn->slink);
			n++;
			o++;
			continue;
		}

		if (pn && po)
			diff = memcmp(&pn->server->uuid, &po->server->uuid,
				      sizeof(pn->server->uuid));
		else
			diff = pn ? -1 : 1;

		if (diff < 0) {
			list_for_each(p, &pn->server->volumes) {
				s = list_entry(p, struct afs_server_entry, slink);
				if (volume->vid <= s->volume->vid)
					break;
			}
			list_add_tail(&pn->slink, p);
			n++;
		} else {
			list_del(&po->slink);
			o++;
		}
	}

	up_write(&volume->cell->vs_lock);
}

/*
 * Detach a volume from the servers it has been using.
 */
void afs_detach_volume_from_servers(struct afs_volume *volume, struct afs_server_list *slist)
{
	unsigned int i;

	if (!slist->attached)
		return;

	down_write(&volume->cell->vs_lock);

	for (i = 0; i < slist->nr_servers; i++)
		list_del(&slist->servers[i].slink);

	slist->attached = false;
	up_write(&volume->cell->vs_lock);
}
