Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* fsclient.c: AFS File Server client stubs |
2 | * | |
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells (dhowells@redhat.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the License, or (at your option) any later version. | |
10 | */ | |
11 | ||
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 "fsclient.h" | |
19 | #include "cmservice.h" | |
20 | #include "vnode.h" | |
21 | #include "server.h" | |
22 | #include "errors.h" | |
23 | #include "internal.h" | |
24 | ||
25 | #define FSFETCHSTATUS 132 /* AFS Fetch file status */ | |
26 | #define FSFETCHDATA 130 /* AFS Fetch file data */ | |
27 | #define FSGIVEUPCALLBACKS 147 /* AFS Discard callback promises */ | |
28 | #define FSGETVOLUMEINFO 148 /* AFS Get root volume information */ | |
29 | #define FSGETROOTVOLUME 151 /* AFS Get root volume name */ | |
30 | #define FSLOOKUP 161 /* AFS lookup file in directory */ | |
31 | ||
1da177e4 LT |
32 | /* |
33 | * map afs abort codes to/from Linux error codes | |
34 | * - called with call->lock held | |
35 | */ | |
36 | static void afs_rxfs_aemap(struct rxrpc_call *call) | |
37 | { | |
38 | switch (call->app_err_state) { | |
39 | case RXRPC_ESTATE_LOCAL_ABORT: | |
40 | call->app_abort_code = -call->app_errno; | |
41 | break; | |
42 | case RXRPC_ESTATE_PEER_ABORT: | |
43 | call->app_errno = afs_abort_to_error(call->app_abort_code); | |
44 | break; | |
45 | default: | |
46 | break; | |
47 | } | |
ec26815a | 48 | } |
1da177e4 | 49 | |
1da177e4 LT |
50 | /* |
51 | * get the root volume name from a fileserver | |
52 | * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2 | |
53 | */ | |
54 | #if 0 | |
55 | int afs_rxfs_get_root_volume(struct afs_server *server, | |
56 | char *buf, size_t *buflen) | |
57 | { | |
58 | struct rxrpc_connection *conn; | |
59 | struct rxrpc_call *call; | |
60 | struct kvec piov[2]; | |
61 | size_t sent; | |
62 | int ret; | |
63 | u32 param[1]; | |
64 | ||
65 | DECLARE_WAITQUEUE(myself, current); | |
66 | ||
67 | kenter("%p,%p,%u",server, buf, *buflen); | |
68 | ||
69 | /* get hold of the fileserver connection */ | |
70 | ret = afs_server_get_fsconn(server, &conn); | |
71 | if (ret < 0) | |
72 | goto out; | |
73 | ||
74 | /* create a call through that connection */ | |
75 | ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call); | |
76 | if (ret < 0) { | |
77 | printk("kAFS: Unable to create call: %d\n", ret); | |
78 | goto out_put_conn; | |
79 | } | |
80 | call->app_opcode = FSGETROOTVOLUME; | |
81 | ||
82 | /* we want to get event notifications from the call */ | |
83 | add_wait_queue(&call->waitq, &myself); | |
84 | ||
85 | /* marshall the parameters */ | |
86 | param[0] = htonl(FSGETROOTVOLUME); | |
87 | ||
88 | piov[0].iov_len = sizeof(param); | |
89 | piov[0].iov_base = param; | |
90 | ||
91 | /* send the parameters to the server */ | |
92 | ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, | |
93 | 0, &sent); | |
94 | if (ret < 0) | |
95 | goto abort; | |
96 | ||
97 | /* wait for the reply to completely arrive */ | |
98 | for (;;) { | |
99 | set_current_state(TASK_INTERRUPTIBLE); | |
100 | if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY || | |
101 | signal_pending(current)) | |
102 | break; | |
103 | schedule(); | |
104 | } | |
105 | set_current_state(TASK_RUNNING); | |
106 | ||
107 | ret = -EINTR; | |
108 | if (signal_pending(current)) | |
109 | goto abort; | |
110 | ||
111 | switch (call->app_call_state) { | |
112 | case RXRPC_CSTATE_ERROR: | |
113 | ret = call->app_errno; | |
114 | kdebug("Got Error: %d", ret); | |
115 | goto out_unwait; | |
116 | ||
117 | case RXRPC_CSTATE_CLNT_GOT_REPLY: | |
118 | /* read the reply */ | |
119 | kdebug("Got Reply: qty=%d", call->app_ready_qty); | |
120 | ||
121 | ret = -EBADMSG; | |
122 | if (call->app_ready_qty <= 4) | |
123 | goto abort; | |
124 | ||
125 | ret = rxrpc_call_read_data(call, NULL, call->app_ready_qty, 0); | |
126 | if (ret < 0) | |
127 | goto abort; | |
128 | ||
129 | #if 0 | |
130 | /* unmarshall the reply */ | |
131 | bp = buffer; | |
132 | for (loop = 0; loop < 65; loop++) | |
133 | entry->name[loop] = ntohl(*bp++); | |
134 | entry->name[64] = 0; | |
135 | ||
136 | entry->type = ntohl(*bp++); | |
137 | entry->num_servers = ntohl(*bp++); | |
138 | ||
139 | for (loop = 0; loop < 8; loop++) | |
140 | entry->servers[loop].addr.s_addr = *bp++; | |
141 | ||
142 | for (loop = 0; loop < 8; loop++) | |
143 | entry->servers[loop].partition = ntohl(*bp++); | |
144 | ||
145 | for (loop = 0; loop < 8; loop++) | |
146 | entry->servers[loop].flags = ntohl(*bp++); | |
147 | ||
148 | for (loop = 0; loop < 3; loop++) | |
149 | entry->volume_ids[loop] = ntohl(*bp++); | |
150 | ||
151 | entry->clone_id = ntohl(*bp++); | |
152 | entry->flags = ntohl(*bp); | |
153 | #endif | |
154 | ||
155 | /* success */ | |
156 | ret = 0; | |
157 | goto out_unwait; | |
158 | ||
159 | default: | |
160 | BUG(); | |
161 | } | |
162 | ||
ec26815a | 163 | abort: |
1da177e4 LT |
164 | set_current_state(TASK_UNINTERRUPTIBLE); |
165 | rxrpc_call_abort(call, ret); | |
166 | schedule(); | |
ec26815a | 167 | out_unwait: |
1da177e4 LT |
168 | set_current_state(TASK_RUNNING); |
169 | remove_wait_queue(&call->waitq, &myself); | |
170 | rxrpc_put_call(call); | |
ec26815a | 171 | out_put_conn: |
1da177e4 | 172 | afs_server_release_fsconn(server, conn); |
ec26815a | 173 | out: |
1da177e4 LT |
174 | kleave(""); |
175 | return ret; | |
ec26815a | 176 | } |
1da177e4 LT |
177 | #endif |
178 | ||
1da177e4 LT |
179 | /* |
180 | * get information about a volume | |
181 | */ | |
182 | #if 0 | |
183 | int afs_rxfs_get_volume_info(struct afs_server *server, | |
184 | const char *name, | |
185 | struct afs_volume_info *vinfo) | |
186 | { | |
187 | struct rxrpc_connection *conn; | |
188 | struct rxrpc_call *call; | |
189 | struct kvec piov[3]; | |
190 | size_t sent; | |
191 | int ret; | |
192 | u32 param[2], *bp, zero; | |
193 | ||
194 | DECLARE_WAITQUEUE(myself, current); | |
195 | ||
196 | _enter("%p,%s,%p", server, name, vinfo); | |
197 | ||
198 | /* get hold of the fileserver connection */ | |
199 | ret = afs_server_get_fsconn(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_rxfs_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 = FSGETVOLUMEINFO; | |
210 | ||
211 | /* we want to get event notifications from the call */ | |
212 | add_wait_queue(&call->waitq, &myself); | |
213 | ||
214 | /* marshall the parameters */ | |
215 | piov[1].iov_len = strlen(name); | |
216 | piov[1].iov_base = (char *) name; | |
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(FSGETVOLUMEINFO); | |
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, 64); | |
236 | ||
237 | ret = rxrpc_call_read_data(call, bp, 64, | |
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 | ||
248 | /* unmarshall the reply */ | |
249 | vinfo->vid = ntohl(*bp++); | |
250 | vinfo->type = ntohl(*bp++); | |
251 | ||
252 | vinfo->type_vids[0] = ntohl(*bp++); | |
253 | vinfo->type_vids[1] = ntohl(*bp++); | |
254 | vinfo->type_vids[2] = ntohl(*bp++); | |
255 | vinfo->type_vids[3] = ntohl(*bp++); | |
256 | vinfo->type_vids[4] = ntohl(*bp++); | |
257 | ||
258 | vinfo->nservers = ntohl(*bp++); | |
259 | vinfo->servers[0].addr.s_addr = *bp++; | |
260 | vinfo->servers[1].addr.s_addr = *bp++; | |
261 | vinfo->servers[2].addr.s_addr = *bp++; | |
262 | vinfo->servers[3].addr.s_addr = *bp++; | |
263 | vinfo->servers[4].addr.s_addr = *bp++; | |
264 | vinfo->servers[5].addr.s_addr = *bp++; | |
265 | vinfo->servers[6].addr.s_addr = *bp++; | |
266 | vinfo->servers[7].addr.s_addr = *bp++; | |
267 | ||
268 | ret = -EBADMSG; | |
269 | if (vinfo->nservers > 8) | |
270 | goto abort; | |
271 | ||
272 | /* success */ | |
273 | ret = 0; | |
274 | ||
ec26815a | 275 | out_unwait: |
1da177e4 LT |
276 | set_current_state(TASK_RUNNING); |
277 | remove_wait_queue(&call->waitq, &myself); | |
278 | rxrpc_put_call(call); | |
ec26815a | 279 | out_put_conn: |
1da177e4 | 280 | afs_server_release_fsconn(server, conn); |
ec26815a | 281 | out: |
1da177e4 LT |
282 | _leave(""); |
283 | return ret; | |
284 | ||
ec26815a | 285 | abort: |
1da177e4 LT |
286 | set_current_state(TASK_UNINTERRUPTIBLE); |
287 | rxrpc_call_abort(call, ret); | |
288 | schedule(); | |
289 | goto out_unwait; | |
ec26815a | 290 | } |
1da177e4 LT |
291 | #endif |
292 | ||
1da177e4 LT |
293 | /* |
294 | * fetch the status information for a file | |
295 | */ | |
296 | int afs_rxfs_fetch_file_status(struct afs_server *server, | |
297 | struct afs_vnode *vnode, | |
298 | struct afs_volsync *volsync) | |
299 | { | |
300 | struct afs_server_callslot callslot; | |
301 | struct rxrpc_call *call; | |
302 | struct kvec piov[1]; | |
303 | size_t sent; | |
304 | int ret; | |
305 | __be32 *bp; | |
306 | ||
307 | DECLARE_WAITQUEUE(myself, current); | |
308 | ||
309 | _enter("%p,{%u,%u,%u}", | |
310 | server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); | |
311 | ||
312 | /* get hold of the fileserver connection */ | |
313 | ret = afs_server_request_callslot(server, &callslot); | |
314 | if (ret < 0) | |
315 | goto out; | |
316 | ||
317 | /* create a call through that connection */ | |
318 | ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, | |
319 | &call); | |
320 | if (ret < 0) { | |
321 | printk("kAFS: Unable to create call: %d\n", ret); | |
322 | goto out_put_conn; | |
323 | } | |
324 | call->app_opcode = FSFETCHSTATUS; | |
325 | ||
326 | /* we want to get event notifications from the call */ | |
327 | add_wait_queue(&call->waitq, &myself); | |
328 | ||
329 | /* marshall the parameters */ | |
330 | bp = rxrpc_call_alloc_scratch(call, 16); | |
331 | bp[0] = htonl(FSFETCHSTATUS); | |
332 | bp[1] = htonl(vnode->fid.vid); | |
333 | bp[2] = htonl(vnode->fid.vnode); | |
334 | bp[3] = htonl(vnode->fid.unique); | |
335 | ||
336 | piov[0].iov_len = 16; | |
337 | piov[0].iov_base = bp; | |
338 | ||
339 | /* send the parameters to the server */ | |
340 | ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, | |
341 | 0, &sent); | |
342 | if (ret < 0) | |
343 | goto abort; | |
344 | ||
345 | /* wait for the reply to completely arrive */ | |
346 | bp = rxrpc_call_alloc_scratch(call, 120); | |
347 | ||
348 | ret = rxrpc_call_read_data(call, bp, 120, | |
349 | RXRPC_CALL_READ_BLOCK | | |
350 | RXRPC_CALL_READ_ALL); | |
351 | if (ret < 0) { | |
352 | if (ret == -ECONNABORTED) { | |
353 | ret = call->app_errno; | |
354 | goto out_unwait; | |
355 | } | |
356 | goto abort; | |
357 | } | |
358 | ||
359 | /* unmarshall the reply */ | |
360 | vnode->status.if_version = ntohl(*bp++); | |
361 | vnode->status.type = ntohl(*bp++); | |
362 | vnode->status.nlink = ntohl(*bp++); | |
363 | vnode->status.size = ntohl(*bp++); | |
364 | vnode->status.version = ntohl(*bp++); | |
365 | vnode->status.author = ntohl(*bp++); | |
366 | vnode->status.owner = ntohl(*bp++); | |
367 | vnode->status.caller_access = ntohl(*bp++); | |
368 | vnode->status.anon_access = ntohl(*bp++); | |
369 | vnode->status.mode = ntohl(*bp++); | |
370 | vnode->status.parent.vid = vnode->fid.vid; | |
371 | vnode->status.parent.vnode = ntohl(*bp++); | |
372 | vnode->status.parent.unique = ntohl(*bp++); | |
373 | bp++; /* seg size */ | |
374 | vnode->status.mtime_client = ntohl(*bp++); | |
375 | vnode->status.mtime_server = ntohl(*bp++); | |
376 | bp++; /* group */ | |
377 | bp++; /* sync counter */ | |
378 | vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; | |
379 | bp++; /* spare2 */ | |
380 | bp++; /* spare3 */ | |
381 | bp++; /* spare4 */ | |
382 | ||
383 | vnode->cb_version = ntohl(*bp++); | |
384 | vnode->cb_expiry = ntohl(*bp++); | |
385 | vnode->cb_type = ntohl(*bp++); | |
386 | ||
387 | if (volsync) { | |
388 | volsync->creation = ntohl(*bp++); | |
389 | bp++; /* spare2 */ | |
390 | bp++; /* spare3 */ | |
391 | bp++; /* spare4 */ | |
392 | bp++; /* spare5 */ | |
393 | bp++; /* spare6 */ | |
394 | } | |
395 | ||
396 | /* success */ | |
397 | ret = 0; | |
398 | ||
ec26815a | 399 | out_unwait: |
1da177e4 LT |
400 | set_current_state(TASK_RUNNING); |
401 | remove_wait_queue(&call->waitq, &myself); | |
402 | rxrpc_put_call(call); | |
ec26815a | 403 | out_put_conn: |
1da177e4 | 404 | afs_server_release_callslot(server, &callslot); |
ec26815a | 405 | out: |
1da177e4 LT |
406 | _leave(""); |
407 | return ret; | |
408 | ||
ec26815a | 409 | abort: |
1da177e4 LT |
410 | set_current_state(TASK_UNINTERRUPTIBLE); |
411 | rxrpc_call_abort(call, ret); | |
412 | schedule(); | |
413 | goto out_unwait; | |
ec26815a | 414 | } |
1da177e4 | 415 | |
1da177e4 LT |
416 | /* |
417 | * fetch the contents of a file or directory | |
418 | */ | |
419 | int afs_rxfs_fetch_file_data(struct afs_server *server, | |
420 | struct afs_vnode *vnode, | |
421 | struct afs_rxfs_fetch_descriptor *desc, | |
422 | struct afs_volsync *volsync) | |
423 | { | |
424 | struct afs_server_callslot callslot; | |
425 | struct rxrpc_call *call; | |
426 | struct kvec piov[1]; | |
427 | size_t sent; | |
428 | int ret; | |
429 | __be32 *bp; | |
430 | ||
431 | DECLARE_WAITQUEUE(myself, current); | |
432 | ||
433 | _enter("%p,{fid={%u,%u,%u},sz=%Zu,of=%lu}", | |
434 | server, | |
435 | desc->fid.vid, | |
436 | desc->fid.vnode, | |
437 | desc->fid.unique, | |
438 | desc->size, | |
439 | desc->offset); | |
440 | ||
441 | /* get hold of the fileserver connection */ | |
442 | ret = afs_server_request_callslot(server, &callslot); | |
443 | if (ret < 0) | |
444 | goto out; | |
445 | ||
446 | /* create a call through that connection */ | |
447 | ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call); | |
448 | if (ret < 0) { | |
449 | printk("kAFS: Unable to create call: %d\n", ret); | |
450 | goto out_put_conn; | |
451 | } | |
452 | call->app_opcode = FSFETCHDATA; | |
453 | ||
454 | /* we want to get event notifications from the call */ | |
455 | add_wait_queue(&call->waitq, &myself); | |
456 | ||
457 | /* marshall the parameters */ | |
458 | bp = rxrpc_call_alloc_scratch(call, 24); | |
459 | bp[0] = htonl(FSFETCHDATA); | |
460 | bp[1] = htonl(desc->fid.vid); | |
461 | bp[2] = htonl(desc->fid.vnode); | |
462 | bp[3] = htonl(desc->fid.unique); | |
463 | bp[4] = htonl(desc->offset); | |
464 | bp[5] = htonl(desc->size); | |
465 | ||
466 | piov[0].iov_len = 24; | |
467 | piov[0].iov_base = bp; | |
468 | ||
469 | /* send the parameters to the server */ | |
470 | ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, | |
471 | 0, &sent); | |
472 | if (ret < 0) | |
473 | goto abort; | |
474 | ||
475 | /* wait for the data count to arrive */ | |
476 | ret = rxrpc_call_read_data(call, bp, 4, RXRPC_CALL_READ_BLOCK); | |
477 | if (ret < 0) | |
478 | goto read_failed; | |
479 | ||
480 | desc->actual = ntohl(bp[0]); | |
481 | if (desc->actual != desc->size) { | |
482 | ret = -EBADMSG; | |
483 | goto abort; | |
484 | } | |
485 | ||
486 | /* call the app to read the actual data */ | |
487 | rxrpc_call_reset_scratch(call); | |
488 | ||
489 | ret = rxrpc_call_read_data(call, desc->buffer, desc->actual, | |
490 | RXRPC_CALL_READ_BLOCK); | |
491 | if (ret < 0) | |
492 | goto read_failed; | |
493 | ||
494 | /* wait for the rest of the reply to completely arrive */ | |
495 | rxrpc_call_reset_scratch(call); | |
496 | bp = rxrpc_call_alloc_scratch(call, 120); | |
497 | ||
498 | ret = rxrpc_call_read_data(call, bp, 120, | |
499 | RXRPC_CALL_READ_BLOCK | | |
500 | RXRPC_CALL_READ_ALL); | |
501 | if (ret < 0) | |
502 | goto read_failed; | |
503 | ||
504 | /* unmarshall the reply */ | |
505 | vnode->status.if_version = ntohl(*bp++); | |
506 | vnode->status.type = ntohl(*bp++); | |
507 | vnode->status.nlink = ntohl(*bp++); | |
508 | vnode->status.size = ntohl(*bp++); | |
509 | vnode->status.version = ntohl(*bp++); | |
510 | vnode->status.author = ntohl(*bp++); | |
511 | vnode->status.owner = ntohl(*bp++); | |
512 | vnode->status.caller_access = ntohl(*bp++); | |
513 | vnode->status.anon_access = ntohl(*bp++); | |
514 | vnode->status.mode = ntohl(*bp++); | |
515 | vnode->status.parent.vid = desc->fid.vid; | |
516 | vnode->status.parent.vnode = ntohl(*bp++); | |
517 | vnode->status.parent.unique = ntohl(*bp++); | |
518 | bp++; /* seg size */ | |
519 | vnode->status.mtime_client = ntohl(*bp++); | |
520 | vnode->status.mtime_server = ntohl(*bp++); | |
521 | bp++; /* group */ | |
522 | bp++; /* sync counter */ | |
523 | vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; | |
524 | bp++; /* spare2 */ | |
525 | bp++; /* spare3 */ | |
526 | bp++; /* spare4 */ | |
527 | ||
528 | vnode->cb_version = ntohl(*bp++); | |
529 | vnode->cb_expiry = ntohl(*bp++); | |
530 | vnode->cb_type = ntohl(*bp++); | |
531 | ||
532 | if (volsync) { | |
533 | volsync->creation = ntohl(*bp++); | |
534 | bp++; /* spare2 */ | |
535 | bp++; /* spare3 */ | |
536 | bp++; /* spare4 */ | |
537 | bp++; /* spare5 */ | |
538 | bp++; /* spare6 */ | |
539 | } | |
540 | ||
541 | /* success */ | |
542 | ret = 0; | |
543 | ||
ec26815a | 544 | out_unwait: |
1da177e4 LT |
545 | set_current_state(TASK_RUNNING); |
546 | remove_wait_queue(&call->waitq,&myself); | |
547 | rxrpc_put_call(call); | |
ec26815a | 548 | out_put_conn: |
1da177e4 | 549 | afs_server_release_callslot(server, &callslot); |
ec26815a | 550 | out: |
1da177e4 LT |
551 | _leave(" = %d", ret); |
552 | return ret; | |
553 | ||
ec26815a | 554 | read_failed: |
1da177e4 LT |
555 | if (ret == -ECONNABORTED) { |
556 | ret = call->app_errno; | |
557 | goto out_unwait; | |
558 | } | |
559 | ||
ec26815a | 560 | abort: |
1da177e4 LT |
561 | set_current_state(TASK_UNINTERRUPTIBLE); |
562 | rxrpc_call_abort(call, ret); | |
563 | schedule(); | |
564 | goto out_unwait; | |
ec26815a | 565 | } |
1da177e4 | 566 | |
1da177e4 LT |
567 | /* |
568 | * ask the AFS fileserver to discard a callback request on a file | |
569 | */ | |
570 | int afs_rxfs_give_up_callback(struct afs_server *server, | |
571 | struct afs_vnode *vnode) | |
572 | { | |
573 | struct afs_server_callslot callslot; | |
574 | struct rxrpc_call *call; | |
575 | struct kvec piov[1]; | |
576 | size_t sent; | |
577 | int ret; | |
578 | __be32 *bp; | |
579 | ||
580 | DECLARE_WAITQUEUE(myself, current); | |
581 | ||
582 | _enter("%p,{%u,%u,%u}", | |
583 | server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); | |
584 | ||
585 | /* get hold of the fileserver connection */ | |
586 | ret = afs_server_request_callslot(server, &callslot); | |
587 | if (ret < 0) | |
588 | goto out; | |
589 | ||
590 | /* create a call through that connection */ | |
591 | ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call); | |
592 | if (ret < 0) { | |
593 | printk("kAFS: Unable to create call: %d\n", ret); | |
594 | goto out_put_conn; | |
595 | } | |
596 | call->app_opcode = FSGIVEUPCALLBACKS; | |
597 | ||
598 | /* we want to get event notifications from the call */ | |
599 | add_wait_queue(&call->waitq, &myself); | |
600 | ||
601 | /* marshall the parameters */ | |
602 | bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4); | |
603 | ||
604 | piov[0].iov_len = (1 + 4 + 4) * 4; | |
605 | piov[0].iov_base = bp; | |
606 | ||
607 | *bp++ = htonl(FSGIVEUPCALLBACKS); | |
608 | *bp++ = htonl(1); | |
609 | *bp++ = htonl(vnode->fid.vid); | |
610 | *bp++ = htonl(vnode->fid.vnode); | |
611 | *bp++ = htonl(vnode->fid.unique); | |
612 | *bp++ = htonl(1); | |
613 | *bp++ = htonl(vnode->cb_version); | |
614 | *bp++ = htonl(vnode->cb_expiry); | |
615 | *bp++ = htonl(vnode->cb_type); | |
616 | ||
617 | /* send the parameters to the server */ | |
618 | ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, | |
619 | 0, &sent); | |
620 | if (ret < 0) | |
621 | goto abort; | |
622 | ||
623 | /* wait for the reply to completely arrive */ | |
624 | for (;;) { | |
625 | set_current_state(TASK_INTERRUPTIBLE); | |
626 | if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY || | |
627 | signal_pending(current)) | |
628 | break; | |
629 | schedule(); | |
630 | } | |
631 | set_current_state(TASK_RUNNING); | |
632 | ||
633 | ret = -EINTR; | |
634 | if (signal_pending(current)) | |
635 | goto abort; | |
636 | ||
637 | switch (call->app_call_state) { | |
638 | case RXRPC_CSTATE_ERROR: | |
639 | ret = call->app_errno; | |
640 | goto out_unwait; | |
641 | ||
642 | case RXRPC_CSTATE_CLNT_GOT_REPLY: | |
643 | ret = 0; | |
644 | goto out_unwait; | |
645 | ||
646 | default: | |
647 | BUG(); | |
648 | } | |
649 | ||
ec26815a | 650 | out_unwait: |
1da177e4 LT |
651 | set_current_state(TASK_RUNNING); |
652 | remove_wait_queue(&call->waitq, &myself); | |
653 | rxrpc_put_call(call); | |
ec26815a | 654 | out_put_conn: |
1da177e4 | 655 | afs_server_release_callslot(server, &callslot); |
ec26815a | 656 | out: |
1da177e4 LT |
657 | _leave(""); |
658 | return ret; | |
659 | ||
ec26815a | 660 | abort: |
1da177e4 LT |
661 | set_current_state(TASK_UNINTERRUPTIBLE); |
662 | rxrpc_call_abort(call, ret); | |
663 | schedule(); | |
664 | goto out_unwait; | |
ec26815a | 665 | } |
1da177e4 | 666 | |
1da177e4 LT |
667 | /* |
668 | * look a filename up in a directory | |
669 | * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2 | |
670 | */ | |
671 | #if 0 | |
672 | int afs_rxfs_lookup(struct afs_server *server, | |
673 | struct afs_vnode *dir, | |
674 | const char *filename, | |
675 | struct afs_vnode *vnode, | |
676 | struct afs_volsync *volsync) | |
677 | { | |
678 | struct rxrpc_connection *conn; | |
679 | struct rxrpc_call *call; | |
680 | struct kvec piov[3]; | |
681 | size_t sent; | |
682 | int ret; | |
683 | u32 *bp, zero; | |
684 | ||
685 | DECLARE_WAITQUEUE(myself, current); | |
686 | ||
687 | kenter("%p,{%u,%u,%u},%s", | |
688 | server, fid->vid, fid->vnode, fid->unique, filename); | |
689 | ||
690 | /* get hold of the fileserver connection */ | |
691 | ret = afs_server_get_fsconn(server, &conn); | |
692 | if (ret < 0) | |
693 | goto out; | |
694 | ||
695 | /* create a call through that connection */ | |
696 | ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call); | |
697 | if (ret < 0) { | |
698 | printk("kAFS: Unable to create call: %d\n", ret); | |
699 | goto out_put_conn; | |
700 | } | |
701 | call->app_opcode = FSLOOKUP; | |
702 | ||
703 | /* we want to get event notifications from the call */ | |
704 | add_wait_queue(&call->waitq,&myself); | |
705 | ||
706 | /* marshall the parameters */ | |
707 | bp = rxrpc_call_alloc_scratch(call, 20); | |
708 | ||
709 | zero = 0; | |
710 | ||
711 | piov[0].iov_len = 20; | |
712 | piov[0].iov_base = bp; | |
713 | piov[1].iov_len = strlen(filename); | |
714 | piov[1].iov_base = (char *) filename; | |
715 | piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3; | |
716 | piov[2].iov_base = &zero; | |
717 | ||
718 | *bp++ = htonl(FSLOOKUP); | |
719 | *bp++ = htonl(dirfid->vid); | |
720 | *bp++ = htonl(dirfid->vnode); | |
721 | *bp++ = htonl(dirfid->unique); | |
722 | *bp++ = htonl(piov[1].iov_len); | |
723 | ||
724 | /* send the parameters to the server */ | |
725 | ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS, | |
726 | 0, &sent); | |
727 | if (ret < 0) | |
728 | goto abort; | |
729 | ||
730 | /* wait for the reply to completely arrive */ | |
731 | bp = rxrpc_call_alloc_scratch(call, 220); | |
732 | ||
733 | ret = rxrpc_call_read_data(call, bp, 220, | |
734 | RXRPC_CALL_READ_BLOCK | | |
735 | RXRPC_CALL_READ_ALL); | |
736 | if (ret < 0) { | |
737 | if (ret == -ECONNABORTED) { | |
738 | ret = call->app_errno; | |
739 | goto out_unwait; | |
740 | } | |
741 | goto abort; | |
742 | } | |
743 | ||
744 | /* unmarshall the reply */ | |
745 | fid->vid = ntohl(*bp++); | |
746 | fid->vnode = ntohl(*bp++); | |
747 | fid->unique = ntohl(*bp++); | |
748 | ||
749 | vnode->status.if_version = ntohl(*bp++); | |
750 | vnode->status.type = ntohl(*bp++); | |
751 | vnode->status.nlink = ntohl(*bp++); | |
752 | vnode->status.size = ntohl(*bp++); | |
753 | vnode->status.version = ntohl(*bp++); | |
754 | vnode->status.author = ntohl(*bp++); | |
755 | vnode->status.owner = ntohl(*bp++); | |
756 | vnode->status.caller_access = ntohl(*bp++); | |
757 | vnode->status.anon_access = ntohl(*bp++); | |
758 | vnode->status.mode = ntohl(*bp++); | |
759 | vnode->status.parent.vid = dirfid->vid; | |
760 | vnode->status.parent.vnode = ntohl(*bp++); | |
761 | vnode->status.parent.unique = ntohl(*bp++); | |
762 | bp++; /* seg size */ | |
763 | vnode->status.mtime_client = ntohl(*bp++); | |
764 | vnode->status.mtime_server = ntohl(*bp++); | |
765 | bp++; /* group */ | |
766 | bp++; /* sync counter */ | |
767 | vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; | |
768 | bp++; /* spare2 */ | |
769 | bp++; /* spare3 */ | |
770 | bp++; /* spare4 */ | |
771 | ||
772 | dir->status.if_version = ntohl(*bp++); | |
773 | dir->status.type = ntohl(*bp++); | |
774 | dir->status.nlink = ntohl(*bp++); | |
775 | dir->status.size = ntohl(*bp++); | |
776 | dir->status.version = ntohl(*bp++); | |
777 | dir->status.author = ntohl(*bp++); | |
778 | dir->status.owner = ntohl(*bp++); | |
779 | dir->status.caller_access = ntohl(*bp++); | |
780 | dir->status.anon_access = ntohl(*bp++); | |
781 | dir->status.mode = ntohl(*bp++); | |
782 | dir->status.parent.vid = dirfid->vid; | |
783 | dir->status.parent.vnode = ntohl(*bp++); | |
784 | dir->status.parent.unique = ntohl(*bp++); | |
785 | bp++; /* seg size */ | |
786 | dir->status.mtime_client = ntohl(*bp++); | |
787 | dir->status.mtime_server = ntohl(*bp++); | |
788 | bp++; /* group */ | |
789 | bp++; /* sync counter */ | |
790 | dir->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; | |
791 | bp++; /* spare2 */ | |
792 | bp++; /* spare3 */ | |
793 | bp++; /* spare4 */ | |
794 | ||
795 | callback->fid = *fid; | |
796 | callback->version = ntohl(*bp++); | |
797 | callback->expiry = ntohl(*bp++); | |
798 | callback->type = ntohl(*bp++); | |
799 | ||
800 | if (volsync) { | |
801 | volsync->creation = ntohl(*bp++); | |
802 | bp++; /* spare2 */ | |
803 | bp++; /* spare3 */ | |
804 | bp++; /* spare4 */ | |
805 | bp++; /* spare5 */ | |
806 | bp++; /* spare6 */ | |
807 | } | |
808 | ||
809 | /* success */ | |
810 | ret = 0; | |
811 | ||
ec26815a | 812 | out_unwait: |
1da177e4 LT |
813 | set_current_state(TASK_RUNNING); |
814 | remove_wait_queue(&call->waitq, &myself); | |
815 | rxrpc_put_call(call); | |
ec26815a | 816 | out_put_conn: |
1da177e4 | 817 | afs_server_release_fsconn(server, conn); |
ec26815a | 818 | out: |
1da177e4 LT |
819 | kleave(""); |
820 | return ret; | |
821 | ||
ec26815a | 822 | abort: |
1da177e4 LT |
823 | set_current_state(TASK_UNINTERRUPTIBLE); |
824 | rxrpc_call_abort(call, ret); | |
825 | schedule(); | |
826 | goto out_unwait; | |
ec26815a | 827 | } |
1da177e4 | 828 | #endif |