linux/fs/afs/vlclient.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* AFS Volume Location Service client
   3 *
   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        bool new_only = false;
  22        u32 tmp, nr_servers, vlflags;
  23        int i, ret;
  24
  25        _enter("");
  26
  27        ret = afs_transfer_reply(call);
  28        if (ret < 0)
  29                return ret;
  30
  31        /* unmarshall the reply once we've received all of it */
  32        uvldb = call->buffer;
  33        entry = call->ret_vldb;
  34
  35        nr_servers = ntohl(uvldb->nServers);
  36        if (nr_servers > AFS_NMAXNSERVERS)
  37                nr_servers = AFS_NMAXNSERVERS;
  38
  39        for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++)
  40                entry->name[i] = (u8)ntohl(uvldb->name[i]);
  41        entry->name[i] = 0;
  42        entry->name_len = strlen(entry->name);
  43
  44        /* If there is a new replication site that we can use, ignore all the
  45         * sites that aren't marked as new.
  46         */
  47        for (i = 0; i < nr_servers; i++) {
  48                tmp = ntohl(uvldb->serverFlags[i]);
  49                if (!(tmp & AFS_VLSF_DONTUSE) &&
  50                    (tmp & AFS_VLSF_NEWREPSITE))
  51                        new_only = true;
  52        }
  53
  54        vlflags = ntohl(uvldb->flags);
  55        for (i = 0; i < nr_servers; i++) {
  56                struct afs_uuid__xdr *xdr;
  57                struct afs_uuid *uuid;
  58                int j;
  59                int n = entry->nr_servers;
  60
  61                tmp = ntohl(uvldb->serverFlags[i]);
  62                if (tmp & AFS_VLSF_DONTUSE ||
  63                    (new_only && !(tmp & AFS_VLSF_NEWREPSITE)))
  64                        continue;
  65                if (tmp & AFS_VLSF_RWVOL) {
  66                        entry->fs_mask[n] |= AFS_VOL_VTM_RW;
  67                        if (vlflags & AFS_VLF_BACKEXISTS)
  68                                entry->fs_mask[n] |= AFS_VOL_VTM_BAK;
  69                }
  70                if (tmp & AFS_VLSF_ROVOL)
  71                        entry->fs_mask[n] |= AFS_VOL_VTM_RO;
  72                if (!entry->fs_mask[n])
  73                        continue;
  74
  75                xdr = &uvldb->serverNumber[i];
  76                uuid = (struct afs_uuid *)&entry->fs_server[n];
  77                uuid->time_low                  = xdr->time_low;
  78                uuid->time_mid                  = htons(ntohl(xdr->time_mid));
  79                uuid->time_hi_and_version       = htons(ntohl(xdr->time_hi_and_version));
  80                uuid->clock_seq_hi_and_reserved = (u8)ntohl(xdr->clock_seq_hi_and_reserved);
  81                uuid->clock_seq_low             = (u8)ntohl(xdr->clock_seq_low);
  82                for (j = 0; j < 6; j++)
  83                        uuid->node[j] = (u8)ntohl(xdr->node[j]);
  84
  85                entry->nr_servers++;
  86        }
  87
  88        for (i = 0; i < AFS_MAXTYPES; i++)
  89                entry->vid[i] = ntohl(uvldb->volumeId[i]);
  90
  91        if (vlflags & AFS_VLF_RWEXISTS)
  92                __set_bit(AFS_VLDB_HAS_RW, &entry->flags);
  93        if (vlflags & AFS_VLF_ROEXISTS)
  94                __set_bit(AFS_VLDB_HAS_RO, &entry->flags);
  95        if (vlflags & AFS_VLF_BACKEXISTS)
  96                __set_bit(AFS_VLDB_HAS_BAK, &entry->flags);
  97
  98        if (!(vlflags & (AFS_VLF_RWEXISTS | AFS_VLF_ROEXISTS | AFS_VLF_BACKEXISTS))) {
  99                entry->error = -ENOMEDIUM;
 100                __set_bit(AFS_VLDB_QUERY_ERROR, &entry->flags);
 101        }
 102
 103        __set_bit(AFS_VLDB_QUERY_VALID, &entry->flags);
 104        _leave(" = 0 [done]");
 105        return 0;
 106}
 107
 108static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call)
 109{
 110        kfree(call->ret_vldb);
 111        afs_flat_call_destructor(call);
 112}
 113
 114/*
 115 * VL.GetEntryByNameU operation type.
 116 */
 117static const struct afs_call_type afs_RXVLGetEntryByNameU = {
 118        .name           = "VL.GetEntryByNameU",
 119        .op             = afs_VL_GetEntryByNameU,
 120        .deliver        = afs_deliver_vl_get_entry_by_name_u,
 121        .destructor     = afs_destroy_vl_get_entry_by_name_u,
 122};
 123
 124/*
 125 * Dispatch a get volume entry by name or ID operation (uuid variant).  If the
 126 * volname is a decimal number then it's a volume ID not a volume name.
 127 */
 128struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc,
 129                                                  const char *volname,
 130                                                  int volnamesz)
 131{
 132        struct afs_vldb_entry *entry;
 133        struct afs_call *call;
 134        struct afs_net *net = vc->cell->net;
 135        size_t reqsz, padsz;
 136        __be32 *bp;
 137
 138        _enter("");
 139
 140        padsz = (4 - (volnamesz & 3)) & 3;
 141        reqsz = 8 + volnamesz + padsz;
 142
 143        entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL);
 144        if (!entry)
 145                return ERR_PTR(-ENOMEM);
 146
 147        call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz,
 148                                   sizeof(struct afs_uvldbentry__xdr));
 149        if (!call) {
 150                kfree(entry);
 151                return ERR_PTR(-ENOMEM);
 152        }
 153
 154        call->key = vc->key;
 155        call->ret_vldb = entry;
 156        call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 157
 158        /* Marshall the parameters */
 159        bp = call->request;
 160        *bp++ = htonl(VLGETENTRYBYNAMEU);
 161        *bp++ = htonl(volnamesz);
 162        memcpy(bp, volname, volnamesz);
 163        if (padsz > 0)
 164                memset((void *)bp + volnamesz, 0, padsz);
 165
 166        trace_afs_make_vl_call(call);
 167        afs_make_call(&vc->ac, call, GFP_KERNEL);
 168        return (struct afs_vldb_entry *)afs_wait_for_call_to_complete(call, &vc->ac);
 169}
 170
 171/*
 172 * Deliver reply data to a VL.GetAddrsU call.
 173 *
 174 *      GetAddrsU(IN ListAddrByAttributes *inaddr,
 175 *                OUT afsUUID *uuidp1,
 176 *                OUT uint32_t *uniquifier,
 177 *                OUT uint32_t *nentries,
 178 *                OUT bulkaddrs *blkaddrs);
 179 */
 180static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
 181{
 182        struct afs_addr_list *alist;
 183        __be32 *bp;
 184        u32 uniquifier, nentries, count;
 185        int i, ret;
 186
 187        _enter("{%u,%zu/%u}",
 188               call->unmarshall, iov_iter_count(call->iter), call->count);
 189
 190        switch (call->unmarshall) {
 191        case 0:
 192                afs_extract_to_buf(call,
 193                                   sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
 194                call->unmarshall++;
 195
 196                /* Extract the returned uuid, uniquifier, nentries and
 197                 * blkaddrs size */
 198                /* Fall through */
 199        case 1:
 200                ret = afs_extract_data(call, true);
 201                if (ret < 0)
 202                        return ret;
 203
 204                bp = call->buffer + sizeof(struct afs_uuid__xdr);
 205                uniquifier      = ntohl(*bp++);
 206                nentries        = ntohl(*bp++);
 207                count           = ntohl(*bp);
 208
 209                nentries = min(nentries, count);
 210                alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT);
 211                if (!alist)
 212                        return -ENOMEM;
 213                alist->version = uniquifier;
 214                call->ret_alist = alist;
 215                call->count = count;
 216                call->count2 = nentries;
 217                call->unmarshall++;
 218
 219        more_entries:
 220                count = min(call->count, 4U);
 221                afs_extract_to_buf(call, count * sizeof(__be32));
 222
 223                /* Fall through - and extract entries */
 224        case 2:
 225                ret = afs_extract_data(call, call->count > 4);
 226                if (ret < 0)
 227                        return ret;
 228
 229                alist = call->ret_alist;
 230                bp = call->buffer;
 231                count = min(call->count, 4U);
 232                for (i = 0; i < count; i++)
 233                        if (alist->nr_addrs < call->count2)
 234                                afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT);
 235
 236                call->count -= count;
 237                if (call->count > 0)
 238                        goto more_entries;
 239                call->unmarshall++;
 240                break;
 241        }
 242
 243        _leave(" = 0 [done]");
 244        return 0;
 245}
 246
 247static void afs_vl_get_addrs_u_destructor(struct afs_call *call)
 248{
 249        afs_put_addrlist(call->ret_alist);
 250        return afs_flat_call_destructor(call);
 251}
 252
 253/*
 254 * VL.GetAddrsU operation type.
 255 */
 256static const struct afs_call_type afs_RXVLGetAddrsU = {
 257        .name           = "VL.GetAddrsU",
 258        .op             = afs_VL_GetAddrsU,
 259        .deliver        = afs_deliver_vl_get_addrs_u,
 260        .destructor     = afs_vl_get_addrs_u_destructor,
 261};
 262
 263/*
 264 * Dispatch an operation to get the addresses for a server, where the server is
 265 * nominated by UUID.
 266 */
 267struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc,
 268                                         const uuid_t *uuid)
 269{
 270        struct afs_ListAddrByAttributes__xdr *r;
 271        const struct afs_uuid *u = (const struct afs_uuid *)uuid;
 272        struct afs_call *call;
 273        struct afs_net *net = vc->cell->net;
 274        __be32 *bp;
 275        int i;
 276
 277        _enter("");
 278
 279        call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU,
 280                                   sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr),
 281                                   sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
 282        if (!call)
 283                return ERR_PTR(-ENOMEM);
 284
 285        call->key = vc->key;
 286        call->ret_alist = NULL;
 287        call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 288
 289        /* Marshall the parameters */
 290        bp = call->request;
 291        *bp++ = htonl(VLGETADDRSU);
 292        r = (struct afs_ListAddrByAttributes__xdr *)bp;
 293        r->Mask         = htonl(AFS_VLADDR_UUID);
 294        r->ipaddr       = 0;
 295        r->index        = 0;
 296        r->spare        = 0;
 297        r->uuid.time_low                        = u->time_low;
 298        r->uuid.time_mid                        = htonl(ntohs(u->time_mid));
 299        r->uuid.time_hi_and_version             = htonl(ntohs(u->time_hi_and_version));
 300        r->uuid.clock_seq_hi_and_reserved       = htonl(u->clock_seq_hi_and_reserved);
 301        r->uuid.clock_seq_low                   = htonl(u->clock_seq_low);
 302        for (i = 0; i < 6; i++)
 303                r->uuid.node[i] = htonl(u->node[i]);
 304
 305        trace_afs_make_vl_call(call);
 306        afs_make_call(&vc->ac, call, GFP_KERNEL);
 307        return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
 308}
 309
 310/*
 311 * Deliver reply data to an VL.GetCapabilities operation.
 312 */
 313static int afs_deliver_vl_get_capabilities(struct afs_call *call)
 314{
 315        u32 count;
 316        int ret;
 317
 318        _enter("{%u,%zu/%u}",
 319               call->unmarshall, iov_iter_count(call->iter), call->count);
 320
 321        switch (call->unmarshall) {
 322        case 0:
 323                afs_extract_to_tmp(call);
 324                call->unmarshall++;
 325
 326                /* Fall through - and extract the capabilities word count */
 327        case 1:
 328                ret = afs_extract_data(call, true);
 329                if (ret < 0)
 330                        return ret;
 331
 332                count = ntohl(call->tmp);
 333                call->count = count;
 334                call->count2 = count;
 335
 336                call->unmarshall++;
 337                afs_extract_discard(call, count * sizeof(__be32));
 338
 339                /* Fall through - and extract capabilities words */
 340        case 2:
 341                ret = afs_extract_data(call, false);
 342                if (ret < 0)
 343                        return ret;
 344
 345                /* TODO: Examine capabilities */
 346
 347                call->unmarshall++;
 348                break;
 349        }
 350
 351        _leave(" = 0 [done]");
 352        return 0;
 353}
 354
 355static void afs_destroy_vl_get_capabilities(struct afs_call *call)
 356{
 357        afs_put_vlserver(call->net, call->vlserver);
 358        afs_flat_call_destructor(call);
 359}
 360
 361/*
 362 * VL.GetCapabilities operation type
 363 */
 364static const struct afs_call_type afs_RXVLGetCapabilities = {
 365        .name           = "VL.GetCapabilities",
 366        .op             = afs_VL_GetCapabilities,
 367        .deliver        = afs_deliver_vl_get_capabilities,
 368        .done           = afs_vlserver_probe_result,
 369        .destructor     = afs_destroy_vl_get_capabilities,
 370};
 371
 372/*
 373 * Probe a volume server for the capabilities that it supports.  This can
 374 * return up to 196 words.
 375 *
 376 * We use this to probe for service upgrade to determine what the server at the
 377 * other end supports.
 378 */
 379struct afs_call *afs_vl_get_capabilities(struct afs_net *net,
 380                                         struct afs_addr_cursor *ac,
 381                                         struct key *key,
 382                                         struct afs_vlserver *server,
 383                                         unsigned int server_index)
 384{
 385        struct afs_call *call;
 386        __be32 *bp;
 387
 388        _enter("");
 389
 390        call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4);
 391        if (!call)
 392                return ERR_PTR(-ENOMEM);
 393
 394        call->key = key;
 395        call->vlserver = afs_get_vlserver(server);
 396        call->server_index = server_index;
 397        call->upgrade = true;
 398        call->async = true;
 399        call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
 400
 401        /* marshall the parameters */
 402        bp = call->request;
 403        *bp++ = htonl(VLGETCAPABILITIES);
 404
 405        /* Can't take a ref on server */
 406        trace_afs_make_vl_call(call);
 407        afs_make_call(ac, call, GFP_KERNEL);
 408        return call;
 409}
 410
 411/*
 412 * Deliver reply data to a YFSVL.GetEndpoints call.
 413 *
 414 *      GetEndpoints(IN yfsServerAttributes *attr,
 415 *                   OUT opr_uuid *uuid,
 416 *                   OUT afs_int32 *uniquifier,
 417 *                   OUT endpoints *fsEndpoints,
 418 *                   OUT endpoints *volEndpoints)
 419 */
 420static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
 421{
 422        struct afs_addr_list *alist;
 423        __be32 *bp;
 424        u32 uniquifier, size;
 425        int ret;
 426
 427        _enter("{%u,%zu,%u}",
 428               call->unmarshall, iov_iter_count(call->iter), call->count2);
 429
 430        switch (call->unmarshall) {
 431        case 0:
 432                afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32));
 433                call->unmarshall = 1;
 434
 435                /* Extract the returned uuid, uniquifier, fsEndpoints count and
 436                 * either the first fsEndpoint type or the volEndpoints
 437                 * count if there are no fsEndpoints. */
 438                /* Fall through */
 439        case 1:
 440                ret = afs_extract_data(call, true);
 441                if (ret < 0)
 442                        return ret;
 443
 444                bp = call->buffer + sizeof(uuid_t);
 445                uniquifier      = ntohl(*bp++);
 446                call->count     = ntohl(*bp++);
 447                call->count2    = ntohl(*bp); /* Type or next count */
 448
 449                if (call->count > YFS_MAXENDPOINTS)
 450                        return afs_protocol_error(call, -EBADMSG,
 451                                                  afs_eproto_yvl_fsendpt_num);
 452
 453                alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT);
 454                if (!alist)
 455                        return -ENOMEM;
 456                alist->version = uniquifier;
 457                call->ret_alist = alist;
 458
 459                if (call->count == 0)
 460                        goto extract_volendpoints;
 461
 462        next_fsendpoint:
 463                switch (call->count2) {
 464                case YFS_ENDPOINT_IPV4:
 465                        size = sizeof(__be32) * (1 + 1 + 1);
 466                        break;
 467                case YFS_ENDPOINT_IPV6:
 468                        size = sizeof(__be32) * (1 + 4 + 1);
 469                        break;
 470                default:
 471                        return afs_protocol_error(call, -EBADMSG,
 472                                                  afs_eproto_yvl_fsendpt_type);
 473                }
 474
 475                size += sizeof(__be32);
 476                afs_extract_to_buf(call, size);
 477                call->unmarshall = 2;
 478
 479                /* Fall through - and extract fsEndpoints[] entries */
 480        case 2:
 481                ret = afs_extract_data(call, true);
 482                if (ret < 0)
 483                        return ret;
 484
 485                alist = call->ret_alist;
 486                bp = call->buffer;
 487                switch (call->count2) {
 488                case YFS_ENDPOINT_IPV4:
 489                        if (ntohl(bp[0]) != sizeof(__be32) * 2)
 490                                return afs_protocol_error(call, -EBADMSG,
 491                                                          afs_eproto_yvl_fsendpt4_len);
 492                        afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2]));
 493                        bp += 3;
 494                        break;
 495                case YFS_ENDPOINT_IPV6:
 496                        if (ntohl(bp[0]) != sizeof(__be32) * 5)
 497                                return afs_protocol_error(call, -EBADMSG,
 498                                                          afs_eproto_yvl_fsendpt6_len);
 499                        afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5]));
 500                        bp += 6;
 501                        break;
 502                default:
 503                        return afs_protocol_error(call, -EBADMSG,
 504                                                  afs_eproto_yvl_fsendpt_type);
 505                }
 506
 507                /* Got either the type of the next entry or the count of
 508                 * volEndpoints if no more fsEndpoints.
 509                 */
 510                call->count2 = ntohl(*bp++);
 511
 512                call->count--;
 513                if (call->count > 0)
 514                        goto next_fsendpoint;
 515
 516        extract_volendpoints:
 517                /* Extract the list of volEndpoints. */
 518                call->count = call->count2;
 519                if (!call->count)
 520                        goto end;
 521                if (call->count > YFS_MAXENDPOINTS)
 522                        return afs_protocol_error(call, -EBADMSG,
 523                                                  afs_eproto_yvl_vlendpt_type);
 524
 525                afs_extract_to_buf(call, 1 * sizeof(__be32));
 526                call->unmarshall = 3;
 527
 528                /* Extract the type of volEndpoints[0].  Normally we would
 529                 * extract the type of the next endpoint when we extract the
 530                 * data of the current one, but this is the first...
 531                 */
 532                /* Fall through */
 533        case 3:
 534                ret = afs_extract_data(call, true);
 535                if (ret < 0)
 536                        return ret;
 537
 538                bp = call->buffer;
 539
 540        next_volendpoint:
 541                call->count2 = ntohl(*bp++);
 542                switch (call->count2) {
 543                case YFS_ENDPOINT_IPV4:
 544                        size = sizeof(__be32) * (1 + 1 + 1);
 545                        break;
 546                case YFS_ENDPOINT_IPV6:
 547                        size = sizeof(__be32) * (1 + 4 + 1);
 548                        break;
 549                default:
 550                        return afs_protocol_error(call, -EBADMSG,
 551                                                  afs_eproto_yvl_vlendpt_type);
 552                }
 553
 554                if (call->count > 1)
 555                        size += sizeof(__be32); /* Get next type too */
 556                afs_extract_to_buf(call, size);
 557                call->unmarshall = 4;
 558
 559                /* Fall through - and extract volEndpoints[] entries */
 560        case 4:
 561                ret = afs_extract_data(call, true);
 562                if (ret < 0)
 563                        return ret;
 564
 565                bp = call->buffer;
 566                switch (call->count2) {
 567                case YFS_ENDPOINT_IPV4:
 568                        if (ntohl(bp[0]) != sizeof(__be32) * 2)
 569                                return afs_protocol_error(call, -EBADMSG,
 570                                                          afs_eproto_yvl_vlendpt4_len);
 571                        bp += 3;
 572                        break;
 573                case YFS_ENDPOINT_IPV6:
 574                        if (ntohl(bp[0]) != sizeof(__be32) * 5)
 575                                return afs_protocol_error(call, -EBADMSG,
 576                                                          afs_eproto_yvl_vlendpt6_len);
 577                        bp += 6;
 578                        break;
 579                default:
 580                        return afs_protocol_error(call, -EBADMSG,
 581                                                  afs_eproto_yvl_vlendpt_type);
 582                }
 583
 584                /* Got either the type of the next entry or the count of
 585                 * volEndpoints if no more fsEndpoints.
 586                 */
 587                call->count--;
 588                if (call->count > 0)
 589                        goto next_volendpoint;
 590
 591        end:
 592                afs_extract_discard(call, 0);
 593                call->unmarshall = 5;
 594
 595                /* Fall through - Done */
 596        case 5:
 597                ret = afs_extract_data(call, false);
 598                if (ret < 0)
 599                        return ret;
 600                call->unmarshall = 6;
 601
 602        case 6:
 603                break;
 604        }
 605
 606        _leave(" = 0 [done]");
 607        return 0;
 608}
 609
 610/*
 611 * YFSVL.GetEndpoints operation type.
 612 */
 613static const struct afs_call_type afs_YFSVLGetEndpoints = {
 614        .name           = "YFSVL.GetEndpoints",
 615        .op             = afs_YFSVL_GetEndpoints,
 616        .deliver        = afs_deliver_yfsvl_get_endpoints,
 617        .destructor     = afs_vl_get_addrs_u_destructor,
 618};
 619
 620/*
 621 * Dispatch an operation to get the addresses for a server, where the server is
 622 * nominated by UUID.
 623 */
 624struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc,
 625                                              const uuid_t *uuid)
 626{
 627        struct afs_call *call;
 628        struct afs_net *net = vc->cell->net;
 629        __be32 *bp;
 630
 631        _enter("");
 632
 633        call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints,
 634                                   sizeof(__be32) * 2 + sizeof(*uuid),
 635                                   sizeof(struct in6_addr) + sizeof(__be32) * 3);
 636        if (!call)
 637                return ERR_PTR(-ENOMEM);
 638
 639        call->key = vc->key;
 640        call->ret_alist = NULL;
 641        call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 642
 643        /* Marshall the parameters */
 644        bp = call->request;
 645        *bp++ = htonl(YVLGETENDPOINTS);
 646        *bp++ = htonl(YFS_SERVER_UUID);
 647        memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */
 648
 649        trace_afs_make_vl_call(call);
 650        afs_make_call(&vc->ac, call, GFP_KERNEL);
 651        return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
 652}
 653