brintos

brintos / linux-shallow public Read only

0
0
Text · 19.4 KiB · cac75f8 Raw
793 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* AFS Volume Location Service client3 *4 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.5 * Written by David Howells (dhowells@redhat.com)6 */7 8#include <linux/gfp.h>9#include <linux/init.h>10#include <linux/sched.h>11#include "afs_fs.h"12#include "internal.h"13 14/*15 * Deliver reply data to a VL.GetEntryByNameU call.16 */17static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)18{19	struct afs_uvldbentry__xdr *uvldb;20	struct afs_vldb_entry *entry;21	u32 nr_servers, vlflags;22	int i, ret;23 24	_enter("");25 26	ret = afs_transfer_reply(call);27	if (ret < 0)28		return ret;29 30	/* unmarshall the reply once we've received all of it */31	uvldb = call->buffer;32	entry = call->ret_vldb;33 34	nr_servers = ntohl(uvldb->nServers);35	if (nr_servers > AFS_NMAXNSERVERS)36		nr_servers = AFS_NMAXNSERVERS;37 38	for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++)39		entry->name[i] = (u8)ntohl(uvldb->name[i]);40	entry->name[i] = 0;41	entry->name_len = strlen(entry->name);42 43	vlflags = ntohl(uvldb->flags);44	for (i = 0; i < nr_servers; i++) {45		struct afs_uuid__xdr *xdr;46		struct afs_uuid *uuid;47		u32 tmp = ntohl(uvldb->serverFlags[i]);48		int j;49		int n = entry->nr_servers;50 51		if (tmp & AFS_VLSF_RWVOL) {52			entry->fs_mask[n] |= AFS_VOL_VTM_RW;53			if (vlflags & AFS_VLF_BACKEXISTS)54				entry->fs_mask[n] |= AFS_VOL_VTM_BAK;55		}56		if (tmp & AFS_VLSF_ROVOL)57			entry->fs_mask[n] |= AFS_VOL_VTM_RO;58		if (!entry->fs_mask[n])59			continue;60 61		xdr = &uvldb->serverNumber[i];62		uuid = (struct afs_uuid *)&entry->fs_server[n];63		uuid->time_low			= xdr->time_low;64		uuid->time_mid			= htons(ntohl(xdr->time_mid));65		uuid->time_hi_and_version	= htons(ntohl(xdr->time_hi_and_version));66		uuid->clock_seq_hi_and_reserved	= (u8)ntohl(xdr->clock_seq_hi_and_reserved);67		uuid->clock_seq_low		= (u8)ntohl(xdr->clock_seq_low);68		for (j = 0; j < 6; j++)69			uuid->node[j] = (u8)ntohl(xdr->node[j]);70 71		entry->vlsf_flags[n] = tmp;72		entry->addr_version[n] = ntohl(uvldb->serverUnique[i]);73		entry->nr_servers++;74	}75 76	for (i = 0; i < AFS_MAXTYPES; i++)77		entry->vid[i] = ntohl(uvldb->volumeId[i]);78 79	if (vlflags & AFS_VLF_RWEXISTS)80		__set_bit(AFS_VLDB_HAS_RW, &entry->flags);81	if (vlflags & AFS_VLF_ROEXISTS)82		__set_bit(AFS_VLDB_HAS_RO, &entry->flags);83	if (vlflags & AFS_VLF_BACKEXISTS)84		__set_bit(AFS_VLDB_HAS_BAK, &entry->flags);85 86	if (!(vlflags & (AFS_VLF_RWEXISTS | AFS_VLF_ROEXISTS | AFS_VLF_BACKEXISTS))) {87		entry->error = -ENOMEDIUM;88		__set_bit(AFS_VLDB_QUERY_ERROR, &entry->flags);89	}90 91	__set_bit(AFS_VLDB_QUERY_VALID, &entry->flags);92	_leave(" = 0 [done]");93	return 0;94}95 96/*97 * VL.GetEntryByNameU operation type.98 */99static const struct afs_call_type afs_RXVLGetEntryByNameU = {100	.name		= "VL.GetEntryByNameU",101	.op		= afs_VL_GetEntryByNameU,102	.deliver	= afs_deliver_vl_get_entry_by_name_u,103	.destructor	= afs_flat_call_destructor,104};105 106/*107 * Dispatch a get volume entry by name or ID operation (uuid variant).  If the108 * volname is a decimal number then it's a volume ID not a volume name.109 */110struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc,111						  const char *volname,112						  int volnamesz)113{114	struct afs_vldb_entry *entry;115	struct afs_call *call;116	struct afs_net *net = vc->cell->net;117	size_t reqsz, padsz;118	__be32 *bp;119 120	_enter("");121 122	padsz = (4 - (volnamesz & 3)) & 3;123	reqsz = 8 + volnamesz + padsz;124 125	entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL);126	if (!entry)127		return ERR_PTR(-ENOMEM);128 129	call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz,130				   sizeof(struct afs_uvldbentry__xdr));131	if (!call) {132		kfree(entry);133		return ERR_PTR(-ENOMEM);134	}135 136	call->key = vc->key;137	call->ret_vldb = entry;138	call->max_lifespan = AFS_VL_MAX_LIFESPAN;139	call->peer = rxrpc_kernel_get_peer(vc->alist->addrs[vc->addr_index].peer);140	call->service_id = vc->server->service_id;141 142	/* Marshall the parameters */143	bp = call->request;144	*bp++ = htonl(VLGETENTRYBYNAMEU);145	*bp++ = htonl(volnamesz);146	memcpy(bp, volname, volnamesz);147	if (padsz > 0)148		memset((void *)bp + volnamesz, 0, padsz);149 150	trace_afs_make_vl_call(call);151	afs_make_call(call, GFP_KERNEL);152	afs_wait_for_call_to_complete(call);153	vc->call_abort_code	= call->abort_code;154	vc->call_error		= call->error;155	vc->call_responded	= call->responded;156	afs_put_call(call);157	if (vc->call_error) {158		kfree(entry);159		return ERR_PTR(vc->call_error);160	}161	return entry;162}163 164/*165 * Deliver reply data to a VL.GetAddrsU call.166 *167 *	GetAddrsU(IN ListAddrByAttributes *inaddr,168 *		  OUT afsUUID *uuidp1,169 *		  OUT uint32_t *uniquifier,170 *		  OUT uint32_t *nentries,171 *		  OUT bulkaddrs *blkaddrs);172 */173static int afs_deliver_vl_get_addrs_u(struct afs_call *call)174{175	struct afs_addr_list *alist;176	__be32 *bp;177	u32 uniquifier, nentries, count;178	int i, ret;179 180	_enter("{%u,%zu/%u}",181	       call->unmarshall, iov_iter_count(call->iter), call->count);182 183	switch (call->unmarshall) {184	case 0:185		afs_extract_to_buf(call,186				   sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));187		call->unmarshall++;188 189		/* Extract the returned uuid, uniquifier, nentries and190		 * blkaddrs size */191		fallthrough;192	case 1:193		ret = afs_extract_data(call, true);194		if (ret < 0)195			return ret;196 197		bp = call->buffer + sizeof(struct afs_uuid__xdr);198		uniquifier	= ntohl(*bp++);199		nentries	= ntohl(*bp++);200		count		= ntohl(*bp);201 202		nentries = min(nentries, count);203		alist = afs_alloc_addrlist(nentries);204		if (!alist)205			return -ENOMEM;206		alist->version = uniquifier;207		call->ret_alist = alist;208		call->count = count;209		call->count2 = nentries;210		call->unmarshall++;211 212	more_entries:213		count = min(call->count, 4U);214		afs_extract_to_buf(call, count * sizeof(__be32));215 216		fallthrough;	/* and extract entries */217	case 2:218		ret = afs_extract_data(call, call->count > 4);219		if (ret < 0)220			return ret;221 222		alist = call->ret_alist;223		bp = call->buffer;224		count = min(call->count, 4U);225		for (i = 0; i < count; i++) {226			if (alist->nr_addrs < call->count2) {227				ret = afs_merge_fs_addr4(call->net, alist, *bp++, AFS_FS_PORT);228				if (ret < 0)229					return ret;230			}231		}232 233		call->count -= count;234		if (call->count > 0)235			goto more_entries;236		call->unmarshall++;237		break;238	}239 240	_leave(" = 0 [done]");241	return 0;242}243 244/*245 * VL.GetAddrsU operation type.246 */247static const struct afs_call_type afs_RXVLGetAddrsU = {248	.name		= "VL.GetAddrsU",249	.op		= afs_VL_GetAddrsU,250	.deliver	= afs_deliver_vl_get_addrs_u,251	.destructor	= afs_flat_call_destructor,252};253 254/*255 * Dispatch an operation to get the addresses for a server, where the server is256 * nominated by UUID.257 */258struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc,259					 const uuid_t *uuid)260{261	struct afs_ListAddrByAttributes__xdr *r;262	struct afs_addr_list *alist;263	const struct afs_uuid *u = (const struct afs_uuid *)uuid;264	struct afs_call *call;265	struct afs_net *net = vc->cell->net;266	__be32 *bp;267	int i;268 269	_enter("");270 271	call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU,272				   sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr),273				   sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));274	if (!call)275		return ERR_PTR(-ENOMEM);276 277	call->key = vc->key;278	call->ret_alist = NULL;279	call->max_lifespan = AFS_VL_MAX_LIFESPAN;280	call->peer = rxrpc_kernel_get_peer(vc->alist->addrs[vc->addr_index].peer);281	call->service_id = vc->server->service_id;282 283	/* Marshall the parameters */284	bp = call->request;285	*bp++ = htonl(VLGETADDRSU);286	r = (struct afs_ListAddrByAttributes__xdr *)bp;287	r->Mask		= htonl(AFS_VLADDR_UUID);288	r->ipaddr	= 0;289	r->index	= 0;290	r->spare	= 0;291	r->uuid.time_low			= u->time_low;292	r->uuid.time_mid			= htonl(ntohs(u->time_mid));293	r->uuid.time_hi_and_version		= htonl(ntohs(u->time_hi_and_version));294	r->uuid.clock_seq_hi_and_reserved 	= htonl(u->clock_seq_hi_and_reserved);295	r->uuid.clock_seq_low			= htonl(u->clock_seq_low);296	for (i = 0; i < 6; i++)297		r->uuid.node[i] = htonl(u->node[i]);298 299	trace_afs_make_vl_call(call);300	afs_make_call(call, GFP_KERNEL);301	afs_wait_for_call_to_complete(call);302	vc->call_abort_code	= call->abort_code;303	vc->call_error		= call->error;304	vc->call_responded	= call->responded;305	alist			= call->ret_alist;306	afs_put_call(call);307	if (vc->call_error) {308		afs_put_addrlist(alist, afs_alist_trace_put_getaddru);309		return ERR_PTR(vc->call_error);310	}311	return alist;312}313 314/*315 * Deliver reply data to an VL.GetCapabilities operation.316 */317static int afs_deliver_vl_get_capabilities(struct afs_call *call)318{319	u32 count;320	int ret;321 322	_enter("{%u,%zu/%u}",323	       call->unmarshall, iov_iter_count(call->iter), call->count);324 325	switch (call->unmarshall) {326	case 0:327		afs_extract_to_tmp(call);328		call->unmarshall++;329 330		fallthrough;	/* and extract the capabilities word count */331	case 1:332		ret = afs_extract_data(call, true);333		if (ret < 0)334			return ret;335 336		count = ntohl(call->tmp);337		call->count = count;338		call->count2 = count;339 340		call->unmarshall++;341		afs_extract_discard(call, count * sizeof(__be32));342 343		fallthrough;	/* and extract capabilities words */344	case 2:345		ret = afs_extract_data(call, false);346		if (ret < 0)347			return ret;348 349		/* TODO: Examine capabilities */350 351		call->unmarshall++;352		break;353	}354 355	_leave(" = 0 [done]");356	return 0;357}358 359static void afs_destroy_vl_get_capabilities(struct afs_call *call)360{361	afs_put_addrlist(call->vl_probe, afs_alist_trace_put_vlgetcaps);362	afs_put_vlserver(call->net, call->vlserver);363	afs_flat_call_destructor(call);364}365 366/*367 * VL.GetCapabilities operation type368 */369static const struct afs_call_type afs_RXVLGetCapabilities = {370	.name		= "VL.GetCapabilities",371	.op		= afs_VL_GetCapabilities,372	.deliver	= afs_deliver_vl_get_capabilities,373	.done		= afs_vlserver_probe_result,374	.destructor	= afs_destroy_vl_get_capabilities,375};376 377/*378 * Probe a volume server for the capabilities that it supports.  This can379 * return up to 196 words.380 *381 * We use this to probe for service upgrade to determine what the server at the382 * other end supports.383 */384struct afs_call *afs_vl_get_capabilities(struct afs_net *net,385					 struct afs_addr_list *alist,386					 unsigned int addr_index,387					 struct key *key,388					 struct afs_vlserver *server,389					 unsigned int server_index)390{391	struct afs_call *call;392	__be32 *bp;393 394	_enter("");395 396	call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4);397	if (!call)398		return ERR_PTR(-ENOMEM);399 400	call->key = key;401	call->vlserver = afs_get_vlserver(server);402	call->server_index = server_index;403	call->peer = rxrpc_kernel_get_peer(alist->addrs[addr_index].peer);404	call->vl_probe = afs_get_addrlist(alist, afs_alist_trace_get_vlgetcaps);405	call->probe_index = addr_index;406	call->service_id = server->service_id;407	call->upgrade = true;408	call->async = true;409	call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;410 411	/* marshall the parameters */412	bp = call->request;413	*bp++ = htonl(VLGETCAPABILITIES);414 415	/* Can't take a ref on server */416	trace_afs_make_vl_call(call);417	afs_make_call(call, GFP_KERNEL);418	return call;419}420 421/*422 * Deliver reply data to a YFSVL.GetEndpoints call.423 *424 *	GetEndpoints(IN yfsServerAttributes *attr,425 *		     OUT opr_uuid *uuid,426 *		     OUT afs_int32 *uniquifier,427 *		     OUT endpoints *fsEndpoints,428 *		     OUT endpoints *volEndpoints)429 */430static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)431{432	struct afs_addr_list *alist;433	__be32 *bp;434	u32 uniquifier, size;435	int ret;436 437	_enter("{%u,%zu,%u}",438	       call->unmarshall, iov_iter_count(call->iter), call->count2);439 440	switch (call->unmarshall) {441	case 0:442		afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32));443		call->unmarshall = 1;444 445		/* Extract the returned uuid, uniquifier, fsEndpoints count and446		 * either the first fsEndpoint type or the volEndpoints447		 * count if there are no fsEndpoints. */448		fallthrough;449	case 1:450		ret = afs_extract_data(call, true);451		if (ret < 0)452			return ret;453 454		bp = call->buffer + sizeof(uuid_t);455		uniquifier	= ntohl(*bp++);456		call->count	= ntohl(*bp++);457		call->count2	= ntohl(*bp); /* Type or next count */458 459		if (call->count > YFS_MAXENDPOINTS)460			return afs_protocol_error(call, afs_eproto_yvl_fsendpt_num);461 462		alist = afs_alloc_addrlist(call->count);463		if (!alist)464			return -ENOMEM;465		alist->version = uniquifier;466		call->ret_alist = alist;467 468		if (call->count == 0)469			goto extract_volendpoints;470 471	next_fsendpoint:472		switch (call->count2) {473		case YFS_ENDPOINT_IPV4:474			size = sizeof(__be32) * (1 + 1 + 1);475			break;476		case YFS_ENDPOINT_IPV6:477			size = sizeof(__be32) * (1 + 4 + 1);478			break;479		default:480			return afs_protocol_error(call, afs_eproto_yvl_fsendpt_type);481		}482 483		size += sizeof(__be32);484		afs_extract_to_buf(call, size);485		call->unmarshall = 2;486 487		fallthrough;	/* and extract fsEndpoints[] entries */488	case 2:489		ret = afs_extract_data(call, true);490		if (ret < 0)491			return ret;492 493		alist = call->ret_alist;494		bp = call->buffer;495		switch (call->count2) {496		case YFS_ENDPOINT_IPV4:497			if (ntohl(bp[0]) != sizeof(__be32) * 2)498				return afs_protocol_error(499					call, afs_eproto_yvl_fsendpt4_len);500			ret = afs_merge_fs_addr4(call->net, alist, bp[1], ntohl(bp[2]));501			if (ret < 0)502				return ret;503			bp += 3;504			break;505		case YFS_ENDPOINT_IPV6:506			if (ntohl(bp[0]) != sizeof(__be32) * 5)507				return afs_protocol_error(508					call, afs_eproto_yvl_fsendpt6_len);509			ret = afs_merge_fs_addr6(call->net, alist, bp + 1, ntohl(bp[5]));510			if (ret < 0)511				return ret;512			bp += 6;513			break;514		default:515			return afs_protocol_error(call, afs_eproto_yvl_fsendpt_type);516		}517 518		/* Got either the type of the next entry or the count of519		 * volEndpoints if no more fsEndpoints.520		 */521		call->count2 = ntohl(*bp++);522 523		call->count--;524		if (call->count > 0)525			goto next_fsendpoint;526 527	extract_volendpoints:528		/* Extract the list of volEndpoints. */529		call->count = call->count2;530		if (!call->count)531			goto end;532		if (call->count > YFS_MAXENDPOINTS)533			return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);534 535		afs_extract_to_buf(call, 1 * sizeof(__be32));536		call->unmarshall = 3;537 538		/* Extract the type of volEndpoints[0].  Normally we would539		 * extract the type of the next endpoint when we extract the540		 * data of the current one, but this is the first...541		 */542		fallthrough;543	case 3:544		ret = afs_extract_data(call, true);545		if (ret < 0)546			return ret;547 548		bp = call->buffer;549 550	next_volendpoint:551		call->count2 = ntohl(*bp++);552		switch (call->count2) {553		case YFS_ENDPOINT_IPV4:554			size = sizeof(__be32) * (1 + 1 + 1);555			break;556		case YFS_ENDPOINT_IPV6:557			size = sizeof(__be32) * (1 + 4 + 1);558			break;559		default:560			return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);561		}562 563		if (call->count > 1)564			size += sizeof(__be32); /* Get next type too */565		afs_extract_to_buf(call, size);566		call->unmarshall = 4;567 568		fallthrough;	/* and extract volEndpoints[] entries */569	case 4:570		ret = afs_extract_data(call, true);571		if (ret < 0)572			return ret;573 574		bp = call->buffer;575		switch (call->count2) {576		case YFS_ENDPOINT_IPV4:577			if (ntohl(bp[0]) != sizeof(__be32) * 2)578				return afs_protocol_error(579					call, afs_eproto_yvl_vlendpt4_len);580			bp += 3;581			break;582		case YFS_ENDPOINT_IPV6:583			if (ntohl(bp[0]) != sizeof(__be32) * 5)584				return afs_protocol_error(585					call, afs_eproto_yvl_vlendpt6_len);586			bp += 6;587			break;588		default:589			return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);590		}591 592		/* Got either the type of the next entry or the count of593		 * volEndpoints if no more fsEndpoints.594		 */595		call->count--;596		if (call->count > 0)597			goto next_volendpoint;598 599	end:600		afs_extract_discard(call, 0);601		call->unmarshall = 5;602 603		fallthrough;	/* Done */604	case 5:605		ret = afs_extract_data(call, false);606		if (ret < 0)607			return ret;608		call->unmarshall = 6;609		fallthrough;610 611	case 6:612		break;613	}614 615	_leave(" = 0 [done]");616	return 0;617}618 619/*620 * YFSVL.GetEndpoints operation type.621 */622static const struct afs_call_type afs_YFSVLGetEndpoints = {623	.name		= "YFSVL.GetEndpoints",624	.op		= afs_YFSVL_GetEndpoints,625	.deliver	= afs_deliver_yfsvl_get_endpoints,626	.destructor	= afs_flat_call_destructor,627};628 629/*630 * Dispatch an operation to get the addresses for a server, where the server is631 * nominated by UUID.632 */633struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc,634					      const uuid_t *uuid)635{636	struct afs_addr_list *alist;637	struct afs_call *call;638	struct afs_net *net = vc->cell->net;639	__be32 *bp;640 641	_enter("");642 643	call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints,644				   sizeof(__be32) * 2 + sizeof(*uuid),645				   sizeof(struct in6_addr) + sizeof(__be32) * 3);646	if (!call)647		return ERR_PTR(-ENOMEM);648 649	call->key = vc->key;650	call->ret_alist = NULL;651	call->max_lifespan = AFS_VL_MAX_LIFESPAN;652	call->peer = rxrpc_kernel_get_peer(vc->alist->addrs[vc->addr_index].peer);653	call->service_id = vc->server->service_id;654 655	/* Marshall the parameters */656	bp = call->request;657	*bp++ = htonl(YVLGETENDPOINTS);658	*bp++ = htonl(YFS_SERVER_UUID);659	memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */660 661	trace_afs_make_vl_call(call);662	afs_make_call(call, GFP_KERNEL);663	afs_wait_for_call_to_complete(call);664	vc->call_abort_code	= call->abort_code;665	vc->call_error		= call->error;666	vc->call_responded	= call->responded;667	alist			= call->ret_alist;668	afs_put_call(call);669	if (vc->call_error) {670		afs_put_addrlist(alist, afs_alist_trace_put_getaddru);671		return ERR_PTR(vc->call_error);672	}673	return alist;674}675 676/*677 * Deliver reply data to a YFSVL.GetCellName operation.678 */679static int afs_deliver_yfsvl_get_cell_name(struct afs_call *call)680{681	char *cell_name;682	u32 namesz, paddedsz;683	int ret;684 685	_enter("{%u,%zu/%u}",686	       call->unmarshall, iov_iter_count(call->iter), call->count);687 688	switch (call->unmarshall) {689	case 0:690		afs_extract_to_tmp(call);691		call->unmarshall++;692 693		fallthrough;	/* and extract the cell name length */694	case 1:695		ret = afs_extract_data(call, true);696		if (ret < 0)697			return ret;698 699		namesz = ntohl(call->tmp);700		if (namesz > AFS_MAXCELLNAME)701			return afs_protocol_error(call, afs_eproto_cellname_len);702		paddedsz = (namesz + 3) & ~3;703		call->count = namesz;704		call->count2 = paddedsz - namesz;705 706		cell_name = kmalloc(namesz + 1, GFP_KERNEL);707		if (!cell_name)708			return -ENOMEM;709		cell_name[namesz] = 0;710		call->ret_str = cell_name;711 712		afs_extract_begin(call, cell_name, namesz);713		call->unmarshall++;714 715		fallthrough;	/* and extract cell name */716	case 2:717		ret = afs_extract_data(call, true);718		if (ret < 0)719			return ret;720 721		afs_extract_discard(call, call->count2);722		call->unmarshall++;723 724		fallthrough;	/* and extract padding */725	case 3:726		ret = afs_extract_data(call, false);727		if (ret < 0)728			return ret;729 730		call->unmarshall++;731		break;732	}733 734	_leave(" = 0 [done]");735	return 0;736}737 738/*739 * VL.GetCapabilities operation type740 */741static const struct afs_call_type afs_YFSVLGetCellName = {742	.name		= "YFSVL.GetCellName",743	.op		= afs_YFSVL_GetCellName,744	.deliver	= afs_deliver_yfsvl_get_cell_name,745	.destructor	= afs_flat_call_destructor,746};747 748/*749 * Probe a volume server for the capabilities that it supports.  This can750 * return up to 196 words.751 *752 * We use this to probe for service upgrade to determine what the server at the753 * other end supports.754 */755char *afs_yfsvl_get_cell_name(struct afs_vl_cursor *vc)756{757	struct afs_call *call;758	struct afs_net *net = vc->cell->net;759	__be32 *bp;760	char *cellname;761 762	_enter("");763 764	call = afs_alloc_flat_call(net, &afs_YFSVLGetCellName, 1 * 4, 0);765	if (!call)766		return ERR_PTR(-ENOMEM);767 768	call->key = vc->key;769	call->ret_str = NULL;770	call->max_lifespan = AFS_VL_MAX_LIFESPAN;771	call->peer = rxrpc_kernel_get_peer(vc->alist->addrs[vc->addr_index].peer);772	call->service_id = vc->server->service_id;773 774	/* marshall the parameters */775	bp = call->request;776	*bp++ = htonl(YVLGETCELLNAME);777 778	/* Can't take a ref on server */779	trace_afs_make_vl_call(call);780	afs_make_call(call, GFP_KERNEL);781	afs_wait_for_call_to_complete(call);782	vc->call_abort_code	= call->abort_code;783	vc->call_error		= call->error;784	vc->call_responded	= call->responded;785	cellname		= call->ret_str;786	afs_put_call(call);787	if (vc->call_error) {788		kfree(cellname);789		return ERR_PTR(vc->call_error);790	}791	return cellname;792}793