aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/vlclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/vlclient.c')
-rw-r--r--fs/afs/vlclient.c737
1 files changed, 130 insertions, 607 deletions
diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c
index 7b0e3192ee39..36c1306e09e0 100644
--- a/fs/afs/vlclient.c
+++ b/fs/afs/vlclient.c
@@ -1,4 +1,4 @@
1/* vlclient.c: AFS Volume Location Service client 1/* AFS Volume Location Service client
2 * 2 *
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
@@ -11,247 +11,76 @@
11 11
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/sched.h> 13#include <linux/sched.h>
14#include <rxrpc/rxrpc.h>
15#include <rxrpc/transport.h>
16#include <rxrpc/connection.h>
17#include <rxrpc/call.h>
18#include "server.h"
19#include "volume.h"
20#include "vlclient.h"
21#include "kafsasyncd.h"
22#include "kafstimod.h"
23#include "errors.h"
24#include "internal.h" 14#include "internal.h"
25 15
26#define VLGETENTRYBYID 503 /* AFS Get Cache Entry By ID operation ID */
27#define VLGETENTRYBYNAME 504 /* AFS Get Cache Entry By Name operation ID */
28#define VLPROBE 514 /* AFS Probe Volume Location Service operation ID */
29
30static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call);
31static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call);
32
33/*****************************************************************************/
34/* 16/*
35 * map afs VL abort codes to/from Linux error codes 17 * map volume locator abort codes to error codes
36 * - called with call->lock held
37 */ 18 */
38static void afs_rxvl_aemap(struct rxrpc_call *call) 19static int afs_vl_abort_to_error(u32 abort_code)
39{ 20{
40 int err; 21 _enter("%u", abort_code);
41 22
42 _enter("{%u,%u,%d}", 23 switch (abort_code) {
43 call->app_err_state, call->app_abort_code, call->app_errno); 24 case AFSVL_IDEXIST: return -EEXIST;
44 25 case AFSVL_IO: return -EREMOTEIO;
45 switch (call->app_err_state) { 26 case AFSVL_NAMEEXIST: return -EEXIST;
46 case RXRPC_ESTATE_LOCAL_ABORT: 27 case AFSVL_CREATEFAIL: return -EREMOTEIO;
47 call->app_abort_code = -call->app_errno; 28 case AFSVL_NOENT: return -ENOMEDIUM;
48 return; 29 case AFSVL_EMPTY: return -ENOMEDIUM;
49 30 case AFSVL_ENTDELETED: return -ENOMEDIUM;
50 case RXRPC_ESTATE_PEER_ABORT: 31 case AFSVL_BADNAME: return -EINVAL;
51 switch (call->app_abort_code) { 32 case AFSVL_BADINDEX: return -EINVAL;
52 case AFSVL_IDEXIST: err = -EEXIST; break; 33 case AFSVL_BADVOLTYPE: return -EINVAL;
53 case AFSVL_IO: err = -EREMOTEIO; break; 34 case AFSVL_BADSERVER: return -EINVAL;
54 case AFSVL_NAMEEXIST: err = -EEXIST; break; 35 case AFSVL_BADPARTITION: return -EINVAL;
55 case AFSVL_CREATEFAIL: err = -EREMOTEIO; break; 36 case AFSVL_REPSFULL: return -EFBIG;
56 case AFSVL_NOENT: err = -ENOMEDIUM; break; 37 case AFSVL_NOREPSERVER: return -ENOENT;
57 case AFSVL_EMPTY: err = -ENOMEDIUM; break; 38 case AFSVL_DUPREPSERVER: return -EEXIST;
58 case AFSVL_ENTDELETED: err = -ENOMEDIUM; break; 39 case AFSVL_RWNOTFOUND: return -ENOENT;
59 case AFSVL_BADNAME: err = -EINVAL; break; 40 case AFSVL_BADREFCOUNT: return -EINVAL;
60 case AFSVL_BADINDEX: err = -EINVAL; break; 41 case AFSVL_SIZEEXCEEDED: return -EINVAL;
61 case AFSVL_BADVOLTYPE: err = -EINVAL; break; 42 case AFSVL_BADENTRY: return -EINVAL;
62 case AFSVL_BADSERVER: err = -EINVAL; break; 43 case AFSVL_BADVOLIDBUMP: return -EINVAL;
63 case AFSVL_BADPARTITION: err = -EINVAL; break; 44 case AFSVL_IDALREADYHASHED: return -EINVAL;
64 case AFSVL_REPSFULL: err = -EFBIG; break; 45 case AFSVL_ENTRYLOCKED: return -EBUSY;
65 case AFSVL_NOREPSERVER: err = -ENOENT; break; 46 case AFSVL_BADVOLOPER: return -EBADRQC;
66 case AFSVL_DUPREPSERVER: err = -EEXIST; break; 47 case AFSVL_BADRELLOCKTYPE: return -EINVAL;
67 case AFSVL_RWNOTFOUND: err = -ENOENT; break; 48 case AFSVL_RERELEASE: return -EREMOTEIO;
68 case AFSVL_BADREFCOUNT: err = -EINVAL; break; 49 case AFSVL_BADSERVERFLAG: return -EINVAL;
69 case AFSVL_SIZEEXCEEDED: err = -EINVAL; break; 50 case AFSVL_PERM: return -EACCES;
70 case AFSVL_BADENTRY: err = -EINVAL; break; 51 case AFSVL_NOMEM: return -EREMOTEIO;
71 case AFSVL_BADVOLIDBUMP: err = -EINVAL; break;
72 case AFSVL_IDALREADYHASHED: err = -EINVAL; break;
73 case AFSVL_ENTRYLOCKED: err = -EBUSY; break;
74 case AFSVL_BADVOLOPER: err = -EBADRQC; break;
75 case AFSVL_BADRELLOCKTYPE: err = -EINVAL; break;
76 case AFSVL_RERELEASE: err = -EREMOTEIO; break;
77 case AFSVL_BADSERVERFLAG: err = -EINVAL; break;
78 case AFSVL_PERM: err = -EACCES; break;
79 case AFSVL_NOMEM: err = -EREMOTEIO; break;
80 default:
81 err = afs_abort_to_error(call->app_abort_code);
82 break;
83 }
84 call->app_errno = err;
85 return;
86
87 default: 52 default:
88 return; 53 return afs_abort_to_error(abort_code);
89 } 54 }
90} /* end afs_rxvl_aemap() */ 55}
91 56
92#if 0
93/*****************************************************************************/
94/* 57/*
95 * probe a volume location server to see if it is still alive -- unused 58 * deliver reply data to a VL.GetEntryByXXX call
96 */ 59 */
97static int afs_rxvl_probe(struct afs_server *server, int alloc_flags) 60static int afs_deliver_vl_get_entry_by_xxx(struct afs_call *call,
61 struct sk_buff *skb, bool last)
98{ 62{
99 struct rxrpc_connection *conn; 63 struct afs_cache_vlocation *entry;
100 struct rxrpc_call *call; 64 __be32 *bp;
101 struct kvec piov[1]; 65 u32 tmp;
102 size_t sent; 66 int loop;
103 int ret;
104 __be32 param[1];
105
106 DECLARE_WAITQUEUE(myself, current);
107
108 /* get hold of the vlserver connection */
109 ret = afs_server_get_vlconn(server, &conn);
110 if (ret < 0)
111 goto out;
112
113 /* create a call through that connection */
114 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);
115 if (ret < 0) {
116 printk("kAFS: Unable to create call: %d\n", ret);
117 goto out_put_conn;
118 }
119 call->app_opcode = VLPROBE;
120
121 /* we want to get event notifications from the call */
122 add_wait_queue(&call->waitq, &myself);
123
124 /* marshall the parameters */
125 param[0] = htonl(VLPROBE);
126 piov[0].iov_len = sizeof(param);
127 piov[0].iov_base = param;
128
129 /* send the parameters to the server */
130 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET,
131 alloc_flags, 0, &sent);
132 if (ret < 0)
133 goto abort;
134
135 /* wait for the reply to completely arrive */
136 for (;;) {
137 set_current_state(TASK_INTERRUPTIBLE);
138 if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY ||
139 signal_pending(current))
140 break;
141 schedule();
142 }
143 set_current_state(TASK_RUNNING);
144
145 ret = -EINTR;
146 if (signal_pending(current))
147 goto abort;
148
149 switch (call->app_call_state) {
150 case RXRPC_CSTATE_ERROR:
151 ret = call->app_errno;
152 goto out_unwait;
153
154 case RXRPC_CSTATE_CLNT_GOT_REPLY:
155 ret = 0;
156 goto out_unwait;
157
158 default:
159 BUG();
160 }
161
162 abort:
163 set_current_state(TASK_UNINTERRUPTIBLE);
164 rxrpc_call_abort(call, ret);
165 schedule();
166
167 out_unwait:
168 set_current_state(TASK_RUNNING);
169 remove_wait_queue(&call->waitq, &myself);
170 rxrpc_put_call(call);
171 out_put_conn:
172 rxrpc_put_connection(conn);
173 out:
174 return ret;
175 67
176} /* end afs_rxvl_probe() */ 68 _enter(",,%u", last);
177#endif
178 69
179/*****************************************************************************/ 70 afs_transfer_reply(call, skb);
180/* 71 if (!last)
181 * look up a volume location database entry by name 72 return 0;
182 */
183int afs_rxvl_get_entry_by_name(struct afs_server *server,
184 const char *volname,
185 unsigned volnamesz,
186 struct afs_cache_vlocation *entry)
187{
188 DECLARE_WAITQUEUE(myself, current);
189
190 struct rxrpc_connection *conn;
191 struct rxrpc_call *call;
192 struct kvec piov[3];
193 unsigned tmp;
194 size_t sent;
195 int ret, loop;
196 __be32 *bp, param[2], zero;
197
198 _enter(",%*.*s,%u,", volnamesz, volnamesz, volname, volnamesz);
199
200 memset(entry, 0, sizeof(*entry));
201
202 /* get hold of the vlserver connection */
203 ret = afs_server_get_vlconn(server, &conn);
204 if (ret < 0)
205 goto out;
206
207 /* create a call through that connection */
208 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);
209 if (ret < 0) {
210 printk("kAFS: Unable to create call: %d\n", ret);
211 goto out_put_conn;
212 }
213 call->app_opcode = VLGETENTRYBYNAME;
214 73
215 /* we want to get event notifications from the call */ 74 if (call->reply_size != call->reply_max)
216 add_wait_queue(&call->waitq, &myself); 75 return -EBADMSG;
217 76
218 /* marshall the parameters */ 77 /* unmarshall the reply once we've received all of it */
219 piov[1].iov_len = volnamesz; 78 entry = call->reply;
220 piov[1].iov_base = (char *) volname; 79 bp = call->buffer;
221
222 zero = 0;
223 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
224 piov[2].iov_base = &zero;
225
226 param[0] = htonl(VLGETENTRYBYNAME);
227 param[1] = htonl(piov[1].iov_len);
228
229 piov[0].iov_len = sizeof(param);
230 piov[0].iov_base = param;
231
232 /* send the parameters to the server */
233 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS,
234 0, &sent);
235 if (ret < 0)
236 goto abort;
237
238 /* wait for the reply to completely arrive */
239 bp = rxrpc_call_alloc_scratch(call, 384);
240
241 ret = rxrpc_call_read_data(call, bp, 384,
242 RXRPC_CALL_READ_BLOCK |
243 RXRPC_CALL_READ_ALL);
244 if (ret < 0) {
245 if (ret == -ECONNABORTED) {
246 ret = call->app_errno;
247 goto out_unwait;
248 }
249 goto abort;
250 }
251 80
252 /* unmarshall the reply */
253 for (loop = 0; loop < 64; loop++) 81 for (loop = 0; loop < 64; loop++)
254 entry->name[loop] = ntohl(*bp++); 82 entry->name[loop] = ntohl(*bp++);
83 entry->name[loop] = 0;
255 bp++; /* final NUL */ 84 bp++; /* final NUL */
256 85
257 bp++; /* type */ 86 bp++; /* type */
@@ -264,6 +93,7 @@ int afs_rxvl_get_entry_by_name(struct afs_server *server,
264 93
265 for (loop = 0; loop < 8; loop++) { 94 for (loop = 0; loop < 8; loop++) {
266 tmp = ntohl(*bp++); 95 tmp = ntohl(*bp++);
96 entry->srvtmask[loop] = 0;
267 if (tmp & AFS_VLSF_RWVOL) 97 if (tmp & AFS_VLSF_RWVOL)
268 entry->srvtmask[loop] |= AFS_VOL_VTM_RW; 98 entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
269 if (tmp & AFS_VLSF_ROVOL) 99 if (tmp & AFS_VLSF_ROVOL)
@@ -279,417 +109,110 @@ int afs_rxvl_get_entry_by_name(struct afs_server *server,
279 bp++; /* clone ID */ 109 bp++; /* clone ID */
280 110
281 tmp = ntohl(*bp++); /* flags */ 111 tmp = ntohl(*bp++); /* flags */
112 entry->vidmask = 0;
282 if (tmp & AFS_VLF_RWEXISTS) 113 if (tmp & AFS_VLF_RWEXISTS)
283 entry->vidmask |= AFS_VOL_VTM_RW; 114 entry->vidmask |= AFS_VOL_VTM_RW;
284 if (tmp & AFS_VLF_ROEXISTS) 115 if (tmp & AFS_VLF_ROEXISTS)
285 entry->vidmask |= AFS_VOL_VTM_RO; 116 entry->vidmask |= AFS_VOL_VTM_RO;
286 if (tmp & AFS_VLF_BACKEXISTS) 117 if (tmp & AFS_VLF_BACKEXISTS)
287 entry->vidmask |= AFS_VOL_VTM_BAK; 118 entry->vidmask |= AFS_VOL_VTM_BAK;
288
289 ret = -ENOMEDIUM;
290 if (!entry->vidmask) 119 if (!entry->vidmask)
291 goto abort; 120 return -EBADMSG;
292
293 /* success */
294 entry->rtime = get_seconds();
295 ret = 0;
296
297 out_unwait:
298 set_current_state(TASK_RUNNING);
299 remove_wait_queue(&call->waitq, &myself);
300 rxrpc_put_call(call);
301 out_put_conn:
302 rxrpc_put_connection(conn);
303 out:
304 _leave(" = %d", ret);
305 return ret;
306
307 abort:
308 set_current_state(TASK_UNINTERRUPTIBLE);
309 rxrpc_call_abort(call, ret);
310 schedule();
311 goto out_unwait;
312} /* end afs_rxvl_get_entry_by_name() */
313
314/*****************************************************************************/
315/*
316 * look up a volume location database entry by ID
317 */
318int afs_rxvl_get_entry_by_id(struct afs_server *server,
319 afs_volid_t volid,
320 afs_voltype_t voltype,
321 struct afs_cache_vlocation *entry)
322{
323 DECLARE_WAITQUEUE(myself, current);
324
325 struct rxrpc_connection *conn;
326 struct rxrpc_call *call;
327 struct kvec piov[1];
328 unsigned tmp;
329 size_t sent;
330 int ret, loop;
331 __be32 *bp, param[3];
332
333 _enter(",%x,%d,", volid, voltype);
334
335 memset(entry, 0, sizeof(*entry));
336
337 /* get hold of the vlserver connection */
338 ret = afs_server_get_vlconn(server, &conn);
339 if (ret < 0)
340 goto out;
341
342 /* create a call through that connection */
343 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);
344 if (ret < 0) {
345 printk("kAFS: Unable to create call: %d\n", ret);
346 goto out_put_conn;
347 }
348 call->app_opcode = VLGETENTRYBYID;
349
350 /* we want to get event notifications from the call */
351 add_wait_queue(&call->waitq, &myself);
352
353 /* marshall the parameters */
354 param[0] = htonl(VLGETENTRYBYID);
355 param[1] = htonl(volid);
356 param[2] = htonl(voltype);
357
358 piov[0].iov_len = sizeof(param);
359 piov[0].iov_base = param;
360
361 /* send the parameters to the server */
362 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
363 0, &sent);
364 if (ret < 0)
365 goto abort;
366
367 /* wait for the reply to completely arrive */
368 bp = rxrpc_call_alloc_scratch(call, 384);
369
370 ret = rxrpc_call_read_data(call, bp, 384,
371 RXRPC_CALL_READ_BLOCK |
372 RXRPC_CALL_READ_ALL);
373 if (ret < 0) {
374 if (ret == -ECONNABORTED) {
375 ret = call->app_errno;
376 goto out_unwait;
377 }
378 goto abort;
379 }
380
381 /* unmarshall the reply */
382 for (loop = 0; loop < 64; loop++)
383 entry->name[loop] = ntohl(*bp++);
384 bp++; /* final NUL */
385 121
386 bp++; /* type */ 122 _leave(" = 0 [done]");
387 entry->nservers = ntohl(*bp++); 123 return 0;
388 124}
389 for (loop = 0; loop < 8; loop++)
390 entry->servers[loop].s_addr = *bp++;
391
392 bp += 8; /* partition IDs */
393 125
394 for (loop = 0; loop < 8; loop++) {
395 tmp = ntohl(*bp++);
396 if (tmp & AFS_VLSF_RWVOL)
397 entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
398 if (tmp & AFS_VLSF_ROVOL)
399 entry->srvtmask[loop] |= AFS_VOL_VTM_RO;
400 if (tmp & AFS_VLSF_BACKVOL)
401 entry->srvtmask[loop] |= AFS_VOL_VTM_BAK;
402 }
403
404 entry->vid[0] = ntohl(*bp++);
405 entry->vid[1] = ntohl(*bp++);
406 entry->vid[2] = ntohl(*bp++);
407
408 bp++; /* clone ID */
409
410 tmp = ntohl(*bp++); /* flags */
411 if (tmp & AFS_VLF_RWEXISTS)
412 entry->vidmask |= AFS_VOL_VTM_RW;
413 if (tmp & AFS_VLF_ROEXISTS)
414 entry->vidmask |= AFS_VOL_VTM_RO;
415 if (tmp & AFS_VLF_BACKEXISTS)
416 entry->vidmask |= AFS_VOL_VTM_BAK;
417
418 ret = -ENOMEDIUM;
419 if (!entry->vidmask)
420 goto abort;
421
422#if 0 /* TODO: remove */
423 entry->nservers = 3;
424 entry->servers[0].s_addr = htonl(0xac101249);
425 entry->servers[1].s_addr = htonl(0xac101243);
426 entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/);
427
428 entry->srvtmask[0] = AFS_VOL_VTM_RO;
429 entry->srvtmask[1] = AFS_VOL_VTM_RO;
430 entry->srvtmask[2] = AFS_VOL_VTM_RO | AFS_VOL_VTM_RW;
431#endif
432
433 /* success */
434 entry->rtime = get_seconds();
435 ret = 0;
436
437 out_unwait:
438 set_current_state(TASK_RUNNING);
439 remove_wait_queue(&call->waitq, &myself);
440 rxrpc_put_call(call);
441 out_put_conn:
442 rxrpc_put_connection(conn);
443 out:
444 _leave(" = %d", ret);
445 return ret;
446
447 abort:
448 set_current_state(TASK_UNINTERRUPTIBLE);
449 rxrpc_call_abort(call, ret);
450 schedule();
451 goto out_unwait;
452} /* end afs_rxvl_get_entry_by_id() */
453
454/*****************************************************************************/
455/* 126/*
456 * look up a volume location database entry by ID asynchronously 127 * VL.GetEntryByName operation type
457 */ 128 */
458int afs_rxvl_get_entry_by_id_async(struct afs_async_op *op, 129static const struct afs_call_type afs_RXVLGetEntryByName = {
459 afs_volid_t volid, 130 .name = "VL.GetEntryByName",
460 afs_voltype_t voltype) 131 .deliver = afs_deliver_vl_get_entry_by_xxx,
461{ 132 .abort_to_error = afs_vl_abort_to_error,
462 struct rxrpc_connection *conn; 133 .destructor = afs_flat_call_destructor,
463 struct rxrpc_call *call; 134};
464 struct kvec piov[1];
465 size_t sent;
466 int ret;
467 __be32 param[3];
468
469 _enter(",%x,%d,", volid, voltype);
470
471 /* get hold of the vlserver connection */
472 ret = afs_server_get_vlconn(op->server, &conn);
473 if (ret < 0) {
474 _leave(" = %d", ret);
475 return ret;
476 }
477
478 /* create a call through that connection */
479 ret = rxrpc_create_call(conn,
480 afs_rxvl_get_entry_by_id_attn,
481 afs_rxvl_get_entry_by_id_error,
482 afs_rxvl_aemap,
483 &op->call);
484 rxrpc_put_connection(conn);
485
486 if (ret < 0) {
487 printk("kAFS: Unable to create call: %d\n", ret);
488 _leave(" = %d", ret);
489 return ret;
490 }
491 135
492 op->call->app_opcode = VLGETENTRYBYID; 136/*
493 op->call->app_user = op; 137 * VL.GetEntryById operation type
494 138 */
495 call = op->call; 139static const struct afs_call_type afs_RXVLGetEntryById = {
496 rxrpc_get_call(call); 140 .name = "VL.GetEntryById",
497 141 .deliver = afs_deliver_vl_get_entry_by_xxx,
498 /* send event notifications from the call to kafsasyncd */ 142 .abort_to_error = afs_vl_abort_to_error,
499 afs_kafsasyncd_begin_op(op); 143 .destructor = afs_flat_call_destructor,
500 144};
501 /* marshall the parameters */
502 param[0] = htonl(VLGETENTRYBYID);
503 param[1] = htonl(volid);
504 param[2] = htonl(voltype);
505
506 piov[0].iov_len = sizeof(param);
507 piov[0].iov_base = param;
508
509 /* allocate result read buffer in scratch space */
510 call->app_scr_ptr = rxrpc_call_alloc_scratch(op->call, 384);
511
512 /* send the parameters to the server */
513 ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS,
514 0, &sent);
515 if (ret < 0) {
516 rxrpc_call_abort(call, ret); /* handle from kafsasyncd */
517 ret = 0;
518 goto out;
519 }
520
521 /* wait for the reply to completely arrive */
522 ret = rxrpc_call_read_data(call, call->app_scr_ptr, 384, 0);
523 switch (ret) {
524 case 0:
525 case -EAGAIN:
526 case -ECONNABORTED:
527 ret = 0;
528 break; /* all handled by kafsasyncd */
529
530 default:
531 rxrpc_call_abort(call, ret); /* make kafsasyncd handle it */
532 ret = 0;
533 break;
534 }
535
536 out:
537 rxrpc_put_call(call);
538 _leave(" = %d", ret);
539 return ret;
540
541} /* end afs_rxvl_get_entry_by_id_async() */
542 145
543/*****************************************************************************/
544/* 146/*
545 * attend to the asynchronous get VLDB entry by ID 147 * dispatch a get volume entry by name operation
546 */ 148 */
547int afs_rxvl_get_entry_by_id_async2(struct afs_async_op *op, 149int afs_vl_get_entry_by_name(struct in_addr *addr,
548 struct afs_cache_vlocation *entry) 150 struct key *key,
151 const char *volname,
152 struct afs_cache_vlocation *entry,
153 const struct afs_wait_mode *wait_mode)
549{ 154{
155 struct afs_call *call;
156 size_t volnamesz, reqsz, padsz;
550 __be32 *bp; 157 __be32 *bp;
551 __u32 tmp;
552 int loop, ret;
553
554 _enter("{op=%p cst=%u}", op, op->call->app_call_state);
555
556 memset(entry, 0, sizeof(*entry));
557
558 if (op->call->app_call_state == RXRPC_CSTATE_COMPLETE) {
559 /* operation finished */
560 afs_kafsasyncd_terminate_op(op);
561
562 bp = op->call->app_scr_ptr;
563
564 /* unmarshall the reply */
565 for (loop = 0; loop < 64; loop++)
566 entry->name[loop] = ntohl(*bp++);
567 bp++; /* final NUL */
568
569 bp++; /* type */
570 entry->nservers = ntohl(*bp++);
571
572 for (loop = 0; loop < 8; loop++)
573 entry->servers[loop].s_addr = *bp++;
574
575 bp += 8; /* partition IDs */
576
577 for (loop = 0; loop < 8; loop++) {
578 tmp = ntohl(*bp++);
579 if (tmp & AFS_VLSF_RWVOL)
580 entry->srvtmask[loop] |= AFS_VOL_VTM_RW;
581 if (tmp & AFS_VLSF_ROVOL)
582 entry->srvtmask[loop] |= AFS_VOL_VTM_RO;
583 if (tmp & AFS_VLSF_BACKVOL)
584 entry->srvtmask[loop] |= AFS_VOL_VTM_BAK;
585 }
586
587 entry->vid[0] = ntohl(*bp++);
588 entry->vid[1] = ntohl(*bp++);
589 entry->vid[2] = ntohl(*bp++);
590
591 bp++; /* clone ID */
592
593 tmp = ntohl(*bp++); /* flags */
594 if (tmp & AFS_VLF_RWEXISTS)
595 entry->vidmask |= AFS_VOL_VTM_RW;
596 if (tmp & AFS_VLF_ROEXISTS)
597 entry->vidmask |= AFS_VOL_VTM_RO;
598 if (tmp & AFS_VLF_BACKEXISTS)
599 entry->vidmask |= AFS_VOL_VTM_BAK;
600
601 ret = -ENOMEDIUM;
602 if (!entry->vidmask) {
603 rxrpc_call_abort(op->call, ret);
604 goto done;
605 }
606
607#if 0 /* TODO: remove */
608 entry->nservers = 3;
609 entry->servers[0].s_addr = htonl(0xac101249);
610 entry->servers[1].s_addr = htonl(0xac101243);
611 entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/);
612
613 entry->srvtmask[0] = AFS_VOL_VTM_RO;
614 entry->srvtmask[1] = AFS_VOL_VTM_RO;
615 entry->srvtmask[2] = AFS_VOL_VTM_RO | AFS_VOL_VTM_RW;
616#endif
617
618 /* success */
619 entry->rtime = get_seconds();
620 ret = 0;
621 goto done;
622 }
623 158
624 if (op->call->app_call_state == RXRPC_CSTATE_ERROR) { 159 _enter("");
625 /* operation error */
626 ret = op->call->app_errno;
627 goto done;
628 }
629 160
630 _leave(" = -EAGAIN"); 161 volnamesz = strlen(volname);
631 return -EAGAIN; 162 padsz = (4 - (volnamesz & 3)) & 3;
163 reqsz = 8 + volnamesz + padsz;
632 164
633 done: 165 call = afs_alloc_flat_call(&afs_RXVLGetEntryByName, reqsz, 384);
634 rxrpc_put_call(op->call); 166 if (!call)
635 op->call = NULL; 167 return -ENOMEM;
636 _leave(" = %d", ret);
637 return ret;
638} /* end afs_rxvl_get_entry_by_id_async2() */
639 168
640/*****************************************************************************/ 169 call->key = key;
641/* 170 call->reply = entry;
642 * handle attention events on an async get-entry-by-ID op 171 call->service_id = VL_SERVICE;
643 * - called from krxiod 172 call->port = htons(AFS_VL_PORT);
644 */
645static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call)
646{
647 struct afs_async_op *op = call->app_user;
648
649 _enter("{op=%p cst=%u}", op, call->app_call_state);
650
651 switch (call->app_call_state) {
652 case RXRPC_CSTATE_COMPLETE:
653 afs_kafsasyncd_attend_op(op);
654 break;
655 case RXRPC_CSTATE_CLNT_RCV_REPLY:
656 if (call->app_async_read)
657 break;
658 case RXRPC_CSTATE_CLNT_GOT_REPLY:
659 if (call->app_read_count == 0)
660 break;
661 printk("kAFS: Reply bigger than expected"
662 " {cst=%u asyn=%d mark=%Zu rdy=%Zu pr=%u%s}",
663 call->app_call_state,
664 call->app_async_read,
665 call->app_mark,
666 call->app_ready_qty,
667 call->pkt_rcv_count,
668 call->app_last_rcv ? " last" : "");
669
670 rxrpc_call_abort(call, -EBADMSG);
671 break;
672 default:
673 BUG();
674 }
675 173
676 _leave(""); 174 /* marshall the parameters */
175 bp = call->request;
176 *bp++ = htonl(VLGETENTRYBYNAME);
177 *bp++ = htonl(volnamesz);
178 memcpy(bp, volname, volnamesz);
179 if (padsz > 0)
180 memset((void *) bp + volnamesz, 0, padsz);
677 181
678} /* end afs_rxvl_get_entry_by_id_attn() */ 182 /* initiate the call */
183 return afs_make_call(addr, call, GFP_KERNEL, wait_mode);
184}
679 185
680/*****************************************************************************/
681/* 186/*
682 * handle error events on an async get-entry-by-ID op 187 * dispatch a get volume entry by ID operation
683 * - called from krxiod
684 */ 188 */
685static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call) 189int afs_vl_get_entry_by_id(struct in_addr *addr,
190 struct key *key,
191 afs_volid_t volid,
192 afs_voltype_t voltype,
193 struct afs_cache_vlocation *entry,
194 const struct afs_wait_mode *wait_mode)
686{ 195{
687 struct afs_async_op *op = call->app_user; 196 struct afs_call *call;
197 __be32 *bp;
688 198
689 _enter("{op=%p cst=%u}", op, call->app_call_state); 199 _enter("");
690 200
691 afs_kafsasyncd_attend_op(op); 201 call = afs_alloc_flat_call(&afs_RXVLGetEntryById, 12, 384);
202 if (!call)
203 return -ENOMEM;
692 204
693 _leave(""); 205 call->key = key;
206 call->reply = entry;
207 call->service_id = VL_SERVICE;
208 call->port = htons(AFS_VL_PORT);
694 209
695} /* end afs_rxvl_get_entry_by_id_error() */ 210 /* marshall the parameters */
211 bp = call->request;
212 *bp++ = htonl(VLGETENTRYBYID);
213 *bp++ = htonl(volid);
214 *bp = htonl(voltype);
215
216 /* initiate the call */
217 return afs_make_call(addr, call, GFP_KERNEL, wait_mode);
218}