18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* AFS Volume Location Service client 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/gfp.h> 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/sched.h> 118c2ecf20Sopenharmony_ci#include "afs_fs.h" 128c2ecf20Sopenharmony_ci#include "internal.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* 158c2ecf20Sopenharmony_ci * Deliver reply data to a VL.GetEntryByNameU call. 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_cistatic int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci struct afs_uvldbentry__xdr *uvldb; 208c2ecf20Sopenharmony_ci struct afs_vldb_entry *entry; 218c2ecf20Sopenharmony_ci bool new_only = false; 228c2ecf20Sopenharmony_ci u32 tmp, nr_servers, vlflags; 238c2ecf20Sopenharmony_ci int i, ret; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci _enter(""); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci ret = afs_transfer_reply(call); 288c2ecf20Sopenharmony_ci if (ret < 0) 298c2ecf20Sopenharmony_ci return ret; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci /* unmarshall the reply once we've received all of it */ 328c2ecf20Sopenharmony_ci uvldb = call->buffer; 338c2ecf20Sopenharmony_ci entry = call->ret_vldb; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci nr_servers = ntohl(uvldb->nServers); 368c2ecf20Sopenharmony_ci if (nr_servers > AFS_NMAXNSERVERS) 378c2ecf20Sopenharmony_ci nr_servers = AFS_NMAXNSERVERS; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++) 408c2ecf20Sopenharmony_ci entry->name[i] = (u8)ntohl(uvldb->name[i]); 418c2ecf20Sopenharmony_ci entry->name[i] = 0; 428c2ecf20Sopenharmony_ci entry->name_len = strlen(entry->name); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci /* If there is a new replication site that we can use, ignore all the 458c2ecf20Sopenharmony_ci * sites that aren't marked as new. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci for (i = 0; i < nr_servers; i++) { 488c2ecf20Sopenharmony_ci tmp = ntohl(uvldb->serverFlags[i]); 498c2ecf20Sopenharmony_ci if (!(tmp & AFS_VLSF_DONTUSE) && 508c2ecf20Sopenharmony_ci (tmp & AFS_VLSF_NEWREPSITE)) 518c2ecf20Sopenharmony_ci new_only = true; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci vlflags = ntohl(uvldb->flags); 558c2ecf20Sopenharmony_ci for (i = 0; i < nr_servers; i++) { 568c2ecf20Sopenharmony_ci struct afs_uuid__xdr *xdr; 578c2ecf20Sopenharmony_ci struct afs_uuid *uuid; 588c2ecf20Sopenharmony_ci int j; 598c2ecf20Sopenharmony_ci int n = entry->nr_servers; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci tmp = ntohl(uvldb->serverFlags[i]); 628c2ecf20Sopenharmony_ci if (tmp & AFS_VLSF_DONTUSE || 638c2ecf20Sopenharmony_ci (new_only && !(tmp & AFS_VLSF_NEWREPSITE))) 648c2ecf20Sopenharmony_ci continue; 658c2ecf20Sopenharmony_ci if (tmp & AFS_VLSF_RWVOL) { 668c2ecf20Sopenharmony_ci entry->fs_mask[n] |= AFS_VOL_VTM_RW; 678c2ecf20Sopenharmony_ci if (vlflags & AFS_VLF_BACKEXISTS) 688c2ecf20Sopenharmony_ci entry->fs_mask[n] |= AFS_VOL_VTM_BAK; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci if (tmp & AFS_VLSF_ROVOL) 718c2ecf20Sopenharmony_ci entry->fs_mask[n] |= AFS_VOL_VTM_RO; 728c2ecf20Sopenharmony_ci if (!entry->fs_mask[n]) 738c2ecf20Sopenharmony_ci continue; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci xdr = &uvldb->serverNumber[i]; 768c2ecf20Sopenharmony_ci uuid = (struct afs_uuid *)&entry->fs_server[n]; 778c2ecf20Sopenharmony_ci uuid->time_low = xdr->time_low; 788c2ecf20Sopenharmony_ci uuid->time_mid = htons(ntohl(xdr->time_mid)); 798c2ecf20Sopenharmony_ci uuid->time_hi_and_version = htons(ntohl(xdr->time_hi_and_version)); 808c2ecf20Sopenharmony_ci uuid->clock_seq_hi_and_reserved = (u8)ntohl(xdr->clock_seq_hi_and_reserved); 818c2ecf20Sopenharmony_ci uuid->clock_seq_low = (u8)ntohl(xdr->clock_seq_low); 828c2ecf20Sopenharmony_ci for (j = 0; j < 6; j++) 838c2ecf20Sopenharmony_ci uuid->node[j] = (u8)ntohl(xdr->node[j]); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci entry->addr_version[n] = ntohl(uvldb->serverUnique[i]); 868c2ecf20Sopenharmony_ci entry->nr_servers++; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci for (i = 0; i < AFS_MAXTYPES; i++) 908c2ecf20Sopenharmony_ci entry->vid[i] = ntohl(uvldb->volumeId[i]); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (vlflags & AFS_VLF_RWEXISTS) 938c2ecf20Sopenharmony_ci __set_bit(AFS_VLDB_HAS_RW, &entry->flags); 948c2ecf20Sopenharmony_ci if (vlflags & AFS_VLF_ROEXISTS) 958c2ecf20Sopenharmony_ci __set_bit(AFS_VLDB_HAS_RO, &entry->flags); 968c2ecf20Sopenharmony_ci if (vlflags & AFS_VLF_BACKEXISTS) 978c2ecf20Sopenharmony_ci __set_bit(AFS_VLDB_HAS_BAK, &entry->flags); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci if (!(vlflags & (AFS_VLF_RWEXISTS | AFS_VLF_ROEXISTS | AFS_VLF_BACKEXISTS))) { 1008c2ecf20Sopenharmony_ci entry->error = -ENOMEDIUM; 1018c2ecf20Sopenharmony_ci __set_bit(AFS_VLDB_QUERY_ERROR, &entry->flags); 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci __set_bit(AFS_VLDB_QUERY_VALID, &entry->flags); 1058c2ecf20Sopenharmony_ci _leave(" = 0 [done]"); 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci kfree(call->ret_vldb); 1128c2ecf20Sopenharmony_ci afs_flat_call_destructor(call); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci/* 1168c2ecf20Sopenharmony_ci * VL.GetEntryByNameU operation type. 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_cistatic const struct afs_call_type afs_RXVLGetEntryByNameU = { 1198c2ecf20Sopenharmony_ci .name = "VL.GetEntryByNameU", 1208c2ecf20Sopenharmony_ci .op = afs_VL_GetEntryByNameU, 1218c2ecf20Sopenharmony_ci .deliver = afs_deliver_vl_get_entry_by_name_u, 1228c2ecf20Sopenharmony_ci .destructor = afs_destroy_vl_get_entry_by_name_u, 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* 1268c2ecf20Sopenharmony_ci * Dispatch a get volume entry by name or ID operation (uuid variant). If the 1278c2ecf20Sopenharmony_ci * volname is a decimal number then it's a volume ID not a volume name. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_cistruct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc, 1308c2ecf20Sopenharmony_ci const char *volname, 1318c2ecf20Sopenharmony_ci int volnamesz) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct afs_vldb_entry *entry; 1348c2ecf20Sopenharmony_ci struct afs_call *call; 1358c2ecf20Sopenharmony_ci struct afs_net *net = vc->cell->net; 1368c2ecf20Sopenharmony_ci size_t reqsz, padsz; 1378c2ecf20Sopenharmony_ci __be32 *bp; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci _enter(""); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci padsz = (4 - (volnamesz & 3)) & 3; 1428c2ecf20Sopenharmony_ci reqsz = 8 + volnamesz + padsz; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL); 1458c2ecf20Sopenharmony_ci if (!entry) 1468c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz, 1498c2ecf20Sopenharmony_ci sizeof(struct afs_uvldbentry__xdr)); 1508c2ecf20Sopenharmony_ci if (!call) { 1518c2ecf20Sopenharmony_ci kfree(entry); 1528c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci call->key = vc->key; 1568c2ecf20Sopenharmony_ci call->ret_vldb = entry; 1578c2ecf20Sopenharmony_ci call->max_lifespan = AFS_VL_MAX_LIFESPAN; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* Marshall the parameters */ 1608c2ecf20Sopenharmony_ci bp = call->request; 1618c2ecf20Sopenharmony_ci *bp++ = htonl(VLGETENTRYBYNAMEU); 1628c2ecf20Sopenharmony_ci *bp++ = htonl(volnamesz); 1638c2ecf20Sopenharmony_ci memcpy(bp, volname, volnamesz); 1648c2ecf20Sopenharmony_ci if (padsz > 0) 1658c2ecf20Sopenharmony_ci memset((void *)bp + volnamesz, 0, padsz); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci trace_afs_make_vl_call(call); 1688c2ecf20Sopenharmony_ci afs_make_call(&vc->ac, call, GFP_KERNEL); 1698c2ecf20Sopenharmony_ci return (struct afs_vldb_entry *)afs_wait_for_call_to_complete(call, &vc->ac); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* 1738c2ecf20Sopenharmony_ci * Deliver reply data to a VL.GetAddrsU call. 1748c2ecf20Sopenharmony_ci * 1758c2ecf20Sopenharmony_ci * GetAddrsU(IN ListAddrByAttributes *inaddr, 1768c2ecf20Sopenharmony_ci * OUT afsUUID *uuidp1, 1778c2ecf20Sopenharmony_ci * OUT uint32_t *uniquifier, 1788c2ecf20Sopenharmony_ci * OUT uint32_t *nentries, 1798c2ecf20Sopenharmony_ci * OUT bulkaddrs *blkaddrs); 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_cistatic int afs_deliver_vl_get_addrs_u(struct afs_call *call) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci struct afs_addr_list *alist; 1848c2ecf20Sopenharmony_ci __be32 *bp; 1858c2ecf20Sopenharmony_ci u32 uniquifier, nentries, count; 1868c2ecf20Sopenharmony_ci int i, ret; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci _enter("{%u,%zu/%u}", 1898c2ecf20Sopenharmony_ci call->unmarshall, iov_iter_count(call->iter), call->count); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci switch (call->unmarshall) { 1928c2ecf20Sopenharmony_ci case 0: 1938c2ecf20Sopenharmony_ci afs_extract_to_buf(call, 1948c2ecf20Sopenharmony_ci sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32)); 1958c2ecf20Sopenharmony_ci call->unmarshall++; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* Extract the returned uuid, uniquifier, nentries and 1988c2ecf20Sopenharmony_ci * blkaddrs size */ 1998c2ecf20Sopenharmony_ci fallthrough; 2008c2ecf20Sopenharmony_ci case 1: 2018c2ecf20Sopenharmony_ci ret = afs_extract_data(call, true); 2028c2ecf20Sopenharmony_ci if (ret < 0) 2038c2ecf20Sopenharmony_ci return ret; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci bp = call->buffer + sizeof(struct afs_uuid__xdr); 2068c2ecf20Sopenharmony_ci uniquifier = ntohl(*bp++); 2078c2ecf20Sopenharmony_ci nentries = ntohl(*bp++); 2088c2ecf20Sopenharmony_ci count = ntohl(*bp); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci nentries = min(nentries, count); 2118c2ecf20Sopenharmony_ci alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT); 2128c2ecf20Sopenharmony_ci if (!alist) 2138c2ecf20Sopenharmony_ci return -ENOMEM; 2148c2ecf20Sopenharmony_ci alist->version = uniquifier; 2158c2ecf20Sopenharmony_ci call->ret_alist = alist; 2168c2ecf20Sopenharmony_ci call->count = count; 2178c2ecf20Sopenharmony_ci call->count2 = nentries; 2188c2ecf20Sopenharmony_ci call->unmarshall++; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci more_entries: 2218c2ecf20Sopenharmony_ci count = min(call->count, 4U); 2228c2ecf20Sopenharmony_ci afs_extract_to_buf(call, count * sizeof(__be32)); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci fallthrough; /* and extract entries */ 2258c2ecf20Sopenharmony_ci case 2: 2268c2ecf20Sopenharmony_ci ret = afs_extract_data(call, call->count > 4); 2278c2ecf20Sopenharmony_ci if (ret < 0) 2288c2ecf20Sopenharmony_ci return ret; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci alist = call->ret_alist; 2318c2ecf20Sopenharmony_ci bp = call->buffer; 2328c2ecf20Sopenharmony_ci count = min(call->count, 4U); 2338c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) 2348c2ecf20Sopenharmony_ci if (alist->nr_addrs < call->count2) 2358c2ecf20Sopenharmony_ci afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci call->count -= count; 2388c2ecf20Sopenharmony_ci if (call->count > 0) 2398c2ecf20Sopenharmony_ci goto more_entries; 2408c2ecf20Sopenharmony_ci call->unmarshall++; 2418c2ecf20Sopenharmony_ci break; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci _leave(" = 0 [done]"); 2458c2ecf20Sopenharmony_ci return 0; 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cistatic void afs_vl_get_addrs_u_destructor(struct afs_call *call) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci afs_put_addrlist(call->ret_alist); 2518c2ecf20Sopenharmony_ci return afs_flat_call_destructor(call); 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci/* 2558c2ecf20Sopenharmony_ci * VL.GetAddrsU operation type. 2568c2ecf20Sopenharmony_ci */ 2578c2ecf20Sopenharmony_cistatic const struct afs_call_type afs_RXVLGetAddrsU = { 2588c2ecf20Sopenharmony_ci .name = "VL.GetAddrsU", 2598c2ecf20Sopenharmony_ci .op = afs_VL_GetAddrsU, 2608c2ecf20Sopenharmony_ci .deliver = afs_deliver_vl_get_addrs_u, 2618c2ecf20Sopenharmony_ci .destructor = afs_vl_get_addrs_u_destructor, 2628c2ecf20Sopenharmony_ci}; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci/* 2658c2ecf20Sopenharmony_ci * Dispatch an operation to get the addresses for a server, where the server is 2668c2ecf20Sopenharmony_ci * nominated by UUID. 2678c2ecf20Sopenharmony_ci */ 2688c2ecf20Sopenharmony_cistruct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc, 2698c2ecf20Sopenharmony_ci const uuid_t *uuid) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci struct afs_ListAddrByAttributes__xdr *r; 2728c2ecf20Sopenharmony_ci const struct afs_uuid *u = (const struct afs_uuid *)uuid; 2738c2ecf20Sopenharmony_ci struct afs_call *call; 2748c2ecf20Sopenharmony_ci struct afs_net *net = vc->cell->net; 2758c2ecf20Sopenharmony_ci __be32 *bp; 2768c2ecf20Sopenharmony_ci int i; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci _enter(""); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU, 2818c2ecf20Sopenharmony_ci sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr), 2828c2ecf20Sopenharmony_ci sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32)); 2838c2ecf20Sopenharmony_ci if (!call) 2848c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci call->key = vc->key; 2878c2ecf20Sopenharmony_ci call->ret_alist = NULL; 2888c2ecf20Sopenharmony_ci call->max_lifespan = AFS_VL_MAX_LIFESPAN; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* Marshall the parameters */ 2918c2ecf20Sopenharmony_ci bp = call->request; 2928c2ecf20Sopenharmony_ci *bp++ = htonl(VLGETADDRSU); 2938c2ecf20Sopenharmony_ci r = (struct afs_ListAddrByAttributes__xdr *)bp; 2948c2ecf20Sopenharmony_ci r->Mask = htonl(AFS_VLADDR_UUID); 2958c2ecf20Sopenharmony_ci r->ipaddr = 0; 2968c2ecf20Sopenharmony_ci r->index = 0; 2978c2ecf20Sopenharmony_ci r->spare = 0; 2988c2ecf20Sopenharmony_ci r->uuid.time_low = u->time_low; 2998c2ecf20Sopenharmony_ci r->uuid.time_mid = htonl(ntohs(u->time_mid)); 3008c2ecf20Sopenharmony_ci r->uuid.time_hi_and_version = htonl(ntohs(u->time_hi_and_version)); 3018c2ecf20Sopenharmony_ci r->uuid.clock_seq_hi_and_reserved = htonl(u->clock_seq_hi_and_reserved); 3028c2ecf20Sopenharmony_ci r->uuid.clock_seq_low = htonl(u->clock_seq_low); 3038c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) 3048c2ecf20Sopenharmony_ci r->uuid.node[i] = htonl(u->node[i]); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci trace_afs_make_vl_call(call); 3078c2ecf20Sopenharmony_ci afs_make_call(&vc->ac, call, GFP_KERNEL); 3088c2ecf20Sopenharmony_ci return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci/* 3128c2ecf20Sopenharmony_ci * Deliver reply data to an VL.GetCapabilities operation. 3138c2ecf20Sopenharmony_ci */ 3148c2ecf20Sopenharmony_cistatic int afs_deliver_vl_get_capabilities(struct afs_call *call) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci u32 count; 3178c2ecf20Sopenharmony_ci int ret; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci _enter("{%u,%zu/%u}", 3208c2ecf20Sopenharmony_ci call->unmarshall, iov_iter_count(call->iter), call->count); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci switch (call->unmarshall) { 3238c2ecf20Sopenharmony_ci case 0: 3248c2ecf20Sopenharmony_ci afs_extract_to_tmp(call); 3258c2ecf20Sopenharmony_ci call->unmarshall++; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci fallthrough; /* and extract the capabilities word count */ 3288c2ecf20Sopenharmony_ci case 1: 3298c2ecf20Sopenharmony_ci ret = afs_extract_data(call, true); 3308c2ecf20Sopenharmony_ci if (ret < 0) 3318c2ecf20Sopenharmony_ci return ret; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci count = ntohl(call->tmp); 3348c2ecf20Sopenharmony_ci call->count = count; 3358c2ecf20Sopenharmony_ci call->count2 = count; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci call->unmarshall++; 3388c2ecf20Sopenharmony_ci afs_extract_discard(call, count * sizeof(__be32)); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci fallthrough; /* and extract capabilities words */ 3418c2ecf20Sopenharmony_ci case 2: 3428c2ecf20Sopenharmony_ci ret = afs_extract_data(call, false); 3438c2ecf20Sopenharmony_ci if (ret < 0) 3448c2ecf20Sopenharmony_ci return ret; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* TODO: Examine capabilities */ 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci call->unmarshall++; 3498c2ecf20Sopenharmony_ci break; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci _leave(" = 0 [done]"); 3538c2ecf20Sopenharmony_ci return 0; 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic void afs_destroy_vl_get_capabilities(struct afs_call *call) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci afs_put_vlserver(call->net, call->vlserver); 3598c2ecf20Sopenharmony_ci afs_flat_call_destructor(call); 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci/* 3638c2ecf20Sopenharmony_ci * VL.GetCapabilities operation type 3648c2ecf20Sopenharmony_ci */ 3658c2ecf20Sopenharmony_cistatic const struct afs_call_type afs_RXVLGetCapabilities = { 3668c2ecf20Sopenharmony_ci .name = "VL.GetCapabilities", 3678c2ecf20Sopenharmony_ci .op = afs_VL_GetCapabilities, 3688c2ecf20Sopenharmony_ci .deliver = afs_deliver_vl_get_capabilities, 3698c2ecf20Sopenharmony_ci .done = afs_vlserver_probe_result, 3708c2ecf20Sopenharmony_ci .destructor = afs_destroy_vl_get_capabilities, 3718c2ecf20Sopenharmony_ci}; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci/* 3748c2ecf20Sopenharmony_ci * Probe a volume server for the capabilities that it supports. This can 3758c2ecf20Sopenharmony_ci * return up to 196 words. 3768c2ecf20Sopenharmony_ci * 3778c2ecf20Sopenharmony_ci * We use this to probe for service upgrade to determine what the server at the 3788c2ecf20Sopenharmony_ci * other end supports. 3798c2ecf20Sopenharmony_ci */ 3808c2ecf20Sopenharmony_cistruct afs_call *afs_vl_get_capabilities(struct afs_net *net, 3818c2ecf20Sopenharmony_ci struct afs_addr_cursor *ac, 3828c2ecf20Sopenharmony_ci struct key *key, 3838c2ecf20Sopenharmony_ci struct afs_vlserver *server, 3848c2ecf20Sopenharmony_ci unsigned int server_index) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci struct afs_call *call; 3878c2ecf20Sopenharmony_ci __be32 *bp; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci _enter(""); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4); 3928c2ecf20Sopenharmony_ci if (!call) 3938c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci call->key = key; 3968c2ecf20Sopenharmony_ci call->vlserver = afs_get_vlserver(server); 3978c2ecf20Sopenharmony_ci call->server_index = server_index; 3988c2ecf20Sopenharmony_ci call->upgrade = true; 3998c2ecf20Sopenharmony_ci call->async = true; 4008c2ecf20Sopenharmony_ci call->max_lifespan = AFS_PROBE_MAX_LIFESPAN; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* marshall the parameters */ 4038c2ecf20Sopenharmony_ci bp = call->request; 4048c2ecf20Sopenharmony_ci *bp++ = htonl(VLGETCAPABILITIES); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci /* Can't take a ref on server */ 4078c2ecf20Sopenharmony_ci trace_afs_make_vl_call(call); 4088c2ecf20Sopenharmony_ci afs_make_call(ac, call, GFP_KERNEL); 4098c2ecf20Sopenharmony_ci return call; 4108c2ecf20Sopenharmony_ci} 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci/* 4138c2ecf20Sopenharmony_ci * Deliver reply data to a YFSVL.GetEndpoints call. 4148c2ecf20Sopenharmony_ci * 4158c2ecf20Sopenharmony_ci * GetEndpoints(IN yfsServerAttributes *attr, 4168c2ecf20Sopenharmony_ci * OUT opr_uuid *uuid, 4178c2ecf20Sopenharmony_ci * OUT afs_int32 *uniquifier, 4188c2ecf20Sopenharmony_ci * OUT endpoints *fsEndpoints, 4198c2ecf20Sopenharmony_ci * OUT endpoints *volEndpoints) 4208c2ecf20Sopenharmony_ci */ 4218c2ecf20Sopenharmony_cistatic int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci struct afs_addr_list *alist; 4248c2ecf20Sopenharmony_ci __be32 *bp; 4258c2ecf20Sopenharmony_ci u32 uniquifier, size; 4268c2ecf20Sopenharmony_ci int ret; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci _enter("{%u,%zu,%u}", 4298c2ecf20Sopenharmony_ci call->unmarshall, iov_iter_count(call->iter), call->count2); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci switch (call->unmarshall) { 4328c2ecf20Sopenharmony_ci case 0: 4338c2ecf20Sopenharmony_ci afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32)); 4348c2ecf20Sopenharmony_ci call->unmarshall = 1; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci /* Extract the returned uuid, uniquifier, fsEndpoints count and 4378c2ecf20Sopenharmony_ci * either the first fsEndpoint type or the volEndpoints 4388c2ecf20Sopenharmony_ci * count if there are no fsEndpoints. */ 4398c2ecf20Sopenharmony_ci fallthrough; 4408c2ecf20Sopenharmony_ci case 1: 4418c2ecf20Sopenharmony_ci ret = afs_extract_data(call, true); 4428c2ecf20Sopenharmony_ci if (ret < 0) 4438c2ecf20Sopenharmony_ci return ret; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci bp = call->buffer + sizeof(uuid_t); 4468c2ecf20Sopenharmony_ci uniquifier = ntohl(*bp++); 4478c2ecf20Sopenharmony_ci call->count = ntohl(*bp++); 4488c2ecf20Sopenharmony_ci call->count2 = ntohl(*bp); /* Type or next count */ 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci if (call->count > YFS_MAXENDPOINTS) 4518c2ecf20Sopenharmony_ci return afs_protocol_error(call, afs_eproto_yvl_fsendpt_num); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT); 4548c2ecf20Sopenharmony_ci if (!alist) 4558c2ecf20Sopenharmony_ci return -ENOMEM; 4568c2ecf20Sopenharmony_ci alist->version = uniquifier; 4578c2ecf20Sopenharmony_ci call->ret_alist = alist; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci if (call->count == 0) 4608c2ecf20Sopenharmony_ci goto extract_volendpoints; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci next_fsendpoint: 4638c2ecf20Sopenharmony_ci switch (call->count2) { 4648c2ecf20Sopenharmony_ci case YFS_ENDPOINT_IPV4: 4658c2ecf20Sopenharmony_ci size = sizeof(__be32) * (1 + 1 + 1); 4668c2ecf20Sopenharmony_ci break; 4678c2ecf20Sopenharmony_ci case YFS_ENDPOINT_IPV6: 4688c2ecf20Sopenharmony_ci size = sizeof(__be32) * (1 + 4 + 1); 4698c2ecf20Sopenharmony_ci break; 4708c2ecf20Sopenharmony_ci default: 4718c2ecf20Sopenharmony_ci return afs_protocol_error(call, afs_eproto_yvl_fsendpt_type); 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci size += sizeof(__be32); 4758c2ecf20Sopenharmony_ci afs_extract_to_buf(call, size); 4768c2ecf20Sopenharmony_ci call->unmarshall = 2; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci fallthrough; /* and extract fsEndpoints[] entries */ 4798c2ecf20Sopenharmony_ci case 2: 4808c2ecf20Sopenharmony_ci ret = afs_extract_data(call, true); 4818c2ecf20Sopenharmony_ci if (ret < 0) 4828c2ecf20Sopenharmony_ci return ret; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci alist = call->ret_alist; 4858c2ecf20Sopenharmony_ci bp = call->buffer; 4868c2ecf20Sopenharmony_ci switch (call->count2) { 4878c2ecf20Sopenharmony_ci case YFS_ENDPOINT_IPV4: 4888c2ecf20Sopenharmony_ci if (ntohl(bp[0]) != sizeof(__be32) * 2) 4898c2ecf20Sopenharmony_ci return afs_protocol_error( 4908c2ecf20Sopenharmony_ci call, afs_eproto_yvl_fsendpt4_len); 4918c2ecf20Sopenharmony_ci afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2])); 4928c2ecf20Sopenharmony_ci bp += 3; 4938c2ecf20Sopenharmony_ci break; 4948c2ecf20Sopenharmony_ci case YFS_ENDPOINT_IPV6: 4958c2ecf20Sopenharmony_ci if (ntohl(bp[0]) != sizeof(__be32) * 5) 4968c2ecf20Sopenharmony_ci return afs_protocol_error( 4978c2ecf20Sopenharmony_ci call, afs_eproto_yvl_fsendpt6_len); 4988c2ecf20Sopenharmony_ci afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5])); 4998c2ecf20Sopenharmony_ci bp += 6; 5008c2ecf20Sopenharmony_ci break; 5018c2ecf20Sopenharmony_ci default: 5028c2ecf20Sopenharmony_ci return afs_protocol_error(call, afs_eproto_yvl_fsendpt_type); 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* Got either the type of the next entry or the count of 5068c2ecf20Sopenharmony_ci * volEndpoints if no more fsEndpoints. 5078c2ecf20Sopenharmony_ci */ 5088c2ecf20Sopenharmony_ci call->count2 = ntohl(*bp++); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci call->count--; 5118c2ecf20Sopenharmony_ci if (call->count > 0) 5128c2ecf20Sopenharmony_ci goto next_fsendpoint; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci extract_volendpoints: 5158c2ecf20Sopenharmony_ci /* Extract the list of volEndpoints. */ 5168c2ecf20Sopenharmony_ci call->count = call->count2; 5178c2ecf20Sopenharmony_ci if (!call->count) 5188c2ecf20Sopenharmony_ci goto end; 5198c2ecf20Sopenharmony_ci if (call->count > YFS_MAXENDPOINTS) 5208c2ecf20Sopenharmony_ci return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type); 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci afs_extract_to_buf(call, 1 * sizeof(__be32)); 5238c2ecf20Sopenharmony_ci call->unmarshall = 3; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci /* Extract the type of volEndpoints[0]. Normally we would 5268c2ecf20Sopenharmony_ci * extract the type of the next endpoint when we extract the 5278c2ecf20Sopenharmony_ci * data of the current one, but this is the first... 5288c2ecf20Sopenharmony_ci */ 5298c2ecf20Sopenharmony_ci fallthrough; 5308c2ecf20Sopenharmony_ci case 3: 5318c2ecf20Sopenharmony_ci ret = afs_extract_data(call, true); 5328c2ecf20Sopenharmony_ci if (ret < 0) 5338c2ecf20Sopenharmony_ci return ret; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci bp = call->buffer; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci next_volendpoint: 5388c2ecf20Sopenharmony_ci call->count2 = ntohl(*bp++); 5398c2ecf20Sopenharmony_ci switch (call->count2) { 5408c2ecf20Sopenharmony_ci case YFS_ENDPOINT_IPV4: 5418c2ecf20Sopenharmony_ci size = sizeof(__be32) * (1 + 1 + 1); 5428c2ecf20Sopenharmony_ci break; 5438c2ecf20Sopenharmony_ci case YFS_ENDPOINT_IPV6: 5448c2ecf20Sopenharmony_ci size = sizeof(__be32) * (1 + 4 + 1); 5458c2ecf20Sopenharmony_ci break; 5468c2ecf20Sopenharmony_ci default: 5478c2ecf20Sopenharmony_ci return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type); 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci if (call->count > 1) 5518c2ecf20Sopenharmony_ci size += sizeof(__be32); /* Get next type too */ 5528c2ecf20Sopenharmony_ci afs_extract_to_buf(call, size); 5538c2ecf20Sopenharmony_ci call->unmarshall = 4; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci fallthrough; /* and extract volEndpoints[] entries */ 5568c2ecf20Sopenharmony_ci case 4: 5578c2ecf20Sopenharmony_ci ret = afs_extract_data(call, true); 5588c2ecf20Sopenharmony_ci if (ret < 0) 5598c2ecf20Sopenharmony_ci return ret; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci bp = call->buffer; 5628c2ecf20Sopenharmony_ci switch (call->count2) { 5638c2ecf20Sopenharmony_ci case YFS_ENDPOINT_IPV4: 5648c2ecf20Sopenharmony_ci if (ntohl(bp[0]) != sizeof(__be32) * 2) 5658c2ecf20Sopenharmony_ci return afs_protocol_error( 5668c2ecf20Sopenharmony_ci call, afs_eproto_yvl_vlendpt4_len); 5678c2ecf20Sopenharmony_ci bp += 3; 5688c2ecf20Sopenharmony_ci break; 5698c2ecf20Sopenharmony_ci case YFS_ENDPOINT_IPV6: 5708c2ecf20Sopenharmony_ci if (ntohl(bp[0]) != sizeof(__be32) * 5) 5718c2ecf20Sopenharmony_ci return afs_protocol_error( 5728c2ecf20Sopenharmony_ci call, afs_eproto_yvl_vlendpt6_len); 5738c2ecf20Sopenharmony_ci bp += 6; 5748c2ecf20Sopenharmony_ci break; 5758c2ecf20Sopenharmony_ci default: 5768c2ecf20Sopenharmony_ci return afs_protocol_error(call, afs_eproto_yvl_vlendpt_type); 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci /* Got either the type of the next entry or the count of 5808c2ecf20Sopenharmony_ci * volEndpoints if no more fsEndpoints. 5818c2ecf20Sopenharmony_ci */ 5828c2ecf20Sopenharmony_ci call->count--; 5838c2ecf20Sopenharmony_ci if (call->count > 0) 5848c2ecf20Sopenharmony_ci goto next_volendpoint; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci end: 5878c2ecf20Sopenharmony_ci afs_extract_discard(call, 0); 5888c2ecf20Sopenharmony_ci call->unmarshall = 5; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci fallthrough; /* Done */ 5918c2ecf20Sopenharmony_ci case 5: 5928c2ecf20Sopenharmony_ci ret = afs_extract_data(call, false); 5938c2ecf20Sopenharmony_ci if (ret < 0) 5948c2ecf20Sopenharmony_ci return ret; 5958c2ecf20Sopenharmony_ci call->unmarshall = 6; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci case 6: 5988c2ecf20Sopenharmony_ci break; 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci _leave(" = 0 [done]"); 6028c2ecf20Sopenharmony_ci return 0; 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci/* 6068c2ecf20Sopenharmony_ci * YFSVL.GetEndpoints operation type. 6078c2ecf20Sopenharmony_ci */ 6088c2ecf20Sopenharmony_cistatic const struct afs_call_type afs_YFSVLGetEndpoints = { 6098c2ecf20Sopenharmony_ci .name = "YFSVL.GetEndpoints", 6108c2ecf20Sopenharmony_ci .op = afs_YFSVL_GetEndpoints, 6118c2ecf20Sopenharmony_ci .deliver = afs_deliver_yfsvl_get_endpoints, 6128c2ecf20Sopenharmony_ci .destructor = afs_vl_get_addrs_u_destructor, 6138c2ecf20Sopenharmony_ci}; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci/* 6168c2ecf20Sopenharmony_ci * Dispatch an operation to get the addresses for a server, where the server is 6178c2ecf20Sopenharmony_ci * nominated by UUID. 6188c2ecf20Sopenharmony_ci */ 6198c2ecf20Sopenharmony_cistruct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc, 6208c2ecf20Sopenharmony_ci const uuid_t *uuid) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci struct afs_call *call; 6238c2ecf20Sopenharmony_ci struct afs_net *net = vc->cell->net; 6248c2ecf20Sopenharmony_ci __be32 *bp; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci _enter(""); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints, 6298c2ecf20Sopenharmony_ci sizeof(__be32) * 2 + sizeof(*uuid), 6308c2ecf20Sopenharmony_ci sizeof(struct in6_addr) + sizeof(__be32) * 3); 6318c2ecf20Sopenharmony_ci if (!call) 6328c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci call->key = vc->key; 6358c2ecf20Sopenharmony_ci call->ret_alist = NULL; 6368c2ecf20Sopenharmony_ci call->max_lifespan = AFS_VL_MAX_LIFESPAN; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* Marshall the parameters */ 6398c2ecf20Sopenharmony_ci bp = call->request; 6408c2ecf20Sopenharmony_ci *bp++ = htonl(YVLGETENDPOINTS); 6418c2ecf20Sopenharmony_ci *bp++ = htonl(YFS_SERVER_UUID); 6428c2ecf20Sopenharmony_ci memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */ 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci trace_afs_make_vl_call(call); 6458c2ecf20Sopenharmony_ci afs_make_call(&vc->ac, call, GFP_KERNEL); 6468c2ecf20Sopenharmony_ci return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac); 6478c2ecf20Sopenharmony_ci} 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci/* 6508c2ecf20Sopenharmony_ci * Deliver reply data to a YFSVL.GetCellName operation. 6518c2ecf20Sopenharmony_ci */ 6528c2ecf20Sopenharmony_cistatic int afs_deliver_yfsvl_get_cell_name(struct afs_call *call) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci char *cell_name; 6558c2ecf20Sopenharmony_ci u32 namesz, paddedsz; 6568c2ecf20Sopenharmony_ci int ret; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci _enter("{%u,%zu/%u}", 6598c2ecf20Sopenharmony_ci call->unmarshall, iov_iter_count(call->iter), call->count); 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci switch (call->unmarshall) { 6628c2ecf20Sopenharmony_ci case 0: 6638c2ecf20Sopenharmony_ci afs_extract_to_tmp(call); 6648c2ecf20Sopenharmony_ci call->unmarshall++; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci fallthrough; /* and extract the cell name length */ 6678c2ecf20Sopenharmony_ci case 1: 6688c2ecf20Sopenharmony_ci ret = afs_extract_data(call, true); 6698c2ecf20Sopenharmony_ci if (ret < 0) 6708c2ecf20Sopenharmony_ci return ret; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci namesz = ntohl(call->tmp); 6738c2ecf20Sopenharmony_ci if (namesz > AFS_MAXCELLNAME) 6748c2ecf20Sopenharmony_ci return afs_protocol_error(call, afs_eproto_cellname_len); 6758c2ecf20Sopenharmony_ci paddedsz = (namesz + 3) & ~3; 6768c2ecf20Sopenharmony_ci call->count = namesz; 6778c2ecf20Sopenharmony_ci call->count2 = paddedsz - namesz; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci cell_name = kmalloc(namesz + 1, GFP_KERNEL); 6808c2ecf20Sopenharmony_ci if (!cell_name) 6818c2ecf20Sopenharmony_ci return -ENOMEM; 6828c2ecf20Sopenharmony_ci cell_name[namesz] = 0; 6838c2ecf20Sopenharmony_ci call->ret_str = cell_name; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci afs_extract_begin(call, cell_name, namesz); 6868c2ecf20Sopenharmony_ci call->unmarshall++; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci fallthrough; /* and extract cell name */ 6898c2ecf20Sopenharmony_ci case 2: 6908c2ecf20Sopenharmony_ci ret = afs_extract_data(call, true); 6918c2ecf20Sopenharmony_ci if (ret < 0) 6928c2ecf20Sopenharmony_ci return ret; 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci afs_extract_discard(call, call->count2); 6958c2ecf20Sopenharmony_ci call->unmarshall++; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci fallthrough; /* and extract padding */ 6988c2ecf20Sopenharmony_ci case 3: 6998c2ecf20Sopenharmony_ci ret = afs_extract_data(call, false); 7008c2ecf20Sopenharmony_ci if (ret < 0) 7018c2ecf20Sopenharmony_ci return ret; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci call->unmarshall++; 7048c2ecf20Sopenharmony_ci break; 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci _leave(" = 0 [done]"); 7088c2ecf20Sopenharmony_ci return 0; 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_cistatic void afs_destroy_yfsvl_get_cell_name(struct afs_call *call) 7128c2ecf20Sopenharmony_ci{ 7138c2ecf20Sopenharmony_ci kfree(call->ret_str); 7148c2ecf20Sopenharmony_ci afs_flat_call_destructor(call); 7158c2ecf20Sopenharmony_ci} 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci/* 7188c2ecf20Sopenharmony_ci * VL.GetCapabilities operation type 7198c2ecf20Sopenharmony_ci */ 7208c2ecf20Sopenharmony_cistatic const struct afs_call_type afs_YFSVLGetCellName = { 7218c2ecf20Sopenharmony_ci .name = "YFSVL.GetCellName", 7228c2ecf20Sopenharmony_ci .op = afs_YFSVL_GetCellName, 7238c2ecf20Sopenharmony_ci .deliver = afs_deliver_yfsvl_get_cell_name, 7248c2ecf20Sopenharmony_ci .destructor = afs_destroy_yfsvl_get_cell_name, 7258c2ecf20Sopenharmony_ci}; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci/* 7288c2ecf20Sopenharmony_ci * Probe a volume server for the capabilities that it supports. This can 7298c2ecf20Sopenharmony_ci * return up to 196 words. 7308c2ecf20Sopenharmony_ci * 7318c2ecf20Sopenharmony_ci * We use this to probe for service upgrade to determine what the server at the 7328c2ecf20Sopenharmony_ci * other end supports. 7338c2ecf20Sopenharmony_ci */ 7348c2ecf20Sopenharmony_cichar *afs_yfsvl_get_cell_name(struct afs_vl_cursor *vc) 7358c2ecf20Sopenharmony_ci{ 7368c2ecf20Sopenharmony_ci struct afs_call *call; 7378c2ecf20Sopenharmony_ci struct afs_net *net = vc->cell->net; 7388c2ecf20Sopenharmony_ci __be32 *bp; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci _enter(""); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci call = afs_alloc_flat_call(net, &afs_YFSVLGetCellName, 1 * 4, 0); 7438c2ecf20Sopenharmony_ci if (!call) 7448c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci call->key = vc->key; 7478c2ecf20Sopenharmony_ci call->ret_str = NULL; 7488c2ecf20Sopenharmony_ci call->max_lifespan = AFS_VL_MAX_LIFESPAN; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci /* marshall the parameters */ 7518c2ecf20Sopenharmony_ci bp = call->request; 7528c2ecf20Sopenharmony_ci *bp++ = htonl(YVLGETCELLNAME); 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci /* Can't take a ref on server */ 7558c2ecf20Sopenharmony_ci trace_afs_make_vl_call(call); 7568c2ecf20Sopenharmony_ci afs_make_call(&vc->ac, call, GFP_KERNEL); 7578c2ecf20Sopenharmony_ci return (char *)afs_wait_for_call_to_complete(call, &vc->ac); 7588c2ecf20Sopenharmony_ci} 759