]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* vlclient.c: AFS Volume Location Service client |
2 | * | |
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells ([email protected]) | |
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 | ||
12 | #include <linux/init.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" | |
25 | ||
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 | ||
30 | static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call); | |
31 | static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call); | |
32 | ||
33 | /*****************************************************************************/ | |
34 | /* | |
35 | * map afs VL abort codes to/from Linux error codes | |
36 | * - called with call->lock held | |
37 | */ | |
38 | static void afs_rxvl_aemap(struct rxrpc_call *call) | |
39 | { | |
40 | int err; | |
41 | ||
42 | _enter("{%u,%u,%d}", | |
43 | call->app_err_state, call->app_abort_code, call->app_errno); | |
44 | ||
45 | switch (call->app_err_state) { | |
46 | case RXRPC_ESTATE_LOCAL_ABORT: | |
47 | call->app_abort_code = -call->app_errno; | |
48 | return; | |
49 | ||
50 | case RXRPC_ESTATE_PEER_ABORT: | |
51 | switch (call->app_abort_code) { | |
52 | case AFSVL_IDEXIST: err = -EEXIST; break; | |
53 | case AFSVL_IO: err = -EREMOTEIO; break; | |
54 | case AFSVL_NAMEEXIST: err = -EEXIST; break; | |
55 | case AFSVL_CREATEFAIL: err = -EREMOTEIO; break; | |
56 | case AFSVL_NOENT: err = -ENOMEDIUM; break; | |
57 | case AFSVL_EMPTY: err = -ENOMEDIUM; break; | |
58 | case AFSVL_ENTDELETED: err = -ENOMEDIUM; break; | |
59 | case AFSVL_BADNAME: err = -EINVAL; break; | |
60 | case AFSVL_BADINDEX: err = -EINVAL; break; | |
61 | case AFSVL_BADVOLTYPE: err = -EINVAL; break; | |
62 | case AFSVL_BADSERVER: err = -EINVAL; break; | |
63 | case AFSVL_BADPARTITION: err = -EINVAL; break; | |
64 | case AFSVL_REPSFULL: err = -EFBIG; break; | |
65 | case AFSVL_NOREPSERVER: err = -ENOENT; break; | |
66 | case AFSVL_DUPREPSERVER: err = -EEXIST; break; | |
67 | case AFSVL_RWNOTFOUND: err = -ENOENT; break; | |
68 | case AFSVL_BADREFCOUNT: err = -EINVAL; break; | |
69 | case AFSVL_SIZEEXCEEDED: err = -EINVAL; break; | |
70 | case AFSVL_BADENTRY: err = -EINVAL; break; | |
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: | |
88 | return; | |
89 | } | |
90 | } /* end afs_rxvl_aemap() */ | |
91 | ||
92 | #if 0 | |
93 | /*****************************************************************************/ | |
94 | /* | |
95 | * probe a volume location server to see if it is still alive -- unused | |
96 | */ | |
97 | static int afs_rxvl_probe(struct afs_server *server, int alloc_flags) | |
98 | { | |
99 | struct rxrpc_connection *conn; | |
100 | struct rxrpc_call *call; | |
101 | struct kvec piov[1]; | |
102 | size_t sent; | |
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 | ||
176 | } /* end afs_rxvl_probe() */ | |
177 | #endif | |
178 | ||
179 | /*****************************************************************************/ | |
180 | /* | |
181 | * look up a volume location database entry by name | |
182 | */ | |
183 | int 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 | ||
215 | /* we want to get event notifications from the call */ | |
216 | add_wait_queue(&call->waitq, &myself); | |
217 | ||
218 | /* marshall the parameters */ | |
219 | piov[1].iov_len = volnamesz; | |
220 | piov[1].iov_base = (char *) volname; | |
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 | ||
252 | /* unmarshall the reply */ | |
253 | for (loop = 0; loop < 64; loop++) | |
254 | entry->name[loop] = ntohl(*bp++); | |
255 | bp++; /* final NUL */ | |
256 | ||
257 | bp++; /* type */ | |
258 | entry->nservers = ntohl(*bp++); | |
259 | ||
260 | for (loop = 0; loop < 8; loop++) | |
261 | entry->servers[loop].s_addr = *bp++; | |
262 | ||
263 | bp += 8; /* partition IDs */ | |
264 | ||
265 | for (loop = 0; loop < 8; loop++) { | |
266 | tmp = ntohl(*bp++); | |
267 | if (tmp & AFS_VLSF_RWVOL) | |
268 | entry->srvtmask[loop] |= AFS_VOL_VTM_RW; | |
269 | if (tmp & AFS_VLSF_ROVOL) | |
270 | entry->srvtmask[loop] |= AFS_VOL_VTM_RO; | |
271 | if (tmp & AFS_VLSF_BACKVOL) | |
272 | entry->srvtmask[loop] |= AFS_VOL_VTM_BAK; | |
273 | } | |
274 | ||
275 | entry->vid[0] = ntohl(*bp++); | |
276 | entry->vid[1] = ntohl(*bp++); | |
277 | entry->vid[2] = ntohl(*bp++); | |
278 | ||
279 | bp++; /* clone ID */ | |
280 | ||
281 | tmp = ntohl(*bp++); /* flags */ | |
282 | if (tmp & AFS_VLF_RWEXISTS) | |
283 | entry->vidmask |= AFS_VOL_VTM_RW; | |
284 | if (tmp & AFS_VLF_ROEXISTS) | |
285 | entry->vidmask |= AFS_VOL_VTM_RO; | |
286 | if (tmp & AFS_VLF_BACKEXISTS) | |
287 | entry->vidmask |= AFS_VOL_VTM_BAK; | |
288 | ||
289 | ret = -ENOMEDIUM; | |
290 | if (!entry->vidmask) | |
291 | goto abort; | |
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 | */ | |
318 | int 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 | ||
386 | bp++; /* type */ | |
387 | entry->nservers = ntohl(*bp++); | |
388 | ||
389 | for (loop = 0; loop < 8; loop++) | |
390 | entry->servers[loop].s_addr = *bp++; | |
391 | ||
392 | bp += 8; /* partition IDs */ | |
393 | ||
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 | /* | |
456 | * look up a volume location database entry by ID asynchronously | |
457 | */ | |
458 | int afs_rxvl_get_entry_by_id_async(struct afs_async_op *op, | |
459 | afs_volid_t volid, | |
460 | afs_voltype_t voltype) | |
461 | { | |
462 | struct rxrpc_connection *conn; | |
463 | struct rxrpc_call *call; | |
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 | ||
492 | op->call->app_opcode = VLGETENTRYBYID; | |
493 | op->call->app_user = op; | |
494 | ||
495 | call = op->call; | |
496 | rxrpc_get_call(call); | |
497 | ||
498 | /* send event notifications from the call to kafsasyncd */ | |
499 | afs_kafsasyncd_begin_op(op); | |
500 | ||
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 | ||
543 | /*****************************************************************************/ | |
544 | /* | |
545 | * attend to the asynchronous get VLDB entry by ID | |
546 | */ | |
547 | int afs_rxvl_get_entry_by_id_async2(struct afs_async_op *op, | |
548 | struct afs_cache_vlocation *entry) | |
549 | { | |
550 | __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 | ||
624 | if (op->call->app_call_state == RXRPC_CSTATE_ERROR) { | |
625 | /* operation error */ | |
626 | ret = op->call->app_errno; | |
627 | goto done; | |
628 | } | |
629 | ||
630 | _leave(" = -EAGAIN"); | |
631 | return -EAGAIN; | |
632 | ||
633 | done: | |
634 | rxrpc_put_call(op->call); | |
635 | op->call = NULL; | |
636 | _leave(" = %d", ret); | |
637 | return ret; | |
638 | } /* end afs_rxvl_get_entry_by_id_async2() */ | |
639 | ||
640 | /*****************************************************************************/ | |
641 | /* | |
642 | * handle attention events on an async get-entry-by-ID op | |
643 | * - called from krxiod | |
644 | */ | |
645 | static 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 | ||
676 | _leave(""); | |
677 | ||
678 | } /* end afs_rxvl_get_entry_by_id_attn() */ | |
679 | ||
680 | /*****************************************************************************/ | |
681 | /* | |
682 | * handle error events on an async get-entry-by-ID op | |
683 | * - called from krxiod | |
684 | */ | |
685 | static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call) | |
686 | { | |
687 | struct afs_async_op *op = call->app_user; | |
688 | ||
689 | _enter("{op=%p cst=%u}", op, call->app_call_state); | |
690 | ||
691 | afs_kafsasyncd_attend_op(op); | |
692 | ||
693 | _leave(""); | |
694 | ||
695 | } /* end afs_rxvl_get_entry_by_id_error() */ |