aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/fsclient.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2007-04-26 18:55:03 -0400
committerDavid S. Miller <davem@davemloft.net>2007-04-26 18:55:03 -0400
commit08e0e7c82eeadec6f4871a386b86bf0f0fbcb4eb (patch)
tree1c4f7e91e20e56ff2ec755e988a6ee828b1a21c0 /fs/afs/fsclient.c
parent651350d10f93bed7003c9a66e24cf25e0f8eed3d (diff)
[AF_RXRPC]: Make the in-kernel AFS filesystem use AF_RXRPC.
Make the in-kernel AFS filesystem use AF_RXRPC instead of the old RxRPC code. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs/afs/fsclient.c')
-rw-r--r--fs/afs/fsclient.c1042
1 files changed, 310 insertions, 732 deletions
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index f1c3a186842e..167ca615c2e6 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -1,6 +1,6 @@
1/* fsclient.c: AFS File Server client stubs 1/* AFS File Server client stubs
2 * 2 *
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -11,818 +11,396 @@
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> 14#include <linux/circ_buf.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" 15#include "internal.h"
24 16#include "afs_fs.h"
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 17
32/* 18/*
33 * map afs abort codes to/from Linux error codes 19 * decode an AFSFetchStatus block
34 * - called with call->lock held
35 */ 20 */
36static void afs_rxfs_aemap(struct rxrpc_call *call) 21static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
22 struct afs_vnode *vnode)
37{ 23{
38 switch (call->app_err_state) { 24 const __be32 *bp = *_bp;
39 case RXRPC_ESTATE_LOCAL_ABORT: 25 umode_t mode;
40 call->app_abort_code = -call->app_errno; 26 u64 data_version;
41 break; 27 u32 changed = 0; /* becomes non-zero if ctime-type changes seen */
42 case RXRPC_ESTATE_PEER_ABORT: 28
43 call->app_errno = afs_abort_to_error(call->app_abort_code); 29#define EXTRACT(DST) \
44 break; 30 do { \
45 default: 31 u32 x = ntohl(*bp++); \
46 break; 32 changed |= DST - x; \
33 DST = x; \
34 } while (0)
35
36 vnode->status.if_version = ntohl(*bp++);
37 EXTRACT(vnode->status.type);
38 vnode->status.nlink = ntohl(*bp++);
39 EXTRACT(vnode->status.size);
40 data_version = ntohl(*bp++);
41 EXTRACT(vnode->status.author);
42 EXTRACT(vnode->status.owner);
43 EXTRACT(vnode->status.caller_access); /* call ticket dependent */
44 EXTRACT(vnode->status.anon_access);
45 EXTRACT(vnode->status.mode);
46 vnode->status.parent.vid = vnode->fid.vid;
47 EXTRACT(vnode->status.parent.vnode);
48 EXTRACT(vnode->status.parent.unique);
49 bp++; /* seg size */
50 vnode->status.mtime_client = ntohl(*bp++);
51 vnode->status.mtime_server = ntohl(*bp++);
52 bp++; /* group */
53 bp++; /* sync counter */
54 data_version |= (u64) ntohl(*bp++) << 32;
55 bp++; /* spare2 */
56 bp++; /* spare3 */
57 bp++; /* spare4 */
58 *_bp = bp;
59
60 if (changed) {
61 _debug("vnode changed");
62 set_bit(AFS_VNODE_CHANGED, &vnode->flags);
63 vnode->vfs_inode.i_uid = vnode->status.owner;
64 vnode->vfs_inode.i_size = vnode->status.size;
65 vnode->vfs_inode.i_version = vnode->fid.unique;
66
67 vnode->status.mode &= S_IALLUGO;
68 mode = vnode->vfs_inode.i_mode;
69 mode &= ~S_IALLUGO;
70 mode |= vnode->status.mode;
71 vnode->vfs_inode.i_mode = mode;
72 }
73
74 _debug("vnode time %lx, %lx",
75 vnode->status.mtime_client, vnode->status.mtime_server);
76 vnode->vfs_inode.i_ctime.tv_sec = vnode->status.mtime_server;
77 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
78 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
79
80 if (vnode->status.data_version != data_version) {
81 _debug("vnode modified %llx", data_version);
82 vnode->status.data_version = data_version;
83 set_bit(AFS_VNODE_MODIFIED, &vnode->flags);
84 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
47 } 85 }
48} 86}
49 87
50/* 88/*
51 * get the root volume name from a fileserver 89 * decode an AFSCallBack block
52 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
53 */ 90 */
54#if 0 91static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode)
55int afs_rxfs_get_root_volume(struct afs_server *server,
56 char *buf, size_t *buflen)
57{ 92{
58 struct rxrpc_connection *conn; 93 const __be32 *bp = *_bp;
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 94
155 /* success */ 95 vnode->cb_version = ntohl(*bp++);
156 ret = 0; 96 vnode->cb_expiry = ntohl(*bp++);
157 goto out_unwait; 97 vnode->cb_type = ntohl(*bp++);
158 98 vnode->cb_expires = vnode->cb_expiry + get_seconds();
159 default: 99 *_bp = bp;
160 BUG();
161 }
162
163abort:
164 set_current_state(TASK_UNINTERRUPTIBLE);
165 rxrpc_call_abort(call, ret);
166 schedule();
167out_unwait:
168 set_current_state(TASK_RUNNING);
169 remove_wait_queue(&call->waitq, &myself);
170 rxrpc_put_call(call);
171out_put_conn:
172 afs_server_release_fsconn(server, conn);
173out:
174 kleave("");
175 return ret;
176} 100}
177#endif
178 101
179/* 102/*
180 * get information about a volume 103 * decode an AFSVolSync block
181 */ 104 */
182#if 0 105static void xdr_decode_AFSVolSync(const __be32 **_bp,
183int afs_rxfs_get_volume_info(struct afs_server *server, 106 struct afs_volsync *volsync)
184 const char *name,
185 struct afs_volume_info *vinfo)
186{ 107{
187 struct rxrpc_connection *conn; 108 const __be32 *bp = *_bp;
188 struct rxrpc_call *call;
189 struct kvec piov[3];
190 size_t sent;
191 int ret;
192 u32 param[2], *bp, zero;
193 109
194 DECLARE_WAITQUEUE(myself, current); 110 volsync->creation = ntohl(*bp++);
111 bp++; /* spare2 */
112 bp++; /* spare3 */
113 bp++; /* spare4 */
114 bp++; /* spare5 */
115 bp++; /* spare6 */
116 *_bp = bp;
117}
195 118
196 _enter("%p,%s,%p", server, name, vinfo); 119/*
120 * deliver reply data to an FS.FetchStatus
121 */
122static int afs_deliver_fs_fetch_status(struct afs_call *call,
123 struct sk_buff *skb, bool last)
124{
125 const __be32 *bp;
197 126
198 /* get hold of the fileserver connection */ 127 _enter(",,%u", last);
199 ret = afs_server_get_fsconn(server, &conn);
200 if (ret < 0)
201 goto out;
202 128
203 /* create a call through that connection */ 129 afs_transfer_reply(call, skb);
204 ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call); 130 if (!last)
205 if (ret < 0) { 131 return 0;
206 printk("kAFS: Unable to create call: %d\n", ret);
207 goto out_put_conn;
208 }
209 call->app_opcode = FSGETVOLUMEINFO;
210 132
211 /* we want to get event notifications from the call */ 133 if (call->reply_size != call->reply_max)
212 add_wait_queue(&call->waitq, &myself); 134 return -EBADMSG;
213 135
214 /* marshall the parameters */ 136 /* unmarshall the reply once we've received all of it */
215 piov[1].iov_len = strlen(name); 137 bp = call->buffer;
216 piov[1].iov_base = (char *) name; 138 xdr_decode_AFSFetchStatus(&bp, call->reply);
217 139 xdr_decode_AFSCallBack(&bp, call->reply);
218 zero = 0; 140 if (call->reply2)
219 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3; 141 xdr_decode_AFSVolSync(&bp, call->reply2);
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 142
248 /* unmarshall the reply */ 143 _leave(" = 0 [done]");
249 vinfo->vid = ntohl(*bp++); 144 return 0;
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
275out_unwait:
276 set_current_state(TASK_RUNNING);
277 remove_wait_queue(&call->waitq, &myself);
278 rxrpc_put_call(call);
279out_put_conn:
280 afs_server_release_fsconn(server, conn);
281out:
282 _leave("");
283 return ret;
284
285abort:
286 set_current_state(TASK_UNINTERRUPTIBLE);
287 rxrpc_call_abort(call, ret);
288 schedule();
289 goto out_unwait;
290} 145}
291#endif 146
147/*
148 * FS.FetchStatus operation type
149 */
150static const struct afs_call_type afs_RXFSFetchStatus = {
151 .deliver = afs_deliver_fs_fetch_status,
152 .abort_to_error = afs_abort_to_error,
153 .destructor = afs_flat_call_destructor,
154};
292 155
293/* 156/*
294 * fetch the status information for a file 157 * fetch the status information for a file
295 */ 158 */
296int afs_rxfs_fetch_file_status(struct afs_server *server, 159int afs_fs_fetch_file_status(struct afs_server *server,
297 struct afs_vnode *vnode, 160 struct afs_vnode *vnode,
298 struct afs_volsync *volsync) 161 struct afs_volsync *volsync,
162 const struct afs_wait_mode *wait_mode)
299{ 163{
300 struct afs_server_callslot callslot; 164 struct afs_call *call;
301 struct rxrpc_call *call;
302 struct kvec piov[1];
303 size_t sent;
304 int ret;
305 __be32 *bp; 165 __be32 *bp;
306 166
307 DECLARE_WAITQUEUE(myself, current); 167 _enter("");
308 168
309 _enter("%p,{%u,%u,%u}", 169 call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, 120);
310 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); 170 if (!call)
171 return -ENOMEM;
311 172
312 /* get hold of the fileserver connection */ 173 call->reply = vnode;
313 ret = afs_server_request_callslot(server, &callslot); 174 call->reply2 = volsync;
314 if (ret < 0) 175 call->service_id = FS_SERVICE;
315 goto out; 176 call->port = htons(AFS_FS_PORT);
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 177
329 /* marshall the parameters */ 178 /* marshall the parameters */
330 bp = rxrpc_call_alloc_scratch(call, 16); 179 bp = call->request;
331 bp[0] = htonl(FSFETCHSTATUS); 180 bp[0] = htonl(FSFETCHSTATUS);
332 bp[1] = htonl(vnode->fid.vid); 181 bp[1] = htonl(vnode->fid.vid);
333 bp[2] = htonl(vnode->fid.vnode); 182 bp[2] = htonl(vnode->fid.vnode);
334 bp[3] = htonl(vnode->fid.unique); 183 bp[3] = htonl(vnode->fid.unique);
335 184
336 piov[0].iov_len = 16; 185 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
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
399out_unwait:
400 set_current_state(TASK_RUNNING);
401 remove_wait_queue(&call->waitq, &myself);
402 rxrpc_put_call(call);
403out_put_conn:
404 afs_server_release_callslot(server, &callslot);
405out:
406 _leave("");
407 return ret;
408
409abort:
410 set_current_state(TASK_UNINTERRUPTIBLE);
411 rxrpc_call_abort(call, ret);
412 schedule();
413 goto out_unwait;
414} 186}
415 187
416/* 188/*
417 * fetch the contents of a file or directory 189 * deliver reply data to an FS.FetchData
418 */ 190 */
419int afs_rxfs_fetch_file_data(struct afs_server *server, 191static int afs_deliver_fs_fetch_data(struct afs_call *call,
420 struct afs_vnode *vnode, 192 struct sk_buff *skb, bool last)
421 struct afs_rxfs_fetch_descriptor *desc,
422 struct afs_volsync *volsync)
423{ 193{
424 struct afs_server_callslot callslot; 194 const __be32 *bp;
425 struct rxrpc_call *call; 195 struct page *page;
426 struct kvec piov[1]; 196 void *buffer;
427 size_t sent;
428 int ret; 197 int ret;
429 __be32 *bp;
430 198
431 DECLARE_WAITQUEUE(myself, current); 199 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
432 200
433 _enter("%p,{fid={%u,%u,%u},sz=%Zu,of=%lu}", 201 switch (call->unmarshall) {
434 server, 202 case 0:
435 desc->fid.vid, 203 call->offset = 0;
436 desc->fid.vnode, 204 call->unmarshall++;
437 desc->fid.unique, 205
438 desc->size, 206 /* extract the returned data length */
439 desc->offset); 207 case 1:
440 208 _debug("extract data length");
441 /* get hold of the fileserver connection */ 209 ret = afs_extract_data(call, skb, last, &call->tmp, 4);
442 ret = afs_server_request_callslot(server, &callslot); 210 switch (ret) {
443 if (ret < 0) 211 case 0: break;
444 goto out; 212 case -EAGAIN: return 0;
445 213 default: return ret;
446 /* create a call through that connection */ 214 }
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 215
454 /* we want to get event notifications from the call */ 216 call->count = ntohl(call->tmp);
455 add_wait_queue(&call->waitq, &myself); 217 _debug("DATA length: %u", call->count);
218 if (call->count > PAGE_SIZE)
219 return -EBADMSG;
220 call->offset = 0;
221 call->unmarshall++;
222
223 if (call->count < PAGE_SIZE) {
224 buffer = kmap_atomic(call->reply3, KM_USER0);
225 memset(buffer + PAGE_SIZE - call->count, 0,
226 call->count);
227 kunmap_atomic(buffer, KM_USER0);
228 }
456 229
457 /* marshall the parameters */ 230 /* extract the returned data */
458 bp = rxrpc_call_alloc_scratch(call, 24); 231 case 2:
459 bp[0] = htonl(FSFETCHDATA); 232 _debug("extract data");
460 bp[1] = htonl(desc->fid.vid); 233 page = call->reply3;
461 bp[2] = htonl(desc->fid.vnode); 234 buffer = kmap_atomic(page, KM_USER0);
462 bp[3] = htonl(desc->fid.unique); 235 ret = afs_extract_data(call, skb, last, buffer, call->count);
463 bp[4] = htonl(desc->offset); 236 kunmap_atomic(buffer, KM_USER0);
464 bp[5] = htonl(desc->size); 237 switch (ret) {
465 238 case 0: break;
466 piov[0].iov_len = 24; 239 case -EAGAIN: return 0;
467 piov[0].iov_base = bp; 240 default: return ret;
468 241 }
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 242
486 /* call the app to read the actual data */ 243 call->offset = 0;
487 rxrpc_call_reset_scratch(call); 244 call->unmarshall++;
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 245
528 vnode->cb_version = ntohl(*bp++); 246 /* extract the metadata */
529 vnode->cb_expiry = ntohl(*bp++); 247 case 3:
530 vnode->cb_type = ntohl(*bp++); 248 ret = afs_extract_data(call, skb, last, call->buffer, 120);
531 249 switch (ret) {
532 if (volsync) { 250 case 0: break;
533 volsync->creation = ntohl(*bp++); 251 case -EAGAIN: return 0;
534 bp++; /* spare2 */ 252 default: return ret;
535 bp++; /* spare3 */ 253 }
536 bp++; /* spare4 */ 254
537 bp++; /* spare5 */ 255 bp = call->buffer;
538 bp++; /* spare6 */ 256 xdr_decode_AFSFetchStatus(&bp, call->reply);
539 } 257 xdr_decode_AFSCallBack(&bp, call->reply);
258 if (call->reply2)
259 xdr_decode_AFSVolSync(&bp, call->reply2);
260
261 call->offset = 0;
262 call->unmarshall++;
540 263
541 /* success */ 264 case 4:
542 ret = 0; 265 _debug("trailer");
543 266 if (skb->len != 0)
544out_unwait: 267 return -EBADMSG;
545 set_current_state(TASK_RUNNING); 268 break;
546 remove_wait_queue(&call->waitq,&myself);
547 rxrpc_put_call(call);
548out_put_conn:
549 afs_server_release_callslot(server, &callslot);
550out:
551 _leave(" = %d", ret);
552 return ret;
553
554read_failed:
555 if (ret == -ECONNABORTED) {
556 ret = call->app_errno;
557 goto out_unwait;
558 } 269 }
559 270
560abort: 271 if (!last)
561 set_current_state(TASK_UNINTERRUPTIBLE); 272 return 0;
562 rxrpc_call_abort(call, ret); 273
563 schedule(); 274 _leave(" = 0 [done]");
564 goto out_unwait; 275 return 0;
565} 276}
566 277
567/* 278/*
568 * ask the AFS fileserver to discard a callback request on a file 279 * FS.FetchData operation type
569 */ 280 */
570int afs_rxfs_give_up_callback(struct afs_server *server, 281static const struct afs_call_type afs_RXFSFetchData = {
571 struct afs_vnode *vnode) 282 .deliver = afs_deliver_fs_fetch_data,
283 .abort_to_error = afs_abort_to_error,
284 .destructor = afs_flat_call_destructor,
285};
286
287/*
288 * fetch data from a file
289 */
290int afs_fs_fetch_data(struct afs_server *server,
291 struct afs_vnode *vnode,
292 off_t offset, size_t length,
293 struct page *buffer,
294 struct afs_volsync *volsync,
295 const struct afs_wait_mode *wait_mode)
572{ 296{
573 struct afs_server_callslot callslot; 297 struct afs_call *call;
574 struct rxrpc_call *call;
575 struct kvec piov[1];
576 size_t sent;
577 int ret;
578 __be32 *bp; 298 __be32 *bp;
579 299
580 DECLARE_WAITQUEUE(myself, current); 300 _enter("");
581 301
582 _enter("%p,{%u,%u,%u}", 302 call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, 120);
583 server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); 303 if (!call)
304 return -ENOMEM;
584 305
585 /* get hold of the fileserver connection */ 306 call->reply = vnode;
586 ret = afs_server_request_callslot(server, &callslot); 307 call->reply2 = volsync;
587 if (ret < 0) 308 call->reply3 = buffer;
588 goto out; 309 call->service_id = FS_SERVICE;
589 310 call->port = htons(AFS_FS_PORT);
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 311
601 /* marshall the parameters */ 312 /* marshall the parameters */
602 bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4); 313 bp = call->request;
603 314 bp[0] = htonl(FSFETCHDATA);
604 piov[0].iov_len = (1 + 4 + 4) * 4; 315 bp[1] = htonl(vnode->fid.vid);
605 piov[0].iov_base = bp; 316 bp[2] = htonl(vnode->fid.vnode);
606 317 bp[3] = htonl(vnode->fid.unique);
607 *bp++ = htonl(FSGIVEUPCALLBACKS); 318 bp[4] = htonl(offset);
608 *bp++ = htonl(1); 319 bp[5] = htonl(length);
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 320
642 case RXRPC_CSTATE_CLNT_GOT_REPLY: 321 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
643 ret = 0; 322}
644 goto out_unwait;
645 323
646 default: 324/*
647 BUG(); 325 * deliver reply data to an FS.GiveUpCallBacks
648 } 326 */
327static int afs_deliver_fs_give_up_callbacks(struct afs_call *call,
328 struct sk_buff *skb, bool last)
329{
330 _enter(",{%u},%d", skb->len, last);
649 331
650out_unwait: 332 if (skb->len > 0)
651 set_current_state(TASK_RUNNING); 333 return -EBADMSG; /* shouldn't be any reply data */
652 remove_wait_queue(&call->waitq, &myself); 334 return 0;
653 rxrpc_put_call(call);
654out_put_conn:
655 afs_server_release_callslot(server, &callslot);
656out:
657 _leave("");
658 return ret;
659
660abort:
661 set_current_state(TASK_UNINTERRUPTIBLE);
662 rxrpc_call_abort(call, ret);
663 schedule();
664 goto out_unwait;
665} 335}
666 336
667/* 337/*
668 * look a filename up in a directory 338 * FS.GiveUpCallBacks operation type
669 * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2 339 */
340static const struct afs_call_type afs_RXFSGiveUpCallBacks = {
341 .deliver = afs_deliver_fs_give_up_callbacks,
342 .abort_to_error = afs_abort_to_error,
343 .destructor = afs_flat_call_destructor,
344};
345
346/*
347 * give up a set of callbacks
348 * - the callbacks are held in the server->cb_break ring
670 */ 349 */
671#if 0 350int afs_fs_give_up_callbacks(struct afs_server *server,
672int afs_rxfs_lookup(struct afs_server *server, 351 const struct afs_wait_mode *wait_mode)
673 struct afs_vnode *dir,
674 const char *filename,
675 struct afs_vnode *vnode,
676 struct afs_volsync *volsync)
677{ 352{
678 struct rxrpc_connection *conn; 353 struct afs_call *call;
679 struct rxrpc_call *call; 354 size_t ncallbacks;
680 struct kvec piov[3]; 355 __be32 *bp, *tp;
681 size_t sent; 356 int loop;
682 int ret;
683 u32 *bp, zero;
684 357
685 DECLARE_WAITQUEUE(myself, current); 358 ncallbacks = CIRC_CNT(server->cb_break_head, server->cb_break_tail,
359 ARRAY_SIZE(server->cb_break));
686 360
687 kenter("%p,{%u,%u,%u},%s", 361 _enter("{%zu},", ncallbacks);
688 server, fid->vid, fid->vnode, fid->unique, filename);
689 362
690 /* get hold of the fileserver connection */ 363 if (ncallbacks == 0)
691 ret = afs_server_get_fsconn(server, &conn); 364 return 0;
692 if (ret < 0) 365 if (ncallbacks > AFSCBMAX)
693 goto out; 366 ncallbacks = AFSCBMAX;
694 367
695 /* create a call through that connection */ 368 _debug("break %zu callbacks", ncallbacks);
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 369
703 /* we want to get event notifications from the call */ 370 call = afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks,
704 add_wait_queue(&call->waitq,&myself); 371 12 + ncallbacks * 6 * 4, 0);
372 if (!call)
373 return -ENOMEM;
374
375 call->service_id = FS_SERVICE;
376 call->port = htons(AFS_FS_PORT);
705 377
706 /* marshall the parameters */ 378 /* marshall the parameters */
707 bp = rxrpc_call_alloc_scratch(call, 20); 379 bp = call->request;
708 380 tp = bp + 2 + ncallbacks * 3;
709 zero = 0; 381 *bp++ = htonl(FSGIVEUPCALLBACKS);
710 382 *bp++ = htonl(ncallbacks);
711 piov[0].iov_len = 20; 383 *tp++ = htonl(ncallbacks);
712 piov[0].iov_base = bp; 384
713 piov[1].iov_len = strlen(filename); 385 atomic_sub(ncallbacks, &server->cb_break_n);
714 piov[1].iov_base = (char *) filename; 386 for (loop = ncallbacks; loop > 0; loop--) {
715 piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3; 387 struct afs_callback *cb =
716 piov[2].iov_base = &zero; 388 &server->cb_break[server->cb_break_tail];
717 389
718 *bp++ = htonl(FSLOOKUP); 390 *bp++ = htonl(cb->fid.vid);
719 *bp++ = htonl(dirfid->vid); 391 *bp++ = htonl(cb->fid.vnode);
720 *bp++ = htonl(dirfid->vnode); 392 *bp++ = htonl(cb->fid.unique);
721 *bp++ = htonl(dirfid->unique); 393 *tp++ = htonl(cb->version);
722 *bp++ = htonl(piov[1].iov_len); 394 *tp++ = htonl(cb->expiry);
723 395 *tp++ = htonl(cb->type);
724 /* send the parameters to the server */ 396 smp_mb();
725 ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS, 397 server->cb_break_tail =
726 0, &sent); 398 (server->cb_break_tail + 1) &
727 if (ret < 0) 399 (ARRAY_SIZE(server->cb_break) - 1);
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 } 400 }
743 401
744 /* unmarshall the reply */ 402 ASSERT(ncallbacks > 0);
745 fid->vid = ntohl(*bp++); 403 wake_up_nr(&server->cb_break_waitq, ncallbacks);
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 404
809 /* success */ 405 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
810 ret = 0;
811
812out_unwait:
813 set_current_state(TASK_RUNNING);
814 remove_wait_queue(&call->waitq, &myself);
815 rxrpc_put_call(call);
816out_put_conn:
817 afs_server_release_fsconn(server, conn);
818out:
819 kleave("");
820 return ret;
821
822abort:
823 set_current_state(TASK_UNINTERRUPTIBLE);
824 rxrpc_call_abort(call, ret);
825 schedule();
826 goto out_unwait;
827} 406}
828#endif