Commit 6dfdf536 authored by David Howells's avatar David Howells
Browse files

afs: Detect cell aliases 3 - YFS Cells with a canonical cell name op



YFS Volume Location servers have an operation by which the cell name may be
queried.  Use this to find out what a YFS server thinks the canonical cell
name should be.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 6ef350b1
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
@@ -268,12 +268,70 @@ static int afs_query_for_alias(struct afs_cell *cell, struct key *key)
	return 1;
}

/*
 * Look up a VLDB record for a volume.
 */
static char *afs_vl_get_cell_name(struct afs_cell *cell, struct key *key)
{
	struct afs_vl_cursor vc;
	char *cell_name = ERR_PTR(-EDESTADDRREQ);
	bool skipped = false, not_skipped = false;
	int ret;

	if (!afs_begin_vlserver_operation(&vc, cell, key))
		return ERR_PTR(-ERESTARTSYS);

	while (afs_select_vlserver(&vc)) {
		if (!test_bit(AFS_VLSERVER_FL_IS_YFS, &vc.server->flags)) {
			vc.ac.error = -EOPNOTSUPP;
			skipped = true;
			continue;
		}
		not_skipped = true;
		cell_name = afs_yfsvl_get_cell_name(&vc);
	}

	ret = afs_end_vlserver_operation(&vc);
	if (skipped && !not_skipped)
		ret = -EOPNOTSUPP;
	return ret < 0 ? ERR_PTR(ret) : cell_name;
}

static int yfs_check_canonical_cell_name(struct afs_cell *cell, struct key *key)
{
	struct afs_cell *master;
	char *cell_name;

	cell_name = afs_vl_get_cell_name(cell, key);
	if (IS_ERR(cell_name))
		return PTR_ERR(cell_name);

	if (strcmp(cell_name, cell->name) == 0) {
		kfree(cell_name);
		return 0;
	}

	master = afs_lookup_cell(cell->net, cell_name, strlen(cell_name),
				 NULL, false);
	kfree(cell_name);
	if (IS_ERR(master))
		return PTR_ERR(master);

	cell->alias_of = master; /* Transfer our ref */
	return 1;
}

static int afs_do_cell_detect_alias(struct afs_cell *cell, struct key *key)
{
	struct afs_volume *root_volume;
	int ret;

	_enter("%s", cell->name);

	ret = yfs_check_canonical_cell_name(cell, key);
	if (ret != -EOPNOTSUPP)
		return ret;

	/* Try and get the root.cell volume for comparison with other cells */
	root_volume = afs_sample_volume(cell, key, "root.cell", 9);
	if (!IS_ERR(root_volume)) {
+4 −0
Original line number Diff line number Diff line
@@ -151,6 +151,10 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
		vc->error = error;
		vc->flags |= AFS_VL_CURSOR_RETRY;
		goto next_server;

	case -EOPNOTSUPP:
		_debug("notsupp");
		goto next_server;
	}

restart_from_beginning: