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->addr_version[n] = ntohl(uvldb->serverUnique[i]);
  86                entry->nr_servers++;
  87        }
  88
  89        for (i = 0; i < AFS_MAXTYPES; i++)
  90                entry->vid[i] = ntohl(uvldb->volumeId[i]);
  91
  92        if (vlflags & AFS_VLF_RWEXISTS)
  93                __set_bit(AFS_VLDB_HAS_RW, &entry->flags);
  94        if (vlflags & AFS_VLF_ROEXISTS)
  95                __set_bit(AFS_VLDB_HAS_RO, &entry->flags);
  96        if (vlflags & AFS_VLF_BACKEXISTS)
  97                __set_bit(AFS_VLDB_HAS_BAK, &entry->flags);
  98
  99        if (!(vlflags & (AFS_VLF_RWEXISTS | AFS_VLF_ROEXISTS | AFS_VLF_BACKEXISTS))) {
 100                entry->error = -ENOMEDIUM;
 101                __set_bit(AFS_VLDB_QUERY_ERROR, &entry->flags);
 102        }
 103
 104        __set_bit(AFS_VLDB_QUERY_VALID, &entry->flags);
 105        _leave(" = 0 [done]");
 106        return 0;
 107}
 108
 109static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call)
 110{
 111        kfree(call->ret_vldb);
 112        afs_flat_call_destructor(call);
 113}
 114
 115/*
 116 * VL.GetEntryByNameU operation type.
 117 */
 118static const struct afs_call_type afs_RXVLGetEntryByNameU = {
 119        .name           = "VL.GetEntryByNameU",
 120        .op             = afs_VL_GetEntryByNameU,
 121        .deliver        = afs_deliver_vl_get_entry_by_name_u,
 122        .destructor     = afs_destroy_vl_get_entry_by_name_u,
 123};
 124
 125/*
 126 * Dispatch a get volume entry by name or ID operation (uuid variant).  If the
 127 * volname is a decimal number then it's a volume ID not a volume name.
 128 */
 129struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc,
 130                                                  const char *volname,
 131                                                  int volnamesz)
 132{
 133        struct afs_vldb_entry *entry;
 134        struct afs_call *call;
 135        struct afs_net *net = vc->cell->net;
 136        size_t reqsz, padsz;
 137        __be32 *bp;
 138
 139        _enter("");
 140
 141        padsz = (4 - (volnamesz & 3)) & 3;
 142        reqsz = 8 + volnamesz + padsz;
 143
 144        entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL);
 145        if (!entry)
 146                return ERR_PTR(-ENOMEM);
 147
 148        call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz,
 149                                   sizeof(struct afs_uvldbentry__xdr));
 150        if (!call) {
 151                kfree(entry);
 152                return ERR_PTR(-ENOMEM);
 153        }
 154
 155        call->key = vc->key;
 156        call->ret_vldb = entry;
 157        call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 158
 159        /* Marshall the parameters */
 160        bp = call->request;
 161        *bp++ = htonl(VLGETENTRYBYNAMEU);
 162        *bp++ = htonl(volnamesz);
 163        memcpy(bp, volname, volnamesz);
 164        if (padsz > 0)
 165                memset((void *)bp + volnamesz, 0, padsz);
 166
 167        trace_afs_make_vl_call(call);
 168        afs_make_call(&vc->ac, call, GFP_KERNEL);
 169        return (struct afs_vldb_entry *)afs_wait_for_call_to_complete(call, &vc->ac);
 170}
 171
 172/*
 173 * Deliver reply data to a VL.GetAddrsU call.
 174 *
 175 *      GetAddrsU(IN ListAddrByAttributes *inaddr,
 176 *                OUT afsUUID *uuidp1,
 177 *                OUT uint32_t *uniquifier,
 178 *                OUT uint32_t *nentries,
 179 *                OUT bulkaddrs *blkaddrs);
 180 */
 181static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
 182{
 183        struct afs_addr_list *alist;
 184        __be32 *bp;
 185        u32 uniquifier, nentries, count;
 186        int i, ret;
 187
 188        _enter("{%u,%zu/%u}",
 189               call->unmarshall, iov_iter_count(call->iter), call->count);
 190
 191        switch (call->unmarshall) {
 192        case 0:
 193                afs_extract_to_buf(call,
 194                                   sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
 195                call->unmarshall++;
 196
 197                /* Extract the returned uuid, uniquifier, nentries and
 198                 * blkaddrs size */
 199                /* Fall through */
 200        case 1:
 201                ret = afs_extract_data(call, true);
 202                if (ret < 0)
 203                        return ret;
 204
 205                bp = call->buffer + sizeof(struct afs_uuid__xdr);
 206                uniquifier      = ntohl(*bp++);
 207                nentries        = ntohl(*bp++);
 208                count           = ntohl(*bp);
 209
 210                nentries = min(nentries, count);
 211                alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT);
 212                if (!alist)
 213                        return -ENOMEM;
 214                alist->version = uniquifier;
 215                call->ret_alist = alist;
 216                call->count = count;
 217                call->count2 = nentries;
 218                call->unmarshall++;
 219
 220        more_entries:
 221                count = min(call->count, 4U);
 222                afs_extract_to_buf(call, count * sizeof(__be32));
 223
 224                /* Fall through - and extract entries */
 225        case 2:
 226                ret = afs_extract_data(call, call->count > 4);
 227                if (ret < 0)
 228                        return ret;
 229
 230                alist = call->ret_alist;
 231                bp = call->buffer;
 232                count = min(call->count, 4U);
 233                for (i = 0; i < count; i++)
 234                        if (alist->nr_addrs < call->count2)
 235                                afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT);
 236
 237                call->count -= count;
 238                if (call->count > 0)
 239                        goto more_entries;
 240                call->unmarshall++;
 241                break;
 242        }
 243
 244        _leave(" = 0 [done]");
 245        return 0;
 246}
 247
 248static void afs_vl_get_addrs_u_destructor(struct afs_call *call)
 249{
 250        afs_put_addrlist(call->ret_alist);
 251        return afs_flat_call_destructor(call);
 252}
 253
 254/*
 255 * VL.GetAddrsU operation type.
 256 */
 257static const struct afs_call_type afs_RXVLGetAddrsU = {
 258        .name           = "VL.GetAddrsU",
 259        .op             = afs_VL_GetAddrsU,
 260        .deliver        = afs_deliver_vl_get_addrs_u,
 261        .destructor     = afs_vl_get_addrs_u_destructor,
 262};
 263
 264/*
 265 * Dispatch an operation to get the addresses for a server, where the server is
 266 * nominated by UUID.
 267 */
 268struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc,
 269                                         const uuid_t *uuid)
 270{
 271        struct afs_ListAddrByAttributes__xdr *r;
 272        const struct afs_uuid *u = (const struct afs_uuid *)uuid;
 273        struct afs_call *call;
 274        struct afs_net *net = vc->cell->net;
 275        __be32 *bp;
 276        int i;
 277
 278        _enter("");
 279
 280        call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU,
 281                                   sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr),
 282                                   sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
 283        if (!call)
 284                return ERR_PTR(-ENOMEM);
 285
 286        call->key = vc->key;
 287        call->ret_alist = NULL;
 288        call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 289
 290        /* Marshall the parameters */
 291        bp = call->request;
 292        *bp++ = htonl(VLGETADDRSU);
 293        r = (struct afs_ListAddrByAttributes__xdr *)bp;
 294        r->Mask         = htonl(AFS_VLADDR_UUID);
 295        r->ipaddr       = 0;
 296        r->index        = 0;
 297        r->spare        = 0;
 298        r->uuid.time_low                        = u->time_low;
 299        r->uuid.time_mid                        = htonl(ntohs(u->time_mid));
 300        r->uuid.time_hi_and_version             = htonl(ntohs(u->time_hi_and_version));
 301        r->uuid.clock_seq_hi_and_reserved       = htonl(u->clock_seq_hi_and_reserved);
 302        r->uuid.clock_seq_low                   = htonl(u->clock_seq_low);
 303        for (i = 0; i < 6; i++)
 304                r->uuid.node[i] = htonl(u->node[i]);
 305
 306        trace_afs_make_vl_call(call);
 307        afs_make_call(&vc->ac, call, GFP_KERNEL);
 308        return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
 309}
 310
 311/*
 312 * Deliver reply data to an VL.GetCapabilities operation.
 313 */
 314static int afs_deliver_vl_get_capabilities(struct afs_call *call)
 315{
 316        u32 count;
 317        int ret;
 318
 319        _enter("{%u,%zu/%u}",
 320               call->unmarshall, iov_iter_count(call->iter), call->count);
 321
 322        switch (call->unmarshall) {
 323        case 0:
 324                afs_extract_to_tmp(call);
 325                call->unmarshall++;
 326
 327                /* Fall through - and extract the capabilities word count */
 328        case 1:
 329                ret = afs_extract_data(call, true);
 330                if (ret < 0)
 331                        return ret;
 332
 333                count = ntohl(call->tmp);
 334                call->count = count;
 335                call->count2 = count;
 336
 337                call->unmarshall++;
 338                afs_extract_discard(call, count * sizeof(__be32));
 339
 340                /* Fall through - and extract capabilities words */
 341        case 2:
 342                ret = afs_extract_data(call, false);
 343                if (ret < 0)
 344                        return ret;
 345
 346                /* TODO: Examine capabilities */
 347
 348                call->unmarshall++;
 349                break;
 350        }
 351
 352        _leave(" = 0 [done]");
 353        return 0;
 354}
 355
 356static void afs_destroy_vl_get_capabilities(struct afs_call *call)
 357{
 358        afs_put_vlserver(call->net, call->vlserver);
 359        afs_flat_call_destructor(call);
 360}
 361
 362/*
 363 * VL.GetCapabilities operation type
 364 */
 365static const struct afs_call_type afs_RXVLGetCapabilities = {
 366        .name           = "VL.GetCapabilities",
 367        .op             = afs_VL_GetCapabilities,
 368        .deliver        = afs_deliver_vl_get_capabilities,
 369        .done           = afs_vlserver_probe_result,
 370        .destructor     = afs_destroy_vl_get_capabilities,
 371};
 372
 373/*
 374 * Probe a volume server for the capabilities that it supports.  This can
 375 * return up to 196 words.
 376 *
 377 * We use this to probe for service upgrade to determine what the server at the
 378 * other end supports.
 379 */
 380struct afs_call *afs_vl_get_capabilities(struct afs_net *net,
 381                                         struct afs_addr_cursor *ac,
 382                                         struct key *key,
 383                                         struct afs_vlserver *server,
 384                                         unsigned int server_index)
 385{
 386        struct afs_call *call;
 387        __be32 *bp;
 388
 389        _enter("");
 390
 391        call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4);
 392        if (!call)
 393                return ERR_PTR(-ENOMEM);
 394
 395        call->key = key;
 396        call->vlserver = afs_get_vlserver(server);
 397        call->server_index = server_index;
 398        call->upgrade = true;
 399        call->async = true;
 400        call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
 401
 402        /* marshall the parameters */
 403        bp = call->request;
 404        *bp++ = htonl(VLGETCAPABILITIES);
 405
 406        /* Can't take a ref on server */
 407        trace_afs_make_vl_call(call);
 408        afs_make_call(ac, call, GFP_KERNEL);
 409        return call;
 410}
 411
 412/*
 413 * Deliver reply data to a YFSVL.GetEndpoints call.
 414 *
 415 *      GetEndpoints(IN yfsServerAttributes *attr,
 416 *                   OUT opr_uuid *uuid,
 417 *                   OUT afs_int32 *uniquifier,
 418 *                   OUT endpoints *fsEndpoints,
 419 *                   OUT endpoints *volEndpoints)
 420 */
 421static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
 422{
 423        struct afs_addr_list *alist;
 424        __be32 *bp;
 425        u32 uniquifier, size;
 426        int ret;
 427
 428        _enter("{%u,%zu,%u}",
 429               call->unmarshall, iov_iter_count(call->iter), call->count2);
 430
 431        switch (call->unmarshall) {
 432        case 0:
 433                afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32));
 434                call->unmarshall = 1;
 435
 436                /* Extract the returned uuid, uniquifier, fsEndpoints count and
 437                 * either the first fsEndpoint type or the volEndpoints
 438                 * count if there are no fsEndpoints. */
 439                /* Fall through */
 440        case 1:
 441                ret = afs_extract_data(call, true);
 442                if (ret < 0)
 443                        return ret;
 444
 445                bp = call->buffer + sizeof(uuid_t);
 446                uniquifier      = ntohl(*bp++);
 447                call->count     = ntohl(*bp++);
 448                call->count2    = ntohl(*bp); /* Type or next count */
 449
 450                if (call->count > YFS_MAXENDPOINTS)
 451                        return afs_protocol_error(call, 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, afs_eproto_yvl_fsendpt_type);
 472                }
 473
 474                size += sizeof(__be32);
 475                afs_extract_to_buf(call, size);
 476                call->unmarshall = 2;
 477
 478                /* Fall through - and extract fsEndpoints[] entries */
 479        case 2:
 480                ret = afs_extract_data(call, true);
 481                if (ret < 0)
 482                        return ret;
 483
 484                alist = call->ret_alist;
 485                bp = call->buffer;
 486                switch (call->count2) {
 487                case YFS_ENDPOINT_IPV4:
 488                        if (ntohl(bp[0]) != sizeof(__be32) * 2)
 489                                return afs_protocol_error(
 490                                        call, afs_eproto_yvl_fsendpt4_len);
 491                        afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2]));
 492                        bp += 3;
 493                        break;
 494                case YFS_ENDPOINT_IPV6:
 495                        if (ntohl(bp[0]) != sizeof(__be32) * 5)
 496                                return afs_protocol_error(
 497                                        call, afs_eproto_yvl_fsendpt6_len);
 498                        afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5]));
 499                        bp += 6;
 500                        break;
 501                default:
 502                        return afs_protocol_error(call, afs_eproto_yvl_fsendpt_type);
 503                }
 504
 505                /* Got either the type of the next entry or the count of
 506                 * volEndpoints if no more fsEndpoints.
 507                 */
 508                call->count2 = ntohl(*bp++);
 509
 510                call->count--;
 511                if (call->count > 0)
 512                        goto next_fsendpoint;
 513
 514        extract_volendpoints:
 515                /* Extract the list of volEndpoints. */
 516                call->count = call->count2;
 517                if (!call->count)
 518                        goto end;
 519                if (call->count > YFS_MAXENDPOINTS)
 520                        return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);
 521
 522                afs_extract_to_buf(call, 1 * sizeof(__be32));
 523                call->unmarshall = 3;
 524
 525                /* Extract the type of volEndpoints[0].  Normally we would
 526                 * extract the type of the next endpoint when we extract the
 527                 * data of the current one, but this is the first...
 528                 */
 529                /* Fall through */
 530        case 3:
 531                ret = afs_extract_data(call, true);
 532                if (ret < 0)
 533                        return ret;
 534
 535                bp = call->buffer;
 536
 537        next_volendpoint:
 538                call->count2 = ntohl(*bp++);
 539                switch (call->count2) {
 540                case YFS_ENDPOINT_IPV4:
 541                        size = sizeof(__be32) * (1 + 1 + 1);
 542                        break;
 543                case YFS_ENDPOINT_IPV6:
 544                        size = sizeof(__be32) * (1 + 4 + 1);
 545                        break;
 546                default:
 547                        return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);
 548                }
 549
 550                if (call->count > 1)
 551                        size += sizeof(__be32); /* Get next type too */
 552                afs_extract_to_buf(call, size);
 553                call->unmarshall = 4;
 554
 555                /* Fall through - and extract volEndpoints[] entries */
 556        case 4:
 557                ret = afs_extract_data(call, true);
 558                if (ret < 0)
 559                        return ret;
 560
 561                bp = call->buffer;
 562                switch (call->count2) {
 563                case YFS_ENDPOINT_IPV4:
 564                        if (ntohl(bp[0]) != sizeof(__be32) * 2)
 565                                return afs_protocol_error(
 566                                        call, afs_eproto_yvl_vlendpt4_len);
 567                        bp += 3;
 568                        break;
 569                case YFS_ENDPOINT_IPV6:
 570                        if (ntohl(bp[0]) != sizeof(__be32) * 5)
 571                                return afs_protocol_error(
 572                                        call, afs_eproto_yvl_vlendpt6_len);
 573                        bp += 6;
 574                        break;
 575                default:
 576                        return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);
 577                }
 578
 579                /* Got either the type of the next entry or the count of
 580                 * volEndpoints if no more fsEndpoints.
 581                 */
 582                call->count--;
 583                if (call->count > 0)
 584                        goto next_volendpoint;
 585
 586        end:
 587                afs_extract_discard(call, 0);
 588                call->unmarshall = 5;
 589
 590                /* Fall through - Done */
 591        case 5:
 592                ret = afs_extract_data(call, false);
 593                if (ret < 0)
 594                        return ret;
 595                call->unmarshall = 6;
 596
 597        case 6:
 598                break;
 599        }
 600
 601        _leave(" = 0 [done]");
 602        return 0;
 603}
 604
 605/*
 606 * YFSVL.GetEndpoints operation type.
 607 */
 608static const struct afs_call_type afs_YFSVLGetEndpoints = {
 609        .name           = "YFSVL.GetEndpoints",
 610        .op             = afs_YFSVL_GetEndpoints,
 611        .deliver        = afs_deliver_yfsvl_get_endpoints,
 612        .destructor     = afs_vl_get_addrs_u_destructor,
 613};
 614
 615/*
 616 * Dispatch an operation to get the addresses for a server, where the server is
 617 * nominated by UUID.
 618 */
 619struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc,
 620                                              const uuid_t *uuid)
 621{
 622        struct afs_call *call;
 623        struct afs_net *net = vc->cell->net;
 624        __be32 *bp;
 625
 626        _enter("");
 627
 628        call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints,
 629                                   sizeof(__be32) * 2 + sizeof(*uuid),
 630                                   sizeof(struct in6_addr) + sizeof(__be32) * 3);
 631        if (!call)
 632                return ERR_PTR(-ENOMEM);
 633
 634        call->key = vc->key;
 635        call->ret_alist = NULL;
 636        call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 637
 638        /* Marshall the parameters */
 639        bp = call->request;
 640        *bp++ = htonl(YVLGETENDPOINTS);
 641        *bp++ = htonl(YFS_SERVER_UUID);
 642        memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */
 643
 644        trace_afs_make_vl_call(call);
 645        afs_make_call(&vc->ac, call, GFP_KERNEL);
 646        return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
 647}
 648
 649/*
 650 * Deliver reply data to a YFSVL.GetCellName operation.
 651 */
 652static int afs_deliver_yfsvl_get_cell_name(struct afs_call *call)
 653{
 654        char *cell_name;
 655        u32 namesz, paddedsz;
 656        int ret;
 657
 658        _enter("{%u,%zu/%u}",
 659               call->unmarshall, iov_iter_count(call->iter), call->count);
 660
 661        switch (call->unmarshall) {
 662        case 0:
 663                afs_extract_to_tmp(call);
 664                call->unmarshall++;
 665
 666                /* Fall through - and extract the cell name length */
 667        case 1:
 668                ret = afs_extract_data(call, true);
 669                if (ret < 0)
 670                        return ret;
 671
 672                namesz = ntohl(call->tmp);
 673                if (namesz > AFS_MAXCELLNAME)
 674                        return afs_protocol_error(call, afs_eproto_cellname_len);
 675                paddedsz = (namesz + 3) & ~3;
 676                call->count = namesz;
 677                call->count2 = paddedsz - namesz;
 678
 679                cell_name = kmalloc(namesz + 1, GFP_KERNEL);
 680                if (!cell_name)
 681                        return -ENOMEM;
 682                cell_name[namesz] = 0;
 683                call->ret_str = cell_name;
 684
 685                afs_extract_begin(call, cell_name, namesz);
 686                call->unmarshall++;
 687
 688                /* Fall through - and extract cell name */
 689        case 2:
 690                ret = afs_extract_data(call, true);
 691                if (ret < 0)
 692                        return ret;
 693
 694                afs_extract_discard(call, call->count2);
 695                call->unmarshall++;
 696
 697                /* Fall through - and extract padding */
 698        case 3:
 699                ret = afs_extract_data(call, false);
 700                if (ret < 0)
 701                        return ret;
 702
 703                call->unmarshall++;
 704                break;
 705        }
 706
 707        _leave(" = 0 [done]");
 708        return 0;
 709}
 710
 711static void afs_destroy_yfsvl_get_cell_name(struct afs_call *call)
 712{
 713        kfree(call->ret_str);
 714        afs_flat_call_destructor(call);
 715}
 716
 717/*
 718 * VL.GetCapabilities operation type
 719 */
 720static const struct afs_call_type afs_YFSVLGetCellName = {
 721        .name           = "YFSVL.GetCellName",
 722        .op             = afs_YFSVL_GetCellName,
 723        .deliver        = afs_deliver_yfsvl_get_cell_name,
 724        .destructor     = afs_destroy_yfsvl_get_cell_name,
 725};
 726
 727/*
 728 * Probe a volume server for the capabilities that it supports.  This can
 729 * return up to 196 words.
 730 *
 731 * We use this to probe for service upgrade to determine what the server at the
 732 * other end supports.
 733 */
 734char *afs_yfsvl_get_cell_name(struct afs_vl_cursor *vc)
 735{
 736        struct afs_call *call;
 737        struct afs_net *net = vc->cell->net;
 738        __be32 *bp;
 739
 740        _enter("");
 741
 742        call = afs_alloc_flat_call(net, &afs_YFSVLGetCellName, 1 * 4, 0);
 743        if (!call)
 744                return ERR_PTR(-ENOMEM);
 745
 746        call->key = vc->key;
 747        call->ret_str = NULL;
 748        call->max_lifespan = AFS_VL_MAX_LIFESPAN;
 749
 750        /* marshall the parameters */
 751        bp = call->request;
 752        *bp++ = htonl(YVLGETCELLNAME);
 753
 754        /* Can't take a ref on server */
 755        trace_afs_make_vl_call(call);
 756        afs_make_call(&vc->ac, call, GFP_KERNEL);
 757        return (char *)afs_wait_for_call_to_complete(call, &vc->ac);
 758}
 759