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