diff options
Diffstat (limited to 'fs/afs/fsclient.c')
-rw-r--r-- | fs/afs/fsclient.c | 1042 |
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 | */ |
36 | static void afs_rxfs_aemap(struct rxrpc_call *call) | 21 | static 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 | 91 | static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode) |
55 | int 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 | |||
163 | abort: | ||
164 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
165 | rxrpc_call_abort(call, ret); | ||
166 | schedule(); | ||
167 | out_unwait: | ||
168 | set_current_state(TASK_RUNNING); | ||
169 | remove_wait_queue(&call->waitq, &myself); | ||
170 | rxrpc_put_call(call); | ||
171 | out_put_conn: | ||
172 | afs_server_release_fsconn(server, conn); | ||
173 | out: | ||
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 | 105 | static void xdr_decode_AFSVolSync(const __be32 **_bp, |
183 | int 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 | */ | ||
122 | static 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 | |||
275 | out_unwait: | ||
276 | set_current_state(TASK_RUNNING); | ||
277 | remove_wait_queue(&call->waitq, &myself); | ||
278 | rxrpc_put_call(call); | ||
279 | out_put_conn: | ||
280 | afs_server_release_fsconn(server, conn); | ||
281 | out: | ||
282 | _leave(""); | ||
283 | return ret; | ||
284 | |||
285 | abort: | ||
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 | */ | ||
150 | static 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 | */ |
296 | int afs_rxfs_fetch_file_status(struct afs_server *server, | 159 | int 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 | |||
399 | out_unwait: | ||
400 | set_current_state(TASK_RUNNING); | ||
401 | remove_wait_queue(&call->waitq, &myself); | ||
402 | rxrpc_put_call(call); | ||
403 | out_put_conn: | ||
404 | afs_server_release_callslot(server, &callslot); | ||
405 | out: | ||
406 | _leave(""); | ||
407 | return ret; | ||
408 | |||
409 | abort: | ||
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 | */ |
419 | int afs_rxfs_fetch_file_data(struct afs_server *server, | 191 | static 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) | |
544 | out_unwait: | 267 | return -EBADMSG; |
545 | set_current_state(TASK_RUNNING); | 268 | break; |
546 | remove_wait_queue(&call->waitq,&myself); | ||
547 | rxrpc_put_call(call); | ||
548 | out_put_conn: | ||
549 | afs_server_release_callslot(server, &callslot); | ||
550 | out: | ||
551 | _leave(" = %d", ret); | ||
552 | return ret; | ||
553 | |||
554 | read_failed: | ||
555 | if (ret == -ECONNABORTED) { | ||
556 | ret = call->app_errno; | ||
557 | goto out_unwait; | ||
558 | } | 269 | } |
559 | 270 | ||
560 | abort: | 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 | */ |
570 | int afs_rxfs_give_up_callback(struct afs_server *server, | 281 | static 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 | */ | ||
290 | int 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 | */ |
327 | static 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 | ||
650 | out_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); | ||
654 | out_put_conn: | ||
655 | afs_server_release_callslot(server, &callslot); | ||
656 | out: | ||
657 | _leave(""); | ||
658 | return ret; | ||
659 | |||
660 | abort: | ||
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 | */ |
340 | static 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 | 350 | int afs_fs_give_up_callbacks(struct afs_server *server, |
672 | int 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 | |||
812 | out_unwait: | ||
813 | set_current_state(TASK_RUNNING); | ||
814 | remove_wait_queue(&call->waitq, &myself); | ||
815 | rxrpc_put_call(call); | ||
816 | out_put_conn: | ||
817 | afs_server_release_fsconn(server, conn); | ||
818 | out: | ||
819 | kleave(""); | ||
820 | return ret; | ||
821 | |||
822 | abort: | ||
823 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
824 | rxrpc_call_abort(call, ret); | ||
825 | schedule(); | ||
826 | goto out_unwait; | ||
827 | } | 406 | } |
828 | #endif | ||