Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* AFS Volume Location Service client
0003  *
0004  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #include <linux/gfp.h>
0009 #include <linux/init.h>
0010 #include <linux/sched.h>
0011 #include "afs_fs.h"
0012 #include "internal.h"
0013 
0014 /*
0015  * Deliver reply data to a VL.GetEntryByNameU call.
0016  */
0017 static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)
0018 {
0019     struct afs_uvldbentry__xdr *uvldb;
0020     struct afs_vldb_entry *entry;
0021     bool new_only = false;
0022     u32 tmp, nr_servers, vlflags;
0023     int i, ret;
0024 
0025     _enter("");
0026 
0027     ret = afs_transfer_reply(call);
0028     if (ret < 0)
0029         return ret;
0030 
0031     /* unmarshall the reply once we've received all of it */
0032     uvldb = call->buffer;
0033     entry = call->ret_vldb;
0034 
0035     nr_servers = ntohl(uvldb->nServers);
0036     if (nr_servers > AFS_NMAXNSERVERS)
0037         nr_servers = AFS_NMAXNSERVERS;
0038 
0039     for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++)
0040         entry->name[i] = (u8)ntohl(uvldb->name[i]);
0041     entry->name[i] = 0;
0042     entry->name_len = strlen(entry->name);
0043 
0044     /* If there is a new replication site that we can use, ignore all the
0045      * sites that aren't marked as new.
0046      */
0047     for (i = 0; i < nr_servers; i++) {
0048         tmp = ntohl(uvldb->serverFlags[i]);
0049         if (!(tmp & AFS_VLSF_DONTUSE) &&
0050             (tmp & AFS_VLSF_NEWREPSITE))
0051             new_only = true;
0052     }
0053 
0054     vlflags = ntohl(uvldb->flags);
0055     for (i = 0; i < nr_servers; i++) {
0056         struct afs_uuid__xdr *xdr;
0057         struct afs_uuid *uuid;
0058         int j;
0059         int n = entry->nr_servers;
0060 
0061         tmp = ntohl(uvldb->serverFlags[i]);
0062         if (tmp & AFS_VLSF_DONTUSE ||
0063             (new_only && !(tmp & AFS_VLSF_NEWREPSITE)))
0064             continue;
0065         if (tmp & AFS_VLSF_RWVOL) {
0066             entry->fs_mask[n] |= AFS_VOL_VTM_RW;
0067             if (vlflags & AFS_VLF_BACKEXISTS)
0068                 entry->fs_mask[n] |= AFS_VOL_VTM_BAK;
0069         }
0070         if (tmp & AFS_VLSF_ROVOL)
0071             entry->fs_mask[n] |= AFS_VOL_VTM_RO;
0072         if (!entry->fs_mask[n])
0073             continue;
0074 
0075         xdr = &uvldb->serverNumber[i];
0076         uuid = (struct afs_uuid *)&entry->fs_server[n];
0077         uuid->time_low          = xdr->time_low;
0078         uuid->time_mid          = htons(ntohl(xdr->time_mid));
0079         uuid->time_hi_and_version   = htons(ntohl(xdr->time_hi_and_version));
0080         uuid->clock_seq_hi_and_reserved = (u8)ntohl(xdr->clock_seq_hi_and_reserved);
0081         uuid->clock_seq_low     = (u8)ntohl(xdr->clock_seq_low);
0082         for (j = 0; j < 6; j++)
0083             uuid->node[j] = (u8)ntohl(xdr->node[j]);
0084 
0085         entry->addr_version[n] = ntohl(uvldb->serverUnique[i]);
0086         entry->nr_servers++;
0087     }
0088 
0089     for (i = 0; i < AFS_MAXTYPES; i++)
0090         entry->vid[i] = ntohl(uvldb->volumeId[i]);
0091 
0092     if (vlflags & AFS_VLF_RWEXISTS)
0093         __set_bit(AFS_VLDB_HAS_RW, &entry->flags);
0094     if (vlflags & AFS_VLF_ROEXISTS)
0095         __set_bit(AFS_VLDB_HAS_RO, &entry->flags);
0096     if (vlflags & AFS_VLF_BACKEXISTS)
0097         __set_bit(AFS_VLDB_HAS_BAK, &entry->flags);
0098 
0099     if (!(vlflags & (AFS_VLF_RWEXISTS | AFS_VLF_ROEXISTS | AFS_VLF_BACKEXISTS))) {
0100         entry->error = -ENOMEDIUM;
0101         __set_bit(AFS_VLDB_QUERY_ERROR, &entry->flags);
0102     }
0103 
0104     __set_bit(AFS_VLDB_QUERY_VALID, &entry->flags);
0105     _leave(" = 0 [done]");
0106     return 0;
0107 }
0108 
0109 static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call)
0110 {
0111     kfree(call->ret_vldb);
0112     afs_flat_call_destructor(call);
0113 }
0114 
0115 /*
0116  * VL.GetEntryByNameU operation type.
0117  */
0118 static const struct afs_call_type afs_RXVLGetEntryByNameU = {
0119     .name       = "VL.GetEntryByNameU",
0120     .op     = afs_VL_GetEntryByNameU,
0121     .deliver    = afs_deliver_vl_get_entry_by_name_u,
0122     .destructor = afs_destroy_vl_get_entry_by_name_u,
0123 };
0124 
0125 /*
0126  * Dispatch a get volume entry by name or ID operation (uuid variant).  If the
0127  * volname is a decimal number then it's a volume ID not a volume name.
0128  */
0129 struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc,
0130                           const char *volname,
0131                           int volnamesz)
0132 {
0133     struct afs_vldb_entry *entry;
0134     struct afs_call *call;
0135     struct afs_net *net = vc->cell->net;
0136     size_t reqsz, padsz;
0137     __be32 *bp;
0138 
0139     _enter("");
0140 
0141     padsz = (4 - (volnamesz & 3)) & 3;
0142     reqsz = 8 + volnamesz + padsz;
0143 
0144     entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL);
0145     if (!entry)
0146         return ERR_PTR(-ENOMEM);
0147 
0148     call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz,
0149                    sizeof(struct afs_uvldbentry__xdr));
0150     if (!call) {
0151         kfree(entry);
0152         return ERR_PTR(-ENOMEM);
0153     }
0154 
0155     call->key = vc->key;
0156     call->ret_vldb = entry;
0157     call->max_lifespan = AFS_VL_MAX_LIFESPAN;
0158 
0159     /* Marshall the parameters */
0160     bp = call->request;
0161     *bp++ = htonl(VLGETENTRYBYNAMEU);
0162     *bp++ = htonl(volnamesz);
0163     memcpy(bp, volname, volnamesz);
0164     if (padsz > 0)
0165         memset((void *)bp + volnamesz, 0, padsz);
0166 
0167     trace_afs_make_vl_call(call);
0168     afs_make_call(&vc->ac, call, GFP_KERNEL);
0169     return (struct afs_vldb_entry *)afs_wait_for_call_to_complete(call, &vc->ac);
0170 }
0171 
0172 /*
0173  * Deliver reply data to a VL.GetAddrsU call.
0174  *
0175  *  GetAddrsU(IN ListAddrByAttributes *inaddr,
0176  *        OUT afsUUID *uuidp1,
0177  *        OUT uint32_t *uniquifier,
0178  *        OUT uint32_t *nentries,
0179  *        OUT bulkaddrs *blkaddrs);
0180  */
0181 static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
0182 {
0183     struct afs_addr_list *alist;
0184     __be32 *bp;
0185     u32 uniquifier, nentries, count;
0186     int i, ret;
0187 
0188     _enter("{%u,%zu/%u}",
0189            call->unmarshall, iov_iter_count(call->iter), call->count);
0190 
0191     switch (call->unmarshall) {
0192     case 0:
0193         afs_extract_to_buf(call,
0194                    sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
0195         call->unmarshall++;
0196 
0197         /* Extract the returned uuid, uniquifier, nentries and
0198          * blkaddrs size */
0199         fallthrough;
0200     case 1:
0201         ret = afs_extract_data(call, true);
0202         if (ret < 0)
0203             return ret;
0204 
0205         bp = call->buffer + sizeof(struct afs_uuid__xdr);
0206         uniquifier  = ntohl(*bp++);
0207         nentries    = ntohl(*bp++);
0208         count       = ntohl(*bp);
0209 
0210         nentries = min(nentries, count);
0211         alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT);
0212         if (!alist)
0213             return -ENOMEM;
0214         alist->version = uniquifier;
0215         call->ret_alist = alist;
0216         call->count = count;
0217         call->count2 = nentries;
0218         call->unmarshall++;
0219 
0220     more_entries:
0221         count = min(call->count, 4U);
0222         afs_extract_to_buf(call, count * sizeof(__be32));
0223 
0224         fallthrough;    /* and extract entries */
0225     case 2:
0226         ret = afs_extract_data(call, call->count > 4);
0227         if (ret < 0)
0228             return ret;
0229 
0230         alist = call->ret_alist;
0231         bp = call->buffer;
0232         count = min(call->count, 4U);
0233         for (i = 0; i < count; i++)
0234             if (alist->nr_addrs < call->count2)
0235                 afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT);
0236 
0237         call->count -= count;
0238         if (call->count > 0)
0239             goto more_entries;
0240         call->unmarshall++;
0241         break;
0242     }
0243 
0244     _leave(" = 0 [done]");
0245     return 0;
0246 }
0247 
0248 static void afs_vl_get_addrs_u_destructor(struct afs_call *call)
0249 {
0250     afs_put_addrlist(call->ret_alist);
0251     return afs_flat_call_destructor(call);
0252 }
0253 
0254 /*
0255  * VL.GetAddrsU operation type.
0256  */
0257 static const struct afs_call_type afs_RXVLGetAddrsU = {
0258     .name       = "VL.GetAddrsU",
0259     .op     = afs_VL_GetAddrsU,
0260     .deliver    = afs_deliver_vl_get_addrs_u,
0261     .destructor = afs_vl_get_addrs_u_destructor,
0262 };
0263 
0264 /*
0265  * Dispatch an operation to get the addresses for a server, where the server is
0266  * nominated by UUID.
0267  */
0268 struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc,
0269                      const uuid_t *uuid)
0270 {
0271     struct afs_ListAddrByAttributes__xdr *r;
0272     const struct afs_uuid *u = (const struct afs_uuid *)uuid;
0273     struct afs_call *call;
0274     struct afs_net *net = vc->cell->net;
0275     __be32 *bp;
0276     int i;
0277 
0278     _enter("");
0279 
0280     call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU,
0281                    sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr),
0282                    sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
0283     if (!call)
0284         return ERR_PTR(-ENOMEM);
0285 
0286     call->key = vc->key;
0287     call->ret_alist = NULL;
0288     call->max_lifespan = AFS_VL_MAX_LIFESPAN;
0289 
0290     /* Marshall the parameters */
0291     bp = call->request;
0292     *bp++ = htonl(VLGETADDRSU);
0293     r = (struct afs_ListAddrByAttributes__xdr *)bp;
0294     r->Mask     = htonl(AFS_VLADDR_UUID);
0295     r->ipaddr   = 0;
0296     r->index    = 0;
0297     r->spare    = 0;
0298     r->uuid.time_low            = u->time_low;
0299     r->uuid.time_mid            = htonl(ntohs(u->time_mid));
0300     r->uuid.time_hi_and_version     = htonl(ntohs(u->time_hi_and_version));
0301     r->uuid.clock_seq_hi_and_reserved   = htonl(u->clock_seq_hi_and_reserved);
0302     r->uuid.clock_seq_low           = htonl(u->clock_seq_low);
0303     for (i = 0; i < 6; i++)
0304         r->uuid.node[i] = htonl(u->node[i]);
0305 
0306     trace_afs_make_vl_call(call);
0307     afs_make_call(&vc->ac, call, GFP_KERNEL);
0308     return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
0309 }
0310 
0311 /*
0312  * Deliver reply data to an VL.GetCapabilities operation.
0313  */
0314 static int afs_deliver_vl_get_capabilities(struct afs_call *call)
0315 {
0316     u32 count;
0317     int ret;
0318 
0319     _enter("{%u,%zu/%u}",
0320            call->unmarshall, iov_iter_count(call->iter), call->count);
0321 
0322     switch (call->unmarshall) {
0323     case 0:
0324         afs_extract_to_tmp(call);
0325         call->unmarshall++;
0326 
0327         fallthrough;    /* and extract the capabilities word count */
0328     case 1:
0329         ret = afs_extract_data(call, true);
0330         if (ret < 0)
0331             return ret;
0332 
0333         count = ntohl(call->tmp);
0334         call->count = count;
0335         call->count2 = count;
0336 
0337         call->unmarshall++;
0338         afs_extract_discard(call, count * sizeof(__be32));
0339 
0340         fallthrough;    /* and extract capabilities words */
0341     case 2:
0342         ret = afs_extract_data(call, false);
0343         if (ret < 0)
0344             return ret;
0345 
0346         /* TODO: Examine capabilities */
0347 
0348         call->unmarshall++;
0349         break;
0350     }
0351 
0352     _leave(" = 0 [done]");
0353     return 0;
0354 }
0355 
0356 static void afs_destroy_vl_get_capabilities(struct afs_call *call)
0357 {
0358     afs_put_vlserver(call->net, call->vlserver);
0359     afs_flat_call_destructor(call);
0360 }
0361 
0362 /*
0363  * VL.GetCapabilities operation type
0364  */
0365 static const struct afs_call_type afs_RXVLGetCapabilities = {
0366     .name       = "VL.GetCapabilities",
0367     .op     = afs_VL_GetCapabilities,
0368     .deliver    = afs_deliver_vl_get_capabilities,
0369     .done       = afs_vlserver_probe_result,
0370     .destructor = afs_destroy_vl_get_capabilities,
0371 };
0372 
0373 /*
0374  * Probe a volume server for the capabilities that it supports.  This can
0375  * return up to 196 words.
0376  *
0377  * We use this to probe for service upgrade to determine what the server at the
0378  * other end supports.
0379  */
0380 struct afs_call *afs_vl_get_capabilities(struct afs_net *net,
0381                      struct afs_addr_cursor *ac,
0382                      struct key *key,
0383                      struct afs_vlserver *server,
0384                      unsigned int server_index)
0385 {
0386     struct afs_call *call;
0387     __be32 *bp;
0388 
0389     _enter("");
0390 
0391     call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4);
0392     if (!call)
0393         return ERR_PTR(-ENOMEM);
0394 
0395     call->key = key;
0396     call->vlserver = afs_get_vlserver(server);
0397     call->server_index = server_index;
0398     call->upgrade = true;
0399     call->async = true;
0400     call->max_lifespan = AFS_PROBE_MAX_LIFESPAN;
0401 
0402     /* marshall the parameters */
0403     bp = call->request;
0404     *bp++ = htonl(VLGETCAPABILITIES);
0405 
0406     /* Can't take a ref on server */
0407     trace_afs_make_vl_call(call);
0408     afs_make_call(ac, call, GFP_KERNEL);
0409     return call;
0410 }
0411 
0412 /*
0413  * Deliver reply data to a YFSVL.GetEndpoints call.
0414  *
0415  *  GetEndpoints(IN yfsServerAttributes *attr,
0416  *           OUT opr_uuid *uuid,
0417  *           OUT afs_int32 *uniquifier,
0418  *           OUT endpoints *fsEndpoints,
0419  *           OUT endpoints *volEndpoints)
0420  */
0421 static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
0422 {
0423     struct afs_addr_list *alist;
0424     __be32 *bp;
0425     u32 uniquifier, size;
0426     int ret;
0427 
0428     _enter("{%u,%zu,%u}",
0429            call->unmarshall, iov_iter_count(call->iter), call->count2);
0430 
0431     switch (call->unmarshall) {
0432     case 0:
0433         afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32));
0434         call->unmarshall = 1;
0435 
0436         /* Extract the returned uuid, uniquifier, fsEndpoints count and
0437          * either the first fsEndpoint type or the volEndpoints
0438          * count if there are no fsEndpoints. */
0439         fallthrough;
0440     case 1:
0441         ret = afs_extract_data(call, true);
0442         if (ret < 0)
0443             return ret;
0444 
0445         bp = call->buffer + sizeof(uuid_t);
0446         uniquifier  = ntohl(*bp++);
0447         call->count = ntohl(*bp++);
0448         call->count2    = ntohl(*bp); /* Type or next count */
0449 
0450         if (call->count > YFS_MAXENDPOINTS)
0451             return afs_protocol_error(call, afs_eproto_yvl_fsendpt_num);
0452 
0453         alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT);
0454         if (!alist)
0455             return -ENOMEM;
0456         alist->version = uniquifier;
0457         call->ret_alist = alist;
0458 
0459         if (call->count == 0)
0460             goto extract_volendpoints;
0461 
0462     next_fsendpoint:
0463         switch (call->count2) {
0464         case YFS_ENDPOINT_IPV4:
0465             size = sizeof(__be32) * (1 + 1 + 1);
0466             break;
0467         case YFS_ENDPOINT_IPV6:
0468             size = sizeof(__be32) * (1 + 4 + 1);
0469             break;
0470         default:
0471             return afs_protocol_error(call, afs_eproto_yvl_fsendpt_type);
0472         }
0473 
0474         size += sizeof(__be32);
0475         afs_extract_to_buf(call, size);
0476         call->unmarshall = 2;
0477 
0478         fallthrough;    /* and extract fsEndpoints[] entries */
0479     case 2:
0480         ret = afs_extract_data(call, true);
0481         if (ret < 0)
0482             return ret;
0483 
0484         alist = call->ret_alist;
0485         bp = call->buffer;
0486         switch (call->count2) {
0487         case YFS_ENDPOINT_IPV4:
0488             if (ntohl(bp[0]) != sizeof(__be32) * 2)
0489                 return afs_protocol_error(
0490                     call, afs_eproto_yvl_fsendpt4_len);
0491             afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2]));
0492             bp += 3;
0493             break;
0494         case YFS_ENDPOINT_IPV6:
0495             if (ntohl(bp[0]) != sizeof(__be32) * 5)
0496                 return afs_protocol_error(
0497                     call, afs_eproto_yvl_fsendpt6_len);
0498             afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5]));
0499             bp += 6;
0500             break;
0501         default:
0502             return afs_protocol_error(call, afs_eproto_yvl_fsendpt_type);
0503         }
0504 
0505         /* Got either the type of the next entry or the count of
0506          * volEndpoints if no more fsEndpoints.
0507          */
0508         call->count2 = ntohl(*bp++);
0509 
0510         call->count--;
0511         if (call->count > 0)
0512             goto next_fsendpoint;
0513 
0514     extract_volendpoints:
0515         /* Extract the list of volEndpoints. */
0516         call->count = call->count2;
0517         if (!call->count)
0518             goto end;
0519         if (call->count > YFS_MAXENDPOINTS)
0520             return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);
0521 
0522         afs_extract_to_buf(call, 1 * sizeof(__be32));
0523         call->unmarshall = 3;
0524 
0525         /* Extract the type of volEndpoints[0].  Normally we would
0526          * extract the type of the next endpoint when we extract the
0527          * data of the current one, but this is the first...
0528          */
0529         fallthrough;
0530     case 3:
0531         ret = afs_extract_data(call, true);
0532         if (ret < 0)
0533             return ret;
0534 
0535         bp = call->buffer;
0536 
0537     next_volendpoint:
0538         call->count2 = ntohl(*bp++);
0539         switch (call->count2) {
0540         case YFS_ENDPOINT_IPV4:
0541             size = sizeof(__be32) * (1 + 1 + 1);
0542             break;
0543         case YFS_ENDPOINT_IPV6:
0544             size = sizeof(__be32) * (1 + 4 + 1);
0545             break;
0546         default:
0547             return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);
0548         }
0549 
0550         if (call->count > 1)
0551             size += sizeof(__be32); /* Get next type too */
0552         afs_extract_to_buf(call, size);
0553         call->unmarshall = 4;
0554 
0555         fallthrough;    /* and extract volEndpoints[] entries */
0556     case 4:
0557         ret = afs_extract_data(call, true);
0558         if (ret < 0)
0559             return ret;
0560 
0561         bp = call->buffer;
0562         switch (call->count2) {
0563         case YFS_ENDPOINT_IPV4:
0564             if (ntohl(bp[0]) != sizeof(__be32) * 2)
0565                 return afs_protocol_error(
0566                     call, afs_eproto_yvl_vlendpt4_len);
0567             bp += 3;
0568             break;
0569         case YFS_ENDPOINT_IPV6:
0570             if (ntohl(bp[0]) != sizeof(__be32) * 5)
0571                 return afs_protocol_error(
0572                     call, afs_eproto_yvl_vlendpt6_len);
0573             bp += 6;
0574             break;
0575         default:
0576             return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type);
0577         }
0578 
0579         /* Got either the type of the next entry or the count of
0580          * volEndpoints if no more fsEndpoints.
0581          */
0582         call->count--;
0583         if (call->count > 0)
0584             goto next_volendpoint;
0585 
0586     end:
0587         afs_extract_discard(call, 0);
0588         call->unmarshall = 5;
0589 
0590         fallthrough;    /* Done */
0591     case 5:
0592         ret = afs_extract_data(call, false);
0593         if (ret < 0)
0594             return ret;
0595         call->unmarshall = 6;
0596         fallthrough;
0597 
0598     case 6:
0599         break;
0600     }
0601 
0602     _leave(" = 0 [done]");
0603     return 0;
0604 }
0605 
0606 /*
0607  * YFSVL.GetEndpoints operation type.
0608  */
0609 static const struct afs_call_type afs_YFSVLGetEndpoints = {
0610     .name       = "YFSVL.GetEndpoints",
0611     .op     = afs_YFSVL_GetEndpoints,
0612     .deliver    = afs_deliver_yfsvl_get_endpoints,
0613     .destructor = afs_vl_get_addrs_u_destructor,
0614 };
0615 
0616 /*
0617  * Dispatch an operation to get the addresses for a server, where the server is
0618  * nominated by UUID.
0619  */
0620 struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc,
0621                           const uuid_t *uuid)
0622 {
0623     struct afs_call *call;
0624     struct afs_net *net = vc->cell->net;
0625     __be32 *bp;
0626 
0627     _enter("");
0628 
0629     call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints,
0630                    sizeof(__be32) * 2 + sizeof(*uuid),
0631                    sizeof(struct in6_addr) + sizeof(__be32) * 3);
0632     if (!call)
0633         return ERR_PTR(-ENOMEM);
0634 
0635     call->key = vc->key;
0636     call->ret_alist = NULL;
0637     call->max_lifespan = AFS_VL_MAX_LIFESPAN;
0638 
0639     /* Marshall the parameters */
0640     bp = call->request;
0641     *bp++ = htonl(YVLGETENDPOINTS);
0642     *bp++ = htonl(YFS_SERVER_UUID);
0643     memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */
0644 
0645     trace_afs_make_vl_call(call);
0646     afs_make_call(&vc->ac, call, GFP_KERNEL);
0647     return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac);
0648 }
0649 
0650 /*
0651  * Deliver reply data to a YFSVL.GetCellName operation.
0652  */
0653 static int afs_deliver_yfsvl_get_cell_name(struct afs_call *call)
0654 {
0655     char *cell_name;
0656     u32 namesz, paddedsz;
0657     int ret;
0658 
0659     _enter("{%u,%zu/%u}",
0660            call->unmarshall, iov_iter_count(call->iter), call->count);
0661 
0662     switch (call->unmarshall) {
0663     case 0:
0664         afs_extract_to_tmp(call);
0665         call->unmarshall++;
0666 
0667         fallthrough;    /* and extract the cell name length */
0668     case 1:
0669         ret = afs_extract_data(call, true);
0670         if (ret < 0)
0671             return ret;
0672 
0673         namesz = ntohl(call->tmp);
0674         if (namesz > AFS_MAXCELLNAME)
0675             return afs_protocol_error(call, afs_eproto_cellname_len);
0676         paddedsz = (namesz + 3) & ~3;
0677         call->count = namesz;
0678         call->count2 = paddedsz - namesz;
0679 
0680         cell_name = kmalloc(namesz + 1, GFP_KERNEL);
0681         if (!cell_name)
0682             return -ENOMEM;
0683         cell_name[namesz] = 0;
0684         call->ret_str = cell_name;
0685 
0686         afs_extract_begin(call, cell_name, namesz);
0687         call->unmarshall++;
0688 
0689         fallthrough;    /* and extract cell name */
0690     case 2:
0691         ret = afs_extract_data(call, true);
0692         if (ret < 0)
0693             return ret;
0694 
0695         afs_extract_discard(call, call->count2);
0696         call->unmarshall++;
0697 
0698         fallthrough;    /* and extract padding */
0699     case 3:
0700         ret = afs_extract_data(call, false);
0701         if (ret < 0)
0702             return ret;
0703 
0704         call->unmarshall++;
0705         break;
0706     }
0707 
0708     _leave(" = 0 [done]");
0709     return 0;
0710 }
0711 
0712 static void afs_destroy_yfsvl_get_cell_name(struct afs_call *call)
0713 {
0714     kfree(call->ret_str);
0715     afs_flat_call_destructor(call);
0716 }
0717 
0718 /*
0719  * VL.GetCapabilities operation type
0720  */
0721 static const struct afs_call_type afs_YFSVLGetCellName = {
0722     .name       = "YFSVL.GetCellName",
0723     .op     = afs_YFSVL_GetCellName,
0724     .deliver    = afs_deliver_yfsvl_get_cell_name,
0725     .destructor = afs_destroy_yfsvl_get_cell_name,
0726 };
0727 
0728 /*
0729  * Probe a volume server for the capabilities that it supports.  This can
0730  * return up to 196 words.
0731  *
0732  * We use this to probe for service upgrade to determine what the server at the
0733  * other end supports.
0734  */
0735 char *afs_yfsvl_get_cell_name(struct afs_vl_cursor *vc)
0736 {
0737     struct afs_call *call;
0738     struct afs_net *net = vc->cell->net;
0739     __be32 *bp;
0740 
0741     _enter("");
0742 
0743     call = afs_alloc_flat_call(net, &afs_YFSVLGetCellName, 1 * 4, 0);
0744     if (!call)
0745         return ERR_PTR(-ENOMEM);
0746 
0747     call->key = vc->key;
0748     call->ret_str = NULL;
0749     call->max_lifespan = AFS_VL_MAX_LIFESPAN;
0750 
0751     /* marshall the parameters */
0752     bp = call->request;
0753     *bp++ = htonl(YVLGETCELLNAME);
0754 
0755     /* Can't take a ref on server */
0756     trace_afs_make_vl_call(call);
0757     afs_make_call(&vc->ac, call, GFP_KERNEL);
0758     return (char *)afs_wait_for_call_to_complete(call, &vc->ac);
0759 }