12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2ec26815aSDavid Howells /* AFS Volume Location Service client
31da177e4SLinus Torvalds *
41da177e4SLinus Torvalds * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
51da177e4SLinus Torvalds * Written by David Howells (dhowells@redhat.com)
61da177e4SLinus Torvalds */
71da177e4SLinus Torvalds
85a0e3ad6STejun Heo #include <linux/gfp.h>
91da177e4SLinus Torvalds #include <linux/init.h>
101da177e4SLinus Torvalds #include <linux/sched.h>
114d9df986SDavid Howells #include "afs_fs.h"
121da177e4SLinus Torvalds #include "internal.h"
131da177e4SLinus Torvalds
1408e0e7c8SDavid Howells /*
15d2ddc776SDavid Howells * Deliver reply data to a VL.GetEntryByNameU call.
161da177e4SLinus Torvalds */
afs_deliver_vl_get_entry_by_name_u(struct afs_call * call)17d2ddc776SDavid Howells static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)
181da177e4SLinus Torvalds {
19d2ddc776SDavid Howells struct afs_uvldbentry__xdr *uvldb;
20d2ddc776SDavid Howells struct afs_vldb_entry *entry;
21d2ddc776SDavid Howells bool new_only = false;
221fba5868SMarc Dionne u32 tmp, nr_servers, vlflags;
23d2ddc776SDavid Howells int i, ret;
241da177e4SLinus Torvalds
25d001648eSDavid Howells _enter("");
261da177e4SLinus Torvalds
27d001648eSDavid Howells ret = afs_transfer_reply(call);
28372ee163SDavid Howells if (ret < 0)
29372ee163SDavid Howells return ret;
301da177e4SLinus Torvalds
3108e0e7c8SDavid Howells /* unmarshall the reply once we've received all of it */
32d2ddc776SDavid Howells uvldb = call->buffer;
33ffba718eSDavid Howells entry = call->ret_vldb;
341da177e4SLinus Torvalds
3545df8462SDavid Howells nr_servers = ntohl(uvldb->nServers);
3645df8462SDavid Howells if (nr_servers > AFS_NMAXNSERVERS)
3745df8462SDavid Howells nr_servers = AFS_NMAXNSERVERS;
3845df8462SDavid Howells
39d2ddc776SDavid Howells for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++)
40d2ddc776SDavid Howells entry->name[i] = (u8)ntohl(uvldb->name[i]);
41d2ddc776SDavid Howells entry->name[i] = 0;
42d2ddc776SDavid Howells entry->name_len = strlen(entry->name);
431da177e4SLinus Torvalds
44d2ddc776SDavid Howells /* If there is a new replication site that we can use, ignore all the
45d2ddc776SDavid Howells * sites that aren't marked as new.
46d2ddc776SDavid Howells */
4745df8462SDavid Howells for (i = 0; i < nr_servers; i++) {
48d2ddc776SDavid Howells tmp = ntohl(uvldb->serverFlags[i]);
49d2ddc776SDavid Howells if (!(tmp & AFS_VLSF_DONTUSE) &&
50d2ddc776SDavid Howells (tmp & AFS_VLSF_NEWREPSITE))
51d2ddc776SDavid Howells new_only = true;
524d9df986SDavid Howells }
531da177e4SLinus Torvalds
541fba5868SMarc Dionne vlflags = ntohl(uvldb->flags);
5545df8462SDavid Howells for (i = 0; i < nr_servers; i++) {
56d2ddc776SDavid Howells struct afs_uuid__xdr *xdr;
57d2ddc776SDavid Howells struct afs_uuid *uuid;
58d2ddc776SDavid Howells int j;
594a46fdbaSMarc Dionne int n = entry->nr_servers;
601da177e4SLinus Torvalds
61d2ddc776SDavid Howells tmp = ntohl(uvldb->serverFlags[i]);
62d2ddc776SDavid Howells if (tmp & AFS_VLSF_DONTUSE ||
63d2ddc776SDavid Howells (new_only && !(tmp & AFS_VLSF_NEWREPSITE)))
64d2ddc776SDavid Howells continue;
651fba5868SMarc Dionne if (tmp & AFS_VLSF_RWVOL) {
664a46fdbaSMarc Dionne entry->fs_mask[n] |= AFS_VOL_VTM_RW;
671fba5868SMarc Dionne if (vlflags & AFS_VLF_BACKEXISTS)
684a46fdbaSMarc Dionne entry->fs_mask[n] |= AFS_VOL_VTM_BAK;
691fba5868SMarc Dionne }
701da177e4SLinus Torvalds if (tmp & AFS_VLSF_ROVOL)
714a46fdbaSMarc Dionne entry->fs_mask[n] |= AFS_VOL_VTM_RO;
724a46fdbaSMarc Dionne if (!entry->fs_mask[n])
73d2ddc776SDavid Howells continue;
74d2ddc776SDavid Howells
75d2ddc776SDavid Howells xdr = &uvldb->serverNumber[i];
764a46fdbaSMarc Dionne uuid = (struct afs_uuid *)&entry->fs_server[n];
77d2ddc776SDavid Howells uuid->time_low = xdr->time_low;
78d2ddc776SDavid Howells uuid->time_mid = htons(ntohl(xdr->time_mid));
79d2ddc776SDavid Howells uuid->time_hi_and_version = htons(ntohl(xdr->time_hi_and_version));
80d2ddc776SDavid Howells uuid->clock_seq_hi_and_reserved = (u8)ntohl(xdr->clock_seq_hi_and_reserved);
81d2ddc776SDavid Howells uuid->clock_seq_low = (u8)ntohl(xdr->clock_seq_low);
82d2ddc776SDavid Howells for (j = 0; j < 6; j++)
83d2ddc776SDavid Howells uuid->node[j] = (u8)ntohl(xdr->node[j]);
84d2ddc776SDavid Howells
8581006805SDavid Howells entry->addr_version[n] = ntohl(uvldb->serverUnique[i]);
86d2ddc776SDavid Howells entry->nr_servers++;
871da177e4SLinus Torvalds }
881da177e4SLinus Torvalds
89d2ddc776SDavid Howells for (i = 0; i < AFS_MAXTYPES; i++)
90d2ddc776SDavid Howells entry->vid[i] = ntohl(uvldb->volumeId[i]);
911da177e4SLinus Torvalds
921fba5868SMarc Dionne if (vlflags & AFS_VLF_RWEXISTS)
93d2ddc776SDavid Howells __set_bit(AFS_VLDB_HAS_RW, &entry->flags);
941fba5868SMarc Dionne if (vlflags & AFS_VLF_ROEXISTS)
95d2ddc776SDavid Howells __set_bit(AFS_VLDB_HAS_RO, &entry->flags);
961fba5868SMarc Dionne if (vlflags & AFS_VLF_BACKEXISTS)
97d2ddc776SDavid Howells __set_bit(AFS_VLDB_HAS_BAK, &entry->flags);
981da177e4SLinus Torvalds
991fba5868SMarc Dionne if (!(vlflags & (AFS_VLF_RWEXISTS | AFS_VLF_ROEXISTS | AFS_VLF_BACKEXISTS))) {
100d2ddc776SDavid Howells entry->error = -ENOMEDIUM;
101d2ddc776SDavid Howells __set_bit(AFS_VLDB_QUERY_ERROR, &entry->flags);
102d2ddc776SDavid Howells }
103d2ddc776SDavid Howells
104d2ddc776SDavid Howells __set_bit(AFS_VLDB_QUERY_VALID, &entry->flags);
10508e0e7c8SDavid Howells _leave(" = 0 [done]");
10608e0e7c8SDavid Howells return 0;
107ec26815aSDavid Howells }
1081da177e4SLinus Torvalds
afs_destroy_vl_get_entry_by_name_u(struct afs_call * call)109d2ddc776SDavid Howells static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call)
110d2ddc776SDavid Howells {
111ffba718eSDavid Howells kfree(call->ret_vldb);
112d2ddc776SDavid Howells afs_flat_call_destructor(call);
113d2ddc776SDavid Howells }
114d2ddc776SDavid Howells
1151da177e4SLinus Torvalds /*
116d2ddc776SDavid Howells * VL.GetEntryByNameU operation type.
1171da177e4SLinus Torvalds */
118d2ddc776SDavid Howells static const struct afs_call_type afs_RXVLGetEntryByNameU = {
119d2ddc776SDavid Howells .name = "VL.GetEntryByNameU",
120025db80cSDavid Howells .op = afs_VL_GetEntryByNameU,
121d2ddc776SDavid Howells .deliver = afs_deliver_vl_get_entry_by_name_u,
122d2ddc776SDavid Howells .destructor = afs_destroy_vl_get_entry_by_name_u,
12308e0e7c8SDavid Howells };
12408e0e7c8SDavid Howells
12508e0e7c8SDavid Howells /*
126d2ddc776SDavid Howells * Dispatch a get volume entry by name or ID operation (uuid variant). If the
127d2ddc776SDavid Howells * volname is a decimal number then it's a volume ID not a volume name.
12808e0e7c8SDavid Howells */
afs_vl_get_entry_by_name_u(struct afs_vl_cursor * vc,const char * volname,int volnamesz)1290a5143f2SDavid Howells struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc,
13008e0e7c8SDavid Howells const char *volname,
131d2ddc776SDavid Howells int volnamesz)
13208e0e7c8SDavid Howells {
133d2ddc776SDavid Howells struct afs_vldb_entry *entry;
13408e0e7c8SDavid Howells struct afs_call *call;
1350a5143f2SDavid Howells struct afs_net *net = vc->cell->net;
136d2ddc776SDavid Howells size_t reqsz, padsz;
13708e0e7c8SDavid Howells __be32 *bp;
13808e0e7c8SDavid Howells
13908e0e7c8SDavid Howells _enter("");
14008e0e7c8SDavid Howells
14108e0e7c8SDavid Howells padsz = (4 - (volnamesz & 3)) & 3;
14208e0e7c8SDavid Howells reqsz = 8 + volnamesz + padsz;
14308e0e7c8SDavid Howells
144d2ddc776SDavid Howells entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL);
145d2ddc776SDavid Howells if (!entry)
146d2ddc776SDavid Howells return ERR_PTR(-ENOMEM);
147d2ddc776SDavid Howells
148d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz,
149d2ddc776SDavid Howells sizeof(struct afs_uvldbentry__xdr));
150d2ddc776SDavid Howells if (!call) {
151d2ddc776SDavid Howells kfree(entry);
152d2ddc776SDavid Howells return ERR_PTR(-ENOMEM);
153d2ddc776SDavid Howells }
15408e0e7c8SDavid Howells
1550a5143f2SDavid Howells call->key = vc->key;
156ffba718eSDavid Howells call->ret_vldb = entry;
15794f699c9SDavid Howells call->max_lifespan = AFS_VL_MAX_LIFESPAN;
15808e0e7c8SDavid Howells
159d2ddc776SDavid Howells /* Marshall the parameters */
16008e0e7c8SDavid Howells bp = call->request;
161d2ddc776SDavid Howells *bp++ = htonl(VLGETENTRYBYNAMEU);
16208e0e7c8SDavid Howells *bp++ = htonl(volnamesz);
16308e0e7c8SDavid Howells memcpy(bp, volname, volnamesz);
16408e0e7c8SDavid Howells if (padsz > 0)
16508e0e7c8SDavid Howells memset((void *)bp + volnamesz, 0, padsz);
16608e0e7c8SDavid Howells
167025db80cSDavid Howells trace_afs_make_vl_call(call);
1680b9bf381SDavid Howells afs_make_call(&vc->ac, call, GFP_KERNEL);
1690b9bf381SDavid Howells return (struct afs_vldb_entry *)afs_wait_for_call_to_complete(call, &vc->ac);
17008e0e7c8SDavid Howells }
17108e0e7c8SDavid Howells
17208e0e7c8SDavid Howells /*
173d2ddc776SDavid Howells * Deliver reply data to a VL.GetAddrsU call.
174d2ddc776SDavid Howells *
175d2ddc776SDavid Howells * GetAddrsU(IN ListAddrByAttributes *inaddr,
176d2ddc776SDavid Howells * OUT afsUUID *uuidp1,
177d2ddc776SDavid Howells * OUT uint32_t *uniquifier,
178d2ddc776SDavid Howells * OUT uint32_t *nentries,
179d2ddc776SDavid Howells * OUT bulkaddrs *blkaddrs);
18008e0e7c8SDavid Howells */
afs_deliver_vl_get_addrs_u(struct afs_call * call)181d2ddc776SDavid Howells static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
182d2ddc776SDavid Howells {
183d2ddc776SDavid Howells struct afs_addr_list *alist;
184d2ddc776SDavid Howells __be32 *bp;
185d2ddc776SDavid Howells u32 uniquifier, nentries, count;
186d2ddc776SDavid Howells int i, ret;
187d2ddc776SDavid Howells
18812bdcf33SDavid Howells _enter("{%u,%zu/%u}",
189fc276122SDavid Howells call->unmarshall, iov_iter_count(call->iter), call->count);
190d2ddc776SDavid Howells
191d2ddc776SDavid Howells switch (call->unmarshall) {
192d2ddc776SDavid Howells case 0:
19312bdcf33SDavid Howells afs_extract_to_buf(call,
19412bdcf33SDavid Howells sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
195d2ddc776SDavid Howells call->unmarshall++;
196d2ddc776SDavid Howells
197e690c9e3SGustavo A. R. Silva /* Extract the returned uuid, uniquifier, nentries and
198e690c9e3SGustavo A. R. Silva * blkaddrs size */
199df561f66SGustavo A. R. Silva fallthrough;
200d2ddc776SDavid Howells case 1:
20112bdcf33SDavid Howells ret = afs_extract_data(call, true);
202d2ddc776SDavid Howells if (ret < 0)
203d2ddc776SDavid Howells return ret;
204d2ddc776SDavid Howells
205d2ddc776SDavid Howells bp = call->buffer + sizeof(struct afs_uuid__xdr);
206d2ddc776SDavid Howells uniquifier = ntohl(*bp++);
207d2ddc776SDavid Howells nentries = ntohl(*bp++);
208d2ddc776SDavid Howells count = ntohl(*bp);
209d2ddc776SDavid Howells
210d2ddc776SDavid Howells nentries = min(nentries, count);
211d2ddc776SDavid Howells alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT);
212d2ddc776SDavid Howells if (!alist)
213d2ddc776SDavid Howells return -ENOMEM;
214d2ddc776SDavid Howells alist->version = uniquifier;
215ffba718eSDavid Howells call->ret_alist = alist;
216d2ddc776SDavid Howells call->count = count;
217d2ddc776SDavid Howells call->count2 = nentries;
218d2ddc776SDavid Howells call->unmarshall++;
219d2ddc776SDavid Howells
22012bdcf33SDavid Howells more_entries:
22112bdcf33SDavid Howells count = min(call->count, 4U);
22212bdcf33SDavid Howells afs_extract_to_buf(call, count * sizeof(__be32));
22312bdcf33SDavid Howells
224df561f66SGustavo A. R. Silva fallthrough; /* and extract entries */
225d2ddc776SDavid Howells case 2:
22612bdcf33SDavid Howells ret = afs_extract_data(call, call->count > 4);
227d2ddc776SDavid Howells if (ret < 0)
228d2ddc776SDavid Howells return ret;
229d2ddc776SDavid Howells
230ffba718eSDavid Howells alist = call->ret_alist;
231d2ddc776SDavid Howells bp = call->buffer;
23212bdcf33SDavid Howells count = min(call->count, 4U);
233d2ddc776SDavid Howells for (i = 0; i < count; i++)
234d2ddc776SDavid Howells if (alist->nr_addrs < call->count2)
235bf99a53cSDavid Howells afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT);
236d2ddc776SDavid Howells
237d2ddc776SDavid Howells call->count -= count;
238d2ddc776SDavid Howells if (call->count > 0)
23912bdcf33SDavid Howells goto more_entries;
240d2ddc776SDavid Howells call->unmarshall++;
241d2ddc776SDavid Howells break;
242d2ddc776SDavid Howells }
243d2ddc776SDavid Howells
244d2ddc776SDavid Howells _leave(" = 0 [done]");
245d2ddc776SDavid Howells return 0;
246d2ddc776SDavid Howells }
247d2ddc776SDavid Howells
afs_vl_get_addrs_u_destructor(struct afs_call * call)248d2ddc776SDavid Howells static void afs_vl_get_addrs_u_destructor(struct afs_call *call)
249d2ddc776SDavid Howells {
250ffba718eSDavid Howells afs_put_addrlist(call->ret_alist);
251d2ddc776SDavid Howells return afs_flat_call_destructor(call);
252d2ddc776SDavid Howells }
253d2ddc776SDavid Howells
254d2ddc776SDavid Howells /*
255d2ddc776SDavid Howells * VL.GetAddrsU operation type.
256d2ddc776SDavid Howells */
257d2ddc776SDavid Howells static const struct afs_call_type afs_RXVLGetAddrsU = {
258d2ddc776SDavid Howells .name = "VL.GetAddrsU",
259025db80cSDavid Howells .op = afs_VL_GetAddrsU,
260d2ddc776SDavid Howells .deliver = afs_deliver_vl_get_addrs_u,
261d2ddc776SDavid Howells .destructor = afs_vl_get_addrs_u_destructor,
262d2ddc776SDavid Howells };
263d2ddc776SDavid Howells
264d2ddc776SDavid Howells /*
265d2ddc776SDavid Howells * Dispatch an operation to get the addresses for a server, where the server is
266d2ddc776SDavid Howells * nominated by UUID.
267d2ddc776SDavid Howells */
afs_vl_get_addrs_u(struct afs_vl_cursor * vc,const uuid_t * uuid)2680a5143f2SDavid Howells struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc,
269d2ddc776SDavid Howells const uuid_t *uuid)
2701da177e4SLinus Torvalds {
271d2ddc776SDavid Howells struct afs_ListAddrByAttributes__xdr *r;
272d2ddc776SDavid Howells const struct afs_uuid *u = (const struct afs_uuid *)uuid;
27308e0e7c8SDavid Howells struct afs_call *call;
2740a5143f2SDavid Howells struct afs_net *net = vc->cell->net;
2751da177e4SLinus Torvalds __be32 *bp;
276d2ddc776SDavid Howells int i;
2771da177e4SLinus Torvalds
27808e0e7c8SDavid Howells _enter("");
2791da177e4SLinus Torvalds
280d2ddc776SDavid Howells call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU,
281d2ddc776SDavid Howells sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr),
282d2ddc776SDavid Howells sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
28308e0e7c8SDavid Howells if (!call)
284d2ddc776SDavid Howells return ERR_PTR(-ENOMEM);
2851da177e4SLinus Torvalds
2860a5143f2SDavid Howells call->key = vc->key;
287ffba718eSDavid Howells call->ret_alist = NULL;
28894f699c9SDavid Howells call->max_lifespan = AFS_VL_MAX_LIFESPAN;
2891da177e4SLinus Torvalds
290d2ddc776SDavid Howells /* Marshall the parameters */
29108e0e7c8SDavid Howells bp = call->request;
292d2ddc776SDavid Howells *bp++ = htonl(VLGETADDRSU);
293d2ddc776SDavid Howells r = (struct afs_ListAddrByAttributes__xdr *)bp;
294d2ddc776SDavid Howells r->Mask = htonl(AFS_VLADDR_UUID);
295d2ddc776SDavid Howells r->ipaddr = 0;
296d2ddc776SDavid Howells r->index = 0;
297d2ddc776SDavid Howells r->spare = 0;
298d2ddc776SDavid Howells r->uuid.time_low = u->time_low;
299d2ddc776SDavid Howells r->uuid.time_mid = htonl(ntohs(u->time_mid));
300d2ddc776SDavid Howells r->uuid.time_hi_and_version = htonl(ntohs(u->time_hi_and_version));
301d2ddc776SDavid Howells r->uuid.clock_seq_hi_and_reserved = htonl(u->clock_seq_hi_and_reserved);
302d2ddc776SDavid Howells r->uuid.clock_seq_low = htonl(u->clock_seq_low);
303d2ddc776SDavid Howells for (i = 0; i < 6; i++)
304fe342cf7SDavid Howells r->uuid.node[i] = htonl(u->node[i]);
3051da177e4SLinus Torvalds
306025db80cSDavid Howells trace_afs_make_vl_call(call);
3070b9bf381SDavid Howells afs_make_call(&vc->ac, call, GFP_KERNEL);
3080b9bf381SDavid Howells return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
309ec26815aSDavid Howells }
310bf99a53cSDavid Howells
311bf99a53cSDavid Howells /*
312bf99a53cSDavid Howells * Deliver reply data to an VL.GetCapabilities operation.
313bf99a53cSDavid Howells */
afs_deliver_vl_get_capabilities(struct afs_call * call)314bf99a53cSDavid Howells static int afs_deliver_vl_get_capabilities(struct afs_call *call)
315bf99a53cSDavid Howells {
316bf99a53cSDavid Howells u32 count;
317bf99a53cSDavid Howells int ret;
318bf99a53cSDavid Howells
31912bdcf33SDavid Howells _enter("{%u,%zu/%u}",
320fc276122SDavid Howells call->unmarshall, iov_iter_count(call->iter), call->count);
321bf99a53cSDavid Howells
322bf99a53cSDavid Howells switch (call->unmarshall) {
323bf99a53cSDavid Howells case 0:
32412bdcf33SDavid Howells afs_extract_to_tmp(call);
325bf99a53cSDavid Howells call->unmarshall++;
326bf99a53cSDavid Howells
327df561f66SGustavo A. R. Silva fallthrough; /* and extract the capabilities word count */
328bf99a53cSDavid Howells case 1:
32912bdcf33SDavid Howells ret = afs_extract_data(call, true);
330bf99a53cSDavid Howells if (ret < 0)
331bf99a53cSDavid Howells return ret;
332bf99a53cSDavid Howells
333bf99a53cSDavid Howells count = ntohl(call->tmp);
334bf99a53cSDavid Howells call->count = count;
335bf99a53cSDavid Howells call->count2 = count;
33612bdcf33SDavid Howells
337bf99a53cSDavid Howells call->unmarshall++;
33812bdcf33SDavid Howells afs_extract_discard(call, count * sizeof(__be32));
339bf99a53cSDavid Howells
340df561f66SGustavo A. R. Silva fallthrough; /* and extract capabilities words */
341bf99a53cSDavid Howells case 2:
34212bdcf33SDavid Howells ret = afs_extract_data(call, false);
343bf99a53cSDavid Howells if (ret < 0)
344bf99a53cSDavid Howells return ret;
345bf99a53cSDavid Howells
346bf99a53cSDavid Howells /* TODO: Examine capabilities */
347bf99a53cSDavid Howells
348bf99a53cSDavid Howells call->unmarshall++;
349bf99a53cSDavid Howells break;
350bf99a53cSDavid Howells }
351bf99a53cSDavid Howells
352bf99a53cSDavid Howells _leave(" = 0 [done]");
353bf99a53cSDavid Howells return 0;
354bf99a53cSDavid Howells }
355bf99a53cSDavid Howells
afs_destroy_vl_get_capabilities(struct afs_call * call)3563bf0fb6fSDavid Howells static void afs_destroy_vl_get_capabilities(struct afs_call *call)
3573bf0fb6fSDavid Howells {
358ffba718eSDavid Howells afs_put_vlserver(call->net, call->vlserver);
3593bf0fb6fSDavid Howells afs_flat_call_destructor(call);
3603bf0fb6fSDavid Howells }
3613bf0fb6fSDavid Howells
362bf99a53cSDavid Howells /*
363bf99a53cSDavid Howells * VL.GetCapabilities operation type
364bf99a53cSDavid Howells */
365bf99a53cSDavid Howells static const struct afs_call_type afs_RXVLGetCapabilities = {
366bf99a53cSDavid Howells .name = "VL.GetCapabilities",
367025db80cSDavid Howells .op = afs_VL_GetCapabilities,
368bf99a53cSDavid Howells .deliver = afs_deliver_vl_get_capabilities,
3693bf0fb6fSDavid Howells .done = afs_vlserver_probe_result,
3703bf0fb6fSDavid Howells .destructor = afs_destroy_vl_get_capabilities,
371bf99a53cSDavid Howells };
372bf99a53cSDavid Howells
373bf99a53cSDavid Howells /*
3740a5143f2SDavid Howells * Probe a volume server for the capabilities that it supports. This can
375bf99a53cSDavid Howells * return up to 196 words.
376bf99a53cSDavid Howells *
377bf99a53cSDavid Howells * We use this to probe for service upgrade to determine what the server at the
378bf99a53cSDavid Howells * other end supports.
379bf99a53cSDavid Howells */
afs_vl_get_capabilities(struct afs_net * net,struct afs_addr_cursor * ac,struct key * key,struct afs_vlserver * server,unsigned int server_index)3800b9bf381SDavid Howells struct afs_call *afs_vl_get_capabilities(struct afs_net *net,
3813bf0fb6fSDavid Howells struct afs_addr_cursor *ac,
3823bf0fb6fSDavid Howells struct key *key,
3833bf0fb6fSDavid Howells struct afs_vlserver *server,
3840b9bf381SDavid Howells unsigned int server_index)
385bf99a53cSDavid Howells {
386bf99a53cSDavid Howells struct afs_call *call;
387bf99a53cSDavid Howells __be32 *bp;
388bf99a53cSDavid Howells
389bf99a53cSDavid Howells _enter("");
390bf99a53cSDavid Howells
391bf99a53cSDavid Howells call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4);
392bf99a53cSDavid Howells if (!call)
3930b9bf381SDavid Howells return ERR_PTR(-ENOMEM);
394bf99a53cSDavid Howells
395bf99a53cSDavid Howells call->key = key;
396ffba718eSDavid Howells call->vlserver = afs_get_vlserver(server);
397ffba718eSDavid Howells call->server_index = server_index;
3983bf0fb6fSDavid Howells call->upgrade = true;
3990b9bf381SDavid Howells call->async = true;
40094f699c9SDavid Howells call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
401bf99a53cSDavid Howells
402bf99a53cSDavid Howells /* marshall the parameters */
403bf99a53cSDavid Howells bp = call->request;
404bf99a53cSDavid Howells *bp++ = htonl(VLGETCAPABILITIES);
405bf99a53cSDavid Howells
406bf99a53cSDavid Howells /* Can't take a ref on server */
407025db80cSDavid Howells trace_afs_make_vl_call(call);
4080b9bf381SDavid Howells afs_make_call(ac, call, GFP_KERNEL);
4090b9bf381SDavid Howells return call;
410bf99a53cSDavid Howells }
411bf99a53cSDavid Howells
412bf99a53cSDavid Howells /*
413bf99a53cSDavid Howells * Deliver reply data to a YFSVL.GetEndpoints call.
414bf99a53cSDavid Howells *
415bf99a53cSDavid Howells * GetEndpoints(IN yfsServerAttributes *attr,
416bf99a53cSDavid Howells * OUT opr_uuid *uuid,
417bf99a53cSDavid Howells * OUT afs_int32 *uniquifier,
418bf99a53cSDavid Howells * OUT endpoints *fsEndpoints,
419bf99a53cSDavid Howells * OUT endpoints *volEndpoints)
420bf99a53cSDavid Howells */
afs_deliver_yfsvl_get_endpoints(struct afs_call * call)421bf99a53cSDavid Howells static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
422bf99a53cSDavid Howells {
423bf99a53cSDavid Howells struct afs_addr_list *alist;
424bf99a53cSDavid Howells __be32 *bp;
425bf99a53cSDavid Howells u32 uniquifier, size;
426bf99a53cSDavid Howells int ret;
427bf99a53cSDavid Howells
42812bdcf33SDavid Howells _enter("{%u,%zu,%u}",
429fc276122SDavid Howells call->unmarshall, iov_iter_count(call->iter), call->count2);
430bf99a53cSDavid Howells
431bf99a53cSDavid Howells switch (call->unmarshall) {
432bf99a53cSDavid Howells case 0:
43312bdcf33SDavid Howells afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32));
434bf99a53cSDavid Howells call->unmarshall = 1;
435bf99a53cSDavid Howells
436bf99a53cSDavid Howells /* Extract the returned uuid, uniquifier, fsEndpoints count and
437bf99a53cSDavid Howells * either the first fsEndpoint type or the volEndpoints
438bf99a53cSDavid Howells * count if there are no fsEndpoints. */
439df561f66SGustavo A. R. Silva fallthrough;
440bf99a53cSDavid Howells case 1:
44112bdcf33SDavid Howells ret = afs_extract_data(call, true);
442bf99a53cSDavid Howells if (ret < 0)
443bf99a53cSDavid Howells return ret;
444bf99a53cSDavid Howells
445bf99a53cSDavid Howells bp = call->buffer + sizeof(uuid_t);
446bf99a53cSDavid Howells uniquifier = ntohl(*bp++);
447bf99a53cSDavid Howells call->count = ntohl(*bp++);
448bf99a53cSDavid Howells call->count2 = ntohl(*bp); /* Type or next count */
449bf99a53cSDavid Howells
450bf99a53cSDavid Howells if (call->count > YFS_MAXENDPOINTS)
4517126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_yvl_fsendpt_num);
452bf99a53cSDavid Howells
453bf99a53cSDavid Howells alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT);
454bf99a53cSDavid Howells if (!alist)
455bf99a53cSDavid Howells return -ENOMEM;
456bf99a53cSDavid Howells alist->version = uniquifier;
457ffba718eSDavid Howells call->ret_alist = alist;
458bf99a53cSDavid Howells
459bf99a53cSDavid Howells if (call->count == 0)
460bf99a53cSDavid Howells goto extract_volendpoints;
461bf99a53cSDavid Howells
46212bdcf33SDavid Howells next_fsendpoint:
463bf99a53cSDavid Howells switch (call->count2) {
464bf99a53cSDavid Howells case YFS_ENDPOINT_IPV4:
465bf99a53cSDavid Howells size = sizeof(__be32) * (1 + 1 + 1);
466bf99a53cSDavid Howells break;
467bf99a53cSDavid Howells case YFS_ENDPOINT_IPV6:
468bf99a53cSDavid Howells size = sizeof(__be32) * (1 + 4 + 1);
469bf99a53cSDavid Howells break;
470bf99a53cSDavid Howells default:
4717126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_yvl_fsendpt_type);
472bf99a53cSDavid Howells }
473bf99a53cSDavid Howells
474bf99a53cSDavid Howells size += sizeof(__be32);
47512bdcf33SDavid Howells afs_extract_to_buf(call, size);
47612bdcf33SDavid Howells call->unmarshall = 2;
47712bdcf33SDavid Howells
478df561f66SGustavo A. R. Silva fallthrough; /* and extract fsEndpoints[] entries */
47912bdcf33SDavid Howells case 2:
48012bdcf33SDavid Howells ret = afs_extract_data(call, true);
481bf99a53cSDavid Howells if (ret < 0)
482bf99a53cSDavid Howells return ret;
483bf99a53cSDavid Howells
484ffba718eSDavid Howells alist = call->ret_alist;
485bf99a53cSDavid Howells bp = call->buffer;
486bf99a53cSDavid Howells switch (call->count2) {
487bf99a53cSDavid Howells case YFS_ENDPOINT_IPV4:
488bf99a53cSDavid Howells if (ntohl(bp[0]) != sizeof(__be32) * 2)
4897126ead9SDavid Howells return afs_protocol_error(
4907126ead9SDavid Howells call, afs_eproto_yvl_fsendpt4_len);
491bf99a53cSDavid Howells afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2]));
492bf99a53cSDavid Howells bp += 3;
493bf99a53cSDavid Howells break;
494bf99a53cSDavid Howells case YFS_ENDPOINT_IPV6:
495bf99a53cSDavid Howells if (ntohl(bp[0]) != sizeof(__be32) * 5)
4967126ead9SDavid Howells return afs_protocol_error(
4977126ead9SDavid Howells call, afs_eproto_yvl_fsendpt6_len);
498bf99a53cSDavid Howells afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5]));
499bf99a53cSDavid Howells bp += 6;
500bf99a53cSDavid Howells break;
501bf99a53cSDavid Howells default:
5027126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_yvl_fsendpt_type);
503bf99a53cSDavid Howells }
504bf99a53cSDavid Howells
505bf99a53cSDavid Howells /* Got either the type of the next entry or the count of
506bf99a53cSDavid Howells * volEndpoints if no more fsEndpoints.
507bf99a53cSDavid Howells */
508fe342cf7SDavid Howells call->count2 = ntohl(*bp++);
509bf99a53cSDavid Howells
510bf99a53cSDavid Howells call->count--;
511bf99a53cSDavid Howells if (call->count > 0)
51212bdcf33SDavid Howells goto next_fsendpoint;
513bf99a53cSDavid Howells
514bf99a53cSDavid Howells extract_volendpoints:
515bf99a53cSDavid Howells /* Extract the list of volEndpoints. */
516bf99a53cSDavid Howells call->count = call->count2;
517bf99a53cSDavid Howells if (!call->count)
518bf99a53cSDavid Howells goto end;
519bf99a53cSDavid Howells if (call->count > YFS_MAXENDPOINTS)
5207126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);
521bf99a53cSDavid Howells
52212bdcf33SDavid Howells afs_extract_to_buf(call, 1 * sizeof(__be32));
523bf99a53cSDavid Howells call->unmarshall = 3;
524bf99a53cSDavid Howells
525bf99a53cSDavid Howells /* Extract the type of volEndpoints[0]. Normally we would
526bf99a53cSDavid Howells * extract the type of the next endpoint when we extract the
527bf99a53cSDavid Howells * data of the current one, but this is the first...
528bf99a53cSDavid Howells */
529df561f66SGustavo A. R. Silva fallthrough;
530bf99a53cSDavid Howells case 3:
53112bdcf33SDavid Howells ret = afs_extract_data(call, true);
532bf99a53cSDavid Howells if (ret < 0)
533bf99a53cSDavid Howells return ret;
534bf99a53cSDavid Howells
535bf99a53cSDavid Howells bp = call->buffer;
536bf99a53cSDavid Howells
53712bdcf33SDavid Howells next_volendpoint:
53812bdcf33SDavid Howells call->count2 = ntohl(*bp++);
539bf99a53cSDavid Howells switch (call->count2) {
540bf99a53cSDavid Howells case YFS_ENDPOINT_IPV4:
541bf99a53cSDavid Howells size = sizeof(__be32) * (1 + 1 + 1);
542bf99a53cSDavid Howells break;
543bf99a53cSDavid Howells case YFS_ENDPOINT_IPV6:
544bf99a53cSDavid Howells size = sizeof(__be32) * (1 + 4 + 1);
545bf99a53cSDavid Howells break;
546bf99a53cSDavid Howells default:
5477126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);
548bf99a53cSDavid Howells }
549bf99a53cSDavid Howells
550bf99a53cSDavid Howells if (call->count > 1)
55112bdcf33SDavid Howells size += sizeof(__be32); /* Get next type too */
55212bdcf33SDavid Howells afs_extract_to_buf(call, size);
55312bdcf33SDavid Howells call->unmarshall = 4;
55412bdcf33SDavid Howells
555df561f66SGustavo A. R. Silva fallthrough; /* and extract volEndpoints[] entries */
55612bdcf33SDavid Howells case 4:
55712bdcf33SDavid Howells ret = afs_extract_data(call, true);
558bf99a53cSDavid Howells if (ret < 0)
559bf99a53cSDavid Howells return ret;
560bf99a53cSDavid Howells
561bf99a53cSDavid Howells bp = call->buffer;
562bf99a53cSDavid Howells switch (call->count2) {
563bf99a53cSDavid Howells case YFS_ENDPOINT_IPV4:
564bf99a53cSDavid Howells if (ntohl(bp[0]) != sizeof(__be32) * 2)
5657126ead9SDavid Howells return afs_protocol_error(
5667126ead9SDavid Howells call, afs_eproto_yvl_vlendpt4_len);
567bf99a53cSDavid Howells bp += 3;
568bf99a53cSDavid Howells break;
569bf99a53cSDavid Howells case YFS_ENDPOINT_IPV6:
570bf99a53cSDavid Howells if (ntohl(bp[0]) != sizeof(__be32) * 5)
5717126ead9SDavid Howells return afs_protocol_error(
5727126ead9SDavid Howells call, afs_eproto_yvl_vlendpt6_len);
573bf99a53cSDavid Howells bp += 6;
574bf99a53cSDavid Howells break;
575bf99a53cSDavid Howells default:
5767126ead9SDavid Howells return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);
577bf99a53cSDavid Howells }
578bf99a53cSDavid Howells
579bf99a53cSDavid Howells /* Got either the type of the next entry or the count of
580bf99a53cSDavid Howells * volEndpoints if no more fsEndpoints.
581bf99a53cSDavid Howells */
582bf99a53cSDavid Howells call->count--;
58312bdcf33SDavid Howells if (call->count > 0)
58412bdcf33SDavid Howells goto next_volendpoint;
585bf99a53cSDavid Howells
586bf99a53cSDavid Howells end:
58712bdcf33SDavid Howells afs_extract_discard(call, 0);
588bf99a53cSDavid Howells call->unmarshall = 5;
589bf99a53cSDavid Howells
590df561f66SGustavo A. R. Silva fallthrough; /* Done */
591bf99a53cSDavid Howells case 5:
59212bdcf33SDavid Howells ret = afs_extract_data(call, false);
593bf99a53cSDavid Howells if (ret < 0)
594bf99a53cSDavid Howells return ret;
595bf99a53cSDavid Howells call->unmarshall = 6;
596b2db6c35SGustavo A. R. Silva fallthrough;
597bf99a53cSDavid Howells
598bf99a53cSDavid Howells case 6:
599bf99a53cSDavid Howells break;
600bf99a53cSDavid Howells }
601bf99a53cSDavid Howells
602bf99a53cSDavid Howells _leave(" = 0 [done]");
603bf99a53cSDavid Howells return 0;
604bf99a53cSDavid Howells }
605bf99a53cSDavid Howells
606bf99a53cSDavid Howells /*
607bf99a53cSDavid Howells * YFSVL.GetEndpoints operation type.
608bf99a53cSDavid Howells */
609bf99a53cSDavid Howells static const struct afs_call_type afs_YFSVLGetEndpoints = {
610025db80cSDavid Howells .name = "YFSVL.GetEndpoints",
611025db80cSDavid Howells .op = afs_YFSVL_GetEndpoints,
612bf99a53cSDavid Howells .deliver = afs_deliver_yfsvl_get_endpoints,
613bf99a53cSDavid Howells .destructor = afs_vl_get_addrs_u_destructor,
614bf99a53cSDavid Howells };
615bf99a53cSDavid Howells
616bf99a53cSDavid Howells /*
617bf99a53cSDavid Howells * Dispatch an operation to get the addresses for a server, where the server is
618bf99a53cSDavid Howells * nominated by UUID.
619bf99a53cSDavid Howells */
afs_yfsvl_get_endpoints(struct afs_vl_cursor * vc,const uuid_t * uuid)6200a5143f2SDavid Howells struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc,
621bf99a53cSDavid Howells const uuid_t *uuid)
622bf99a53cSDavid Howells {
623bf99a53cSDavid Howells struct afs_call *call;
6240a5143f2SDavid Howells struct afs_net *net = vc->cell->net;
625bf99a53cSDavid Howells __be32 *bp;
626bf99a53cSDavid Howells
627bf99a53cSDavid Howells _enter("");
628bf99a53cSDavid Howells
629bf99a53cSDavid Howells call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints,
630bf99a53cSDavid Howells sizeof(__be32) * 2 + sizeof(*uuid),
631bf99a53cSDavid Howells sizeof(struct in6_addr) + sizeof(__be32) * 3);
632bf99a53cSDavid Howells if (!call)
633bf99a53cSDavid Howells return ERR_PTR(-ENOMEM);
634bf99a53cSDavid Howells
6350a5143f2SDavid Howells call->key = vc->key;
636ffba718eSDavid Howells call->ret_alist = NULL;
63794f699c9SDavid Howells call->max_lifespan = AFS_VL_MAX_LIFESPAN;
638bf99a53cSDavid Howells
639bf99a53cSDavid Howells /* Marshall the parameters */
640bf99a53cSDavid Howells bp = call->request;
641bf99a53cSDavid Howells *bp++ = htonl(YVLGETENDPOINTS);
642bf99a53cSDavid Howells *bp++ = htonl(YFS_SERVER_UUID);
643bf99a53cSDavid Howells memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */
644bf99a53cSDavid Howells
645025db80cSDavid Howells trace_afs_make_vl_call(call);
6460b9bf381SDavid Howells afs_make_call(&vc->ac, call, GFP_KERNEL);
6470b9bf381SDavid Howells return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
648bf99a53cSDavid Howells }
649c3e9f888SDavid Howells
650c3e9f888SDavid Howells /*
651c3e9f888SDavid Howells * Deliver reply data to a YFSVL.GetCellName operation.
652c3e9f888SDavid Howells */
afs_deliver_yfsvl_get_cell_name(struct afs_call * call)653c3e9f888SDavid Howells static int afs_deliver_yfsvl_get_cell_name(struct afs_call *call)
654c3e9f888SDavid Howells {
655c3e9f888SDavid Howells char *cell_name;
656c3e9f888SDavid Howells u32 namesz, paddedsz;
657c3e9f888SDavid Howells int ret;
658c3e9f888SDavid Howells
659c3e9f888SDavid Howells _enter("{%u,%zu/%u}",
660c3e9f888SDavid Howells call->unmarshall, iov_iter_count(call->iter), call->count);
661c3e9f888SDavid Howells
662c3e9f888SDavid Howells switch (call->unmarshall) {
663c3e9f888SDavid Howells case 0:
664c3e9f888SDavid Howells afs_extract_to_tmp(call);
665c3e9f888SDavid Howells call->unmarshall++;
666c3e9f888SDavid Howells
667df561f66SGustavo A. R. Silva fallthrough; /* and extract the cell name length */
668c3e9f888SDavid Howells case 1:
669c3e9f888SDavid Howells ret = afs_extract_data(call, true);
670c3e9f888SDavid Howells if (ret < 0)
671c3e9f888SDavid Howells return ret;
672c3e9f888SDavid Howells
673c3e9f888SDavid Howells namesz = ntohl(call->tmp);
674*7673030eSDavid Howells if (namesz > YFS_VL_MAXCELLNAME)
675c3e9f888SDavid Howells return afs_protocol_error(call, afs_eproto_cellname_len);
676c3e9f888SDavid Howells paddedsz = (namesz + 3) & ~3;
677c3e9f888SDavid Howells call->count = namesz;
678c3e9f888SDavid Howells call->count2 = paddedsz - namesz;
679c3e9f888SDavid Howells
680c3e9f888SDavid Howells cell_name = kmalloc(namesz + 1, GFP_KERNEL);
681c3e9f888SDavid Howells if (!cell_name)
682c3e9f888SDavid Howells return -ENOMEM;
683c3e9f888SDavid Howells cell_name[namesz] = 0;
684c3e9f888SDavid Howells call->ret_str = cell_name;
685c3e9f888SDavid Howells
686c3e9f888SDavid Howells afs_extract_begin(call, cell_name, namesz);
687c3e9f888SDavid Howells call->unmarshall++;
688c3e9f888SDavid Howells
689df561f66SGustavo A. R. Silva fallthrough; /* and extract cell name */
690c3e9f888SDavid Howells case 2:
691c3e9f888SDavid Howells ret = afs_extract_data(call, true);
692c3e9f888SDavid Howells if (ret < 0)
693c3e9f888SDavid Howells return ret;
694c3e9f888SDavid Howells
695c3e9f888SDavid Howells afs_extract_discard(call, call->count2);
696c3e9f888SDavid Howells call->unmarshall++;
697c3e9f888SDavid Howells
698df561f66SGustavo A. R. Silva fallthrough; /* and extract padding */
699c3e9f888SDavid Howells case 3:
700c3e9f888SDavid Howells ret = afs_extract_data(call, false);
701c3e9f888SDavid Howells if (ret < 0)
702c3e9f888SDavid Howells return ret;
703c3e9f888SDavid Howells
704c3e9f888SDavid Howells call->unmarshall++;
705c3e9f888SDavid Howells break;
706c3e9f888SDavid Howells }
707c3e9f888SDavid Howells
708c3e9f888SDavid Howells _leave(" = 0 [done]");
709c3e9f888SDavid Howells return 0;
710c3e9f888SDavid Howells }
711c3e9f888SDavid Howells
afs_destroy_yfsvl_get_cell_name(struct afs_call * call)712c3e9f888SDavid Howells static void afs_destroy_yfsvl_get_cell_name(struct afs_call *call)
713c3e9f888SDavid Howells {
714c3e9f888SDavid Howells kfree(call->ret_str);
715c3e9f888SDavid Howells afs_flat_call_destructor(call);
716c3e9f888SDavid Howells }
717c3e9f888SDavid Howells
718c3e9f888SDavid Howells /*
719c3e9f888SDavid Howells * VL.GetCapabilities operation type
720c3e9f888SDavid Howells */
721c3e9f888SDavid Howells static const struct afs_call_type afs_YFSVLGetCellName = {
722c3e9f888SDavid Howells .name = "YFSVL.GetCellName",
723c3e9f888SDavid Howells .op = afs_YFSVL_GetCellName,
724c3e9f888SDavid Howells .deliver = afs_deliver_yfsvl_get_cell_name,
725c3e9f888SDavid Howells .destructor = afs_destroy_yfsvl_get_cell_name,
726c3e9f888SDavid Howells };
727c3e9f888SDavid Howells
728c3e9f888SDavid Howells /*
729c3e9f888SDavid Howells * Probe a volume server for the capabilities that it supports. This can
730c3e9f888SDavid Howells * return up to 196 words.
731c3e9f888SDavid Howells *
732c3e9f888SDavid Howells * We use this to probe for service upgrade to determine what the server at the
733c3e9f888SDavid Howells * other end supports.
734c3e9f888SDavid Howells */
afs_yfsvl_get_cell_name(struct afs_vl_cursor * vc)735c3e9f888SDavid Howells char *afs_yfsvl_get_cell_name(struct afs_vl_cursor *vc)
736c3e9f888SDavid Howells {
737c3e9f888SDavid Howells struct afs_call *call;
738c3e9f888SDavid Howells struct afs_net *net = vc->cell->net;
739c3e9f888SDavid Howells __be32 *bp;
740c3e9f888SDavid Howells
741c3e9f888SDavid Howells _enter("");
742c3e9f888SDavid Howells
743c3e9f888SDavid Howells call = afs_alloc_flat_call(net, &afs_YFSVLGetCellName, 1 * 4, 0);
744c3e9f888SDavid Howells if (!call)
745c3e9f888SDavid Howells return ERR_PTR(-ENOMEM);
746c3e9f888SDavid Howells
747c3e9f888SDavid Howells call->key = vc->key;
748c3e9f888SDavid Howells call->ret_str = NULL;
749c3e9f888SDavid Howells call->max_lifespan = AFS_VL_MAX_LIFESPAN;
750c3e9f888SDavid Howells
751c3e9f888SDavid Howells /* marshall the parameters */
752c3e9f888SDavid Howells bp = call->request;
753c3e9f888SDavid Howells *bp++ = htonl(YVLGETCELLNAME);
754c3e9f888SDavid Howells
755c3e9f888SDavid Howells /* Can't take a ref on server */
756c3e9f888SDavid Howells trace_afs_make_vl_call(call);
757c3e9f888SDavid Howells afs_make_call(&vc->ac, call, GFP_KERNEL);
758c3e9f888SDavid Howells return (char *)afs_wait_for_call_to_complete(call, &vc->ac);
759c3e9f888SDavid Howells }
760