diff options
Diffstat (limited to 'fs/afs/vlclient.c')
-rw-r--r-- | fs/afs/vlclient.c | 709 |
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 | |||
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 | /* | 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 | */ |
37 | static void afs_rxvl_aemap(struct rxrpc_call *call) | 19 | static 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 | */ |
95 | static int afs_rxvl_probe(struct afs_server *server, int alloc_flags) | 60 | static 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 | ||
160 | abort: | 68 | _enter(",,%u", last); |
161 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
162 | rxrpc_call_abort(call, ret); | ||
163 | schedule(); | ||
164 | |||
165 | out_unwait: | ||
166 | set_current_state(TASK_RUNNING); | ||
167 | remove_wait_queue(&call->waitq, &myself); | ||
168 | rxrpc_put_call(call); | ||
169 | out_put_conn: | ||
170 | rxrpc_put_connection(conn); | ||
171 | out: | ||
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; |
179 | int 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 | |||
293 | out_unwait: | ||
294 | set_current_state(TASK_RUNNING); | ||
295 | remove_wait_queue(&call->waitq, &myself); | ||
296 | rxrpc_put_call(call); | ||
297 | out_put_conn: | ||
298 | rxrpc_put_connection(conn); | ||
299 | out: | ||
300 | _leave(" = %d", ret); | ||
301 | return ret; | ||
302 | |||
303 | abort: | ||
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 | */ |
313 | int afs_rxvl_get_entry_by_id(struct afs_server *server, | 129 | static 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 | 138 | static 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 | |||
432 | out_unwait: | ||
433 | set_current_state(TASK_RUNNING); | ||
434 | remove_wait_queue(&call->waitq, &myself); | ||
435 | rxrpc_put_call(call); | ||
436 | out_put_conn: | ||
437 | rxrpc_put_connection(conn); | ||
438 | out: | ||
439 | _leave(" = %d", ret); | ||
440 | return ret; | ||
441 | |||
442 | abort: | ||
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 | */ |
452 | int afs_rxvl_get_entry_by_id_async(struct afs_async_op *op, | 147 | int 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 | |||
530 | out: | ||
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 | */ |
539 | int afs_rxvl_get_entry_by_id_async2(struct afs_async_op *op, | 185 | int 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 | |||
625 | done: | ||
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 | */ | ||
636 | static 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 | */ | ||
674 | static 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 | } |