root/fs/afs/vlclient.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. afs_deliver_vl_get_entry_by_name_u
  2. afs_destroy_vl_get_entry_by_name_u
  3. afs_vl_get_entry_by_name_u
  4. afs_deliver_vl_get_addrs_u
  5. afs_vl_get_addrs_u_destructor
  6. afs_vl_get_addrs_u
  7. afs_deliver_vl_get_capabilities
  8. afs_destroy_vl_get_capabilities
  9. afs_vl_get_capabilities
  10. afs_deliver_yfsvl_get_endpoints
  11. afs_yfsvl_get_endpoints

   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  */
  17 static 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 
 108 static 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  */
 117 static 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  */
 128 struct 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  */
 180 static 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 
 247 static 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  */
 256 static 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  */
 267 struct 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  */
 313 static 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 
 355 static 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  */
 364 static 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  */
 379 struct 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  */
 420 static 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  */
 613 static 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  */
 624 struct 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 }

/* [<][>][^][v][top][bottom][index][help] */