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