vlclient.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /* AFS Volume Location Service client
  2. *
  3. * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/gfp.h>
  12. #include <linux/init.h>
  13. #include <linux/sched.h>
  14. #include "afs_fs.h"
  15. #include "internal.h"
  16. /*
  17. * Deliver reply data to a VL.GetEntryByNameU call.
  18. */
  19. static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)
  20. {
  21. struct afs_uvldbentry__xdr *uvldb;
  22. struct afs_vldb_entry *entry;
  23. bool new_only = false;
  24. u32 tmp, nr_servers, vlflags;
  25. int i, ret;
  26. _enter("");
  27. ret = afs_transfer_reply(call);
  28. if (ret < 0)
  29. return ret;
  30. /* unmarshall the reply once we've received all of it */
  31. uvldb = call->buffer;
  32. entry = call->reply[0];
  33. nr_servers = ntohl(uvldb->nServers);
  34. if (nr_servers > AFS_NMAXNSERVERS)
  35. nr_servers = AFS_NMAXNSERVERS;
  36. for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++)
  37. entry->name[i] = (u8)ntohl(uvldb->name[i]);
  38. entry->name[i] = 0;
  39. entry->name_len = strlen(entry->name);
  40. /* If there is a new replication site that we can use, ignore all the
  41. * sites that aren't marked as new.
  42. */
  43. for (i = 0; i < nr_servers; i++) {
  44. tmp = ntohl(uvldb->serverFlags[i]);
  45. if (!(tmp & AFS_VLSF_DONTUSE) &&
  46. (tmp & AFS_VLSF_NEWREPSITE))
  47. new_only = true;
  48. }
  49. vlflags = ntohl(uvldb->flags);
  50. for (i = 0; i < nr_servers; i++) {
  51. struct afs_uuid__xdr *xdr;
  52. struct afs_uuid *uuid;
  53. int j;
  54. tmp = ntohl(uvldb->serverFlags[i]);
  55. if (tmp & AFS_VLSF_DONTUSE ||
  56. (new_only && !(tmp & AFS_VLSF_NEWREPSITE)))
  57. continue;
  58. if (tmp & AFS_VLSF_RWVOL) {
  59. entry->fs_mask[i] |= AFS_VOL_VTM_RW;
  60. if (vlflags & AFS_VLF_BACKEXISTS)
  61. entry->fs_mask[i] |= AFS_VOL_VTM_BAK;
  62. }
  63. if (tmp & AFS_VLSF_ROVOL)
  64. entry->fs_mask[i] |= AFS_VOL_VTM_RO;
  65. if (!entry->fs_mask[i])
  66. continue;
  67. xdr = &uvldb->serverNumber[i];
  68. uuid = (struct afs_uuid *)&entry->fs_server[i];
  69. uuid->time_low = xdr->time_low;
  70. uuid->time_mid = htons(ntohl(xdr->time_mid));
  71. uuid->time_hi_and_version = htons(ntohl(xdr->time_hi_and_version));
  72. uuid->clock_seq_hi_and_reserved = (u8)ntohl(xdr->clock_seq_hi_and_reserved);
  73. uuid->clock_seq_low = (u8)ntohl(xdr->clock_seq_low);
  74. for (j = 0; j < 6; j++)
  75. uuid->node[j] = (u8)ntohl(xdr->node[j]);
  76. entry->nr_servers++;
  77. }
  78. for (i = 0; i < AFS_MAXTYPES; i++)
  79. entry->vid[i] = ntohl(uvldb->volumeId[i]);
  80. if (vlflags & AFS_VLF_RWEXISTS)
  81. __set_bit(AFS_VLDB_HAS_RW, &entry->flags);
  82. if (vlflags & AFS_VLF_ROEXISTS)
  83. __set_bit(AFS_VLDB_HAS_RO, &entry->flags);
  84. if (vlflags & AFS_VLF_BACKEXISTS)
  85. __set_bit(AFS_VLDB_HAS_BAK, &entry->flags);
  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. __set_bit(AFS_VLDB_QUERY_VALID, &entry->flags);
  91. _leave(" = 0 [done]");
  92. return 0;
  93. }
  94. static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call)
  95. {
  96. kfree(call->reply[0]);
  97. afs_flat_call_destructor(call);
  98. }
  99. /*
  100. * VL.GetEntryByNameU operation type.
  101. */
  102. static const struct afs_call_type afs_RXVLGetEntryByNameU = {
  103. .name = "VL.GetEntryByNameU",
  104. .op = afs_VL_GetEntryByNameU,
  105. .deliver = afs_deliver_vl_get_entry_by_name_u,
  106. .destructor = afs_destroy_vl_get_entry_by_name_u,
  107. };
  108. /*
  109. * Dispatch a get volume entry by name or ID operation (uuid variant). If the
  110. * volname is a decimal number then it's a volume ID not a volume name.
  111. */
  112. struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc,
  113. const char *volname,
  114. int volnamesz)
  115. {
  116. struct afs_vldb_entry *entry;
  117. struct afs_call *call;
  118. struct afs_net *net = vc->cell->net;
  119. size_t reqsz, padsz;
  120. __be32 *bp;
  121. _enter("");
  122. padsz = (4 - (volnamesz & 3)) & 3;
  123. reqsz = 8 + volnamesz + padsz;
  124. entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL);
  125. if (!entry)
  126. return ERR_PTR(-ENOMEM);
  127. call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz,
  128. sizeof(struct afs_uvldbentry__xdr));
  129. if (!call) {
  130. kfree(entry);
  131. return ERR_PTR(-ENOMEM);
  132. }
  133. call->key = vc->key;
  134. call->reply[0] = entry;
  135. call->ret_reply0 = true;
  136. /* Marshall the parameters */
  137. bp = call->request;
  138. *bp++ = htonl(VLGETENTRYBYNAMEU);
  139. *bp++ = htonl(volnamesz);
  140. memcpy(bp, volname, volnamesz);
  141. if (padsz > 0)
  142. memset((void *)bp + volnamesz, 0, padsz);
  143. trace_afs_make_vl_call(call);
  144. return (struct afs_vldb_entry *)afs_make_call(&vc->ac, call, GFP_KERNEL, false);
  145. }
  146. /*
  147. * Deliver reply data to a VL.GetAddrsU call.
  148. *
  149. * GetAddrsU(IN ListAddrByAttributes *inaddr,
  150. * OUT afsUUID *uuidp1,
  151. * OUT uint32_t *uniquifier,
  152. * OUT uint32_t *nentries,
  153. * OUT bulkaddrs *blkaddrs);
  154. */
  155. static int afs_deliver_vl_get_addrs_u(struct afs_call *call)
  156. {
  157. struct afs_addr_list *alist;
  158. __be32 *bp;
  159. u32 uniquifier, nentries, count;
  160. int i, ret;
  161. _enter("{%u,%zu/%u}",
  162. call->unmarshall, iov_iter_count(call->_iter), call->count);
  163. switch (call->unmarshall) {
  164. case 0:
  165. afs_extract_to_buf(call,
  166. sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
  167. call->unmarshall++;
  168. /* Extract the returned uuid, uniquifier, nentries and blkaddrs size */
  169. case 1:
  170. ret = afs_extract_data(call, true);
  171. if (ret < 0)
  172. return ret;
  173. bp = call->buffer + sizeof(struct afs_uuid__xdr);
  174. uniquifier = ntohl(*bp++);
  175. nentries = ntohl(*bp++);
  176. count = ntohl(*bp);
  177. nentries = min(nentries, count);
  178. alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT);
  179. if (!alist)
  180. return -ENOMEM;
  181. alist->version = uniquifier;
  182. call->reply[0] = alist;
  183. call->count = count;
  184. call->count2 = nentries;
  185. call->unmarshall++;
  186. more_entries:
  187. count = min(call->count, 4U);
  188. afs_extract_to_buf(call, count * sizeof(__be32));
  189. /* Extract entries */
  190. case 2:
  191. ret = afs_extract_data(call, call->count > 4);
  192. if (ret < 0)
  193. return ret;
  194. alist = call->reply[0];
  195. bp = call->buffer;
  196. count = min(call->count, 4U);
  197. for (i = 0; i < count; i++)
  198. if (alist->nr_addrs < call->count2)
  199. afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT);
  200. call->count -= count;
  201. if (call->count > 0)
  202. goto more_entries;
  203. call->unmarshall++;
  204. break;
  205. }
  206. _leave(" = 0 [done]");
  207. return 0;
  208. }
  209. static void afs_vl_get_addrs_u_destructor(struct afs_call *call)
  210. {
  211. afs_put_server(call->net, (struct afs_server *)call->reply[0]);
  212. kfree(call->reply[1]);
  213. return afs_flat_call_destructor(call);
  214. }
  215. /*
  216. * VL.GetAddrsU operation type.
  217. */
  218. static const struct afs_call_type afs_RXVLGetAddrsU = {
  219. .name = "VL.GetAddrsU",
  220. .op = afs_VL_GetAddrsU,
  221. .deliver = afs_deliver_vl_get_addrs_u,
  222. .destructor = afs_vl_get_addrs_u_destructor,
  223. };
  224. /*
  225. * Dispatch an operation to get the addresses for a server, where the server is
  226. * nominated by UUID.
  227. */
  228. struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc,
  229. const uuid_t *uuid)
  230. {
  231. struct afs_ListAddrByAttributes__xdr *r;
  232. const struct afs_uuid *u = (const struct afs_uuid *)uuid;
  233. struct afs_call *call;
  234. struct afs_net *net = vc->cell->net;
  235. __be32 *bp;
  236. int i;
  237. _enter("");
  238. call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU,
  239. sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr),
  240. sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32));
  241. if (!call)
  242. return ERR_PTR(-ENOMEM);
  243. call->key = vc->key;
  244. call->reply[0] = NULL;
  245. call->ret_reply0 = true;
  246. /* Marshall the parameters */
  247. bp = call->request;
  248. *bp++ = htonl(VLGETADDRSU);
  249. r = (struct afs_ListAddrByAttributes__xdr *)bp;
  250. r->Mask = htonl(AFS_VLADDR_UUID);
  251. r->ipaddr = 0;
  252. r->index = 0;
  253. r->spare = 0;
  254. r->uuid.time_low = u->time_low;
  255. r->uuid.time_mid = htonl(ntohs(u->time_mid));
  256. r->uuid.time_hi_and_version = htonl(ntohs(u->time_hi_and_version));
  257. r->uuid.clock_seq_hi_and_reserved = htonl(u->clock_seq_hi_and_reserved);
  258. r->uuid.clock_seq_low = htonl(u->clock_seq_low);
  259. for (i = 0; i < 6; i++)
  260. r->uuid.node[i] = htonl(u->node[i]);
  261. trace_afs_make_vl_call(call);
  262. return (struct afs_addr_list *)afs_make_call(&vc->ac, call, GFP_KERNEL, false);
  263. }
  264. /*
  265. * Deliver reply data to an VL.GetCapabilities operation.
  266. */
  267. static int afs_deliver_vl_get_capabilities(struct afs_call *call)
  268. {
  269. u32 count;
  270. int ret;
  271. _enter("{%u,%zu/%u}",
  272. call->unmarshall, iov_iter_count(call->_iter), call->count);
  273. switch (call->unmarshall) {
  274. case 0:
  275. afs_extract_to_tmp(call);
  276. call->unmarshall++;
  277. /* Extract the capabilities word count */
  278. case 1:
  279. ret = afs_extract_data(call, true);
  280. if (ret < 0)
  281. return ret;
  282. count = ntohl(call->tmp);
  283. call->count = count;
  284. call->count2 = count;
  285. call->unmarshall++;
  286. afs_extract_discard(call, count * sizeof(__be32));
  287. /* Extract capabilities words */
  288. case 2:
  289. ret = afs_extract_data(call, false);
  290. if (ret < 0)
  291. return ret;
  292. /* TODO: Examine capabilities */
  293. call->unmarshall++;
  294. break;
  295. }
  296. _leave(" = 0 [done]");
  297. return 0;
  298. }
  299. static void afs_destroy_vl_get_capabilities(struct afs_call *call)
  300. {
  301. struct afs_vlserver *server = call->reply[0];
  302. afs_put_vlserver(call->net, server);
  303. afs_flat_call_destructor(call);
  304. }
  305. /*
  306. * VL.GetCapabilities operation type
  307. */
  308. static const struct afs_call_type afs_RXVLGetCapabilities = {
  309. .name = "VL.GetCapabilities",
  310. .op = afs_VL_GetCapabilities,
  311. .deliver = afs_deliver_vl_get_capabilities,
  312. .done = afs_vlserver_probe_result,
  313. .destructor = afs_destroy_vl_get_capabilities,
  314. };
  315. /*
  316. * Probe a volume server for the capabilities that it supports. This can
  317. * return up to 196 words.
  318. *
  319. * We use this to probe for service upgrade to determine what the server at the
  320. * other end supports.
  321. */
  322. int afs_vl_get_capabilities(struct afs_net *net,
  323. struct afs_addr_cursor *ac,
  324. struct key *key,
  325. struct afs_vlserver *server,
  326. unsigned int server_index,
  327. bool async)
  328. {
  329. struct afs_call *call;
  330. __be32 *bp;
  331. _enter("");
  332. call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4);
  333. if (!call)
  334. return -ENOMEM;
  335. call->key = key;
  336. call->reply[0] = afs_get_vlserver(server);
  337. call->reply[1] = (void *)(long)server_index;
  338. call->upgrade = true;
  339. call->want_reply_time = true;
  340. /* marshall the parameters */
  341. bp = call->request;
  342. *bp++ = htonl(VLGETCAPABILITIES);
  343. /* Can't take a ref on server */
  344. trace_afs_make_vl_call(call);
  345. return afs_make_call(ac, call, GFP_KERNEL, async);
  346. }
  347. /*
  348. * Deliver reply data to a YFSVL.GetEndpoints call.
  349. *
  350. * GetEndpoints(IN yfsServerAttributes *attr,
  351. * OUT opr_uuid *uuid,
  352. * OUT afs_int32 *uniquifier,
  353. * OUT endpoints *fsEndpoints,
  354. * OUT endpoints *volEndpoints)
  355. */
  356. static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
  357. {
  358. struct afs_addr_list *alist;
  359. __be32 *bp;
  360. u32 uniquifier, size;
  361. int ret;
  362. _enter("{%u,%zu,%u}",
  363. call->unmarshall, iov_iter_count(call->_iter), call->count2);
  364. switch (call->unmarshall) {
  365. case 0:
  366. afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32));
  367. call->unmarshall = 1;
  368. /* Extract the returned uuid, uniquifier, fsEndpoints count and
  369. * either the first fsEndpoint type or the volEndpoints
  370. * count if there are no fsEndpoints. */
  371. case 1:
  372. ret = afs_extract_data(call, true);
  373. if (ret < 0)
  374. return ret;
  375. bp = call->buffer + sizeof(uuid_t);
  376. uniquifier = ntohl(*bp++);
  377. call->count = ntohl(*bp++);
  378. call->count2 = ntohl(*bp); /* Type or next count */
  379. if (call->count > YFS_MAXENDPOINTS)
  380. return afs_protocol_error(call, -EBADMSG,
  381. afs_eproto_yvl_fsendpt_num);
  382. alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT);
  383. if (!alist)
  384. return -ENOMEM;
  385. alist->version = uniquifier;
  386. call->reply[0] = alist;
  387. if (call->count == 0)
  388. goto extract_volendpoints;
  389. next_fsendpoint:
  390. switch (call->count2) {
  391. case YFS_ENDPOINT_IPV4:
  392. size = sizeof(__be32) * (1 + 1 + 1);
  393. break;
  394. case YFS_ENDPOINT_IPV6:
  395. size = sizeof(__be32) * (1 + 4 + 1);
  396. break;
  397. default:
  398. return afs_protocol_error(call, -EBADMSG,
  399. afs_eproto_yvl_fsendpt_type);
  400. }
  401. size += sizeof(__be32);
  402. afs_extract_to_buf(call, size);
  403. call->unmarshall = 2;
  404. /* Extract fsEndpoints[] entries */
  405. case 2:
  406. ret = afs_extract_data(call, true);
  407. if (ret < 0)
  408. return ret;
  409. alist = call->reply[0];
  410. bp = call->buffer;
  411. switch (call->count2) {
  412. case YFS_ENDPOINT_IPV4:
  413. if (ntohl(bp[0]) != sizeof(__be32) * 2)
  414. return afs_protocol_error(call, -EBADMSG,
  415. afs_eproto_yvl_fsendpt4_len);
  416. afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2]));
  417. bp += 3;
  418. break;
  419. case YFS_ENDPOINT_IPV6:
  420. if (ntohl(bp[0]) != sizeof(__be32) * 5)
  421. return afs_protocol_error(call, -EBADMSG,
  422. afs_eproto_yvl_fsendpt6_len);
  423. afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5]));
  424. bp += 6;
  425. break;
  426. default:
  427. return afs_protocol_error(call, -EBADMSG,
  428. afs_eproto_yvl_fsendpt_type);
  429. }
  430. /* Got either the type of the next entry or the count of
  431. * volEndpoints if no more fsEndpoints.
  432. */
  433. call->count2 = ntohl(*bp++);
  434. call->count--;
  435. if (call->count > 0)
  436. goto next_fsendpoint;
  437. extract_volendpoints:
  438. /* Extract the list of volEndpoints. */
  439. call->count = call->count2;
  440. if (!call->count)
  441. goto end;
  442. if (call->count > YFS_MAXENDPOINTS)
  443. return afs_protocol_error(call, -EBADMSG,
  444. afs_eproto_yvl_vlendpt_type);
  445. afs_extract_to_buf(call, 1 * sizeof(__be32));
  446. call->unmarshall = 3;
  447. /* Extract the type of volEndpoints[0]. Normally we would
  448. * extract the type of the next endpoint when we extract the
  449. * data of the current one, but this is the first...
  450. */
  451. case 3:
  452. ret = afs_extract_data(call, true);
  453. if (ret < 0)
  454. return ret;
  455. bp = call->buffer;
  456. next_volendpoint:
  457. call->count2 = ntohl(*bp++);
  458. switch (call->count2) {
  459. case YFS_ENDPOINT_IPV4:
  460. size = sizeof(__be32) * (1 + 1 + 1);
  461. break;
  462. case YFS_ENDPOINT_IPV6:
  463. size = sizeof(__be32) * (1 + 4 + 1);
  464. break;
  465. default:
  466. return afs_protocol_error(call, -EBADMSG,
  467. afs_eproto_yvl_vlendpt_type);
  468. }
  469. if (call->count > 1)
  470. size += sizeof(__be32); /* Get next type too */
  471. afs_extract_to_buf(call, size);
  472. call->unmarshall = 4;
  473. /* Extract volEndpoints[] entries */
  474. case 4:
  475. ret = afs_extract_data(call, true);
  476. if (ret < 0)
  477. return ret;
  478. bp = call->buffer;
  479. switch (call->count2) {
  480. case YFS_ENDPOINT_IPV4:
  481. if (ntohl(bp[0]) != sizeof(__be32) * 2)
  482. return afs_protocol_error(call, -EBADMSG,
  483. afs_eproto_yvl_vlendpt4_len);
  484. bp += 3;
  485. break;
  486. case YFS_ENDPOINT_IPV6:
  487. if (ntohl(bp[0]) != sizeof(__be32) * 5)
  488. return afs_protocol_error(call, -EBADMSG,
  489. afs_eproto_yvl_vlendpt6_len);
  490. bp += 6;
  491. break;
  492. default:
  493. return afs_protocol_error(call, -EBADMSG,
  494. afs_eproto_yvl_vlendpt_type);
  495. }
  496. /* Got either the type of the next entry or the count of
  497. * volEndpoints if no more fsEndpoints.
  498. */
  499. call->count--;
  500. if (call->count > 0)
  501. goto next_volendpoint;
  502. end:
  503. afs_extract_discard(call, 0);
  504. call->unmarshall = 5;
  505. /* Done */
  506. case 5:
  507. ret = afs_extract_data(call, false);
  508. if (ret < 0)
  509. return ret;
  510. call->unmarshall = 6;
  511. case 6:
  512. break;
  513. }
  514. alist = call->reply[0];
  515. _leave(" = 0 [done]");
  516. return 0;
  517. }
  518. /*
  519. * YFSVL.GetEndpoints operation type.
  520. */
  521. static const struct afs_call_type afs_YFSVLGetEndpoints = {
  522. .name = "YFSVL.GetEndpoints",
  523. .op = afs_YFSVL_GetEndpoints,
  524. .deliver = afs_deliver_yfsvl_get_endpoints,
  525. .destructor = afs_vl_get_addrs_u_destructor,
  526. };
  527. /*
  528. * Dispatch an operation to get the addresses for a server, where the server is
  529. * nominated by UUID.
  530. */
  531. struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc,
  532. const uuid_t *uuid)
  533. {
  534. struct afs_call *call;
  535. struct afs_net *net = vc->cell->net;
  536. __be32 *bp;
  537. _enter("");
  538. call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints,
  539. sizeof(__be32) * 2 + sizeof(*uuid),
  540. sizeof(struct in6_addr) + sizeof(__be32) * 3);
  541. if (!call)
  542. return ERR_PTR(-ENOMEM);
  543. call->key = vc->key;
  544. call->reply[0] = NULL;
  545. call->ret_reply0 = true;
  546. /* Marshall the parameters */
  547. bp = call->request;
  548. *bp++ = htonl(YVLGETENDPOINTS);
  549. *bp++ = htonl(YFS_SERVER_UUID);
  550. memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */
  551. trace_afs_make_vl_call(call);
  552. return (struct afs_addr_list *)afs_make_call(&vc->ac, call, GFP_KERNEL, false);
  553. }