diff options
Diffstat (limited to 'fs/afs/fsclient.c')
-rw-r--r-- | fs/afs/fsclient.c | 1528 |
1 files changed, 814 insertions, 714 deletions
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 61bc371532ab..2393d2a08d79 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,827 +11,927 @@ | |||
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" |
16 | #include "afs_fs.h" | ||
24 | 17 | ||
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 | |||
32 | /*****************************************************************************/ | ||
33 | /* | 18 | /* |
34 | * map afs abort codes to/from Linux error codes | 19 | * decode an AFSFid block |
35 | * - called with call->lock held | ||
36 | */ | 20 | */ |
37 | static void afs_rxfs_aemap(struct rxrpc_call *call) | 21 | static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid) |
38 | { | 22 | { |
39 | switch (call->app_err_state) { | 23 | const __be32 *bp = *_bp; |
40 | case RXRPC_ESTATE_LOCAL_ABORT: | 24 | |
41 | call->app_abort_code = -call->app_errno; | 25 | fid->vid = ntohl(*bp++); |
42 | break; | 26 | fid->vnode = ntohl(*bp++); |
43 | case RXRPC_ESTATE_PEER_ABORT: | 27 | fid->unique = ntohl(*bp++); |
44 | call->app_errno = afs_abort_to_error(call->app_abort_code); | 28 | *_bp = bp; |
45 | break; | 29 | } |
46 | default: | ||
47 | break; | ||
48 | } | ||
49 | } /* end afs_rxfs_aemap() */ | ||
50 | 30 | ||
51 | /*****************************************************************************/ | ||
52 | /* | 31 | /* |
53 | * get the root volume name from a fileserver | 32 | * decode an AFSFetchStatus block |
54 | * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2 | ||
55 | */ | 33 | */ |
56 | #if 0 | 34 | static void xdr_decode_AFSFetchStatus(const __be32 **_bp, |
57 | int afs_rxfs_get_root_volume(struct afs_server *server, | 35 | struct afs_file_status *status, |
58 | char *buf, size_t *buflen) | 36 | struct afs_vnode *vnode) |
59 | { | 37 | { |
60 | struct rxrpc_connection *conn; | 38 | const __be32 *bp = *_bp; |
61 | struct rxrpc_call *call; | 39 | umode_t mode; |
62 | struct kvec piov[2]; | 40 | u64 data_version, size; |
63 | size_t sent; | 41 | u32 changed = 0; /* becomes non-zero if ctime-type changes seen */ |
64 | int ret; | 42 | |
65 | u32 param[1]; | 43 | #define EXTRACT(DST) \ |
44 | do { \ | ||
45 | u32 x = ntohl(*bp++); \ | ||
46 | changed |= DST - x; \ | ||
47 | DST = x; \ | ||
48 | } while (0) | ||
49 | |||
50 | status->if_version = ntohl(*bp++); | ||
51 | EXTRACT(status->type); | ||
52 | EXTRACT(status->nlink); | ||
53 | size = ntohl(*bp++); | ||
54 | data_version = ntohl(*bp++); | ||
55 | EXTRACT(status->author); | ||
56 | EXTRACT(status->owner); | ||
57 | EXTRACT(status->caller_access); /* call ticket dependent */ | ||
58 | EXTRACT(status->anon_access); | ||
59 | EXTRACT(status->mode); | ||
60 | EXTRACT(status->parent.vnode); | ||
61 | EXTRACT(status->parent.unique); | ||
62 | bp++; /* seg size */ | ||
63 | status->mtime_client = ntohl(*bp++); | ||
64 | status->mtime_server = ntohl(*bp++); | ||
65 | EXTRACT(status->group); | ||
66 | bp++; /* sync counter */ | ||
67 | data_version |= (u64) ntohl(*bp++) << 32; | ||
68 | bp++; /* lock count */ | ||
69 | size |= (u64) ntohl(*bp++) << 32; | ||
70 | bp++; /* spare 4 */ | ||
71 | *_bp = bp; | ||
72 | |||
73 | if (size != status->size) { | ||
74 | status->size = size; | ||
75 | changed |= true; | ||
76 | } | ||
77 | status->mode &= S_IALLUGO; | ||
78 | |||
79 | _debug("vnode time %lx, %lx", | ||
80 | status->mtime_client, status->mtime_server); | ||
81 | |||
82 | if (vnode) { | ||
83 | status->parent.vid = vnode->fid.vid; | ||
84 | if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { | ||
85 | _debug("vnode changed"); | ||
86 | i_size_write(&vnode->vfs_inode, size); | ||
87 | vnode->vfs_inode.i_uid = status->owner; | ||
88 | vnode->vfs_inode.i_gid = status->group; | ||
89 | vnode->vfs_inode.i_version = vnode->fid.unique; | ||
90 | vnode->vfs_inode.i_nlink = status->nlink; | ||
91 | |||
92 | mode = vnode->vfs_inode.i_mode; | ||
93 | mode &= ~S_IALLUGO; | ||
94 | mode |= status->mode; | ||
95 | barrier(); | ||
96 | vnode->vfs_inode.i_mode = mode; | ||
97 | } | ||
66 | 98 | ||
67 | DECLARE_WAITQUEUE(myself, current); | 99 | vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server; |
100 | vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime; | ||
101 | vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime; | ||
102 | } | ||
68 | 103 | ||
69 | kenter("%p,%p,%u",server, buf, *buflen); | 104 | if (status->data_version != data_version) { |
105 | status->data_version = data_version; | ||
106 | if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { | ||
107 | _debug("vnode modified %llx on {%x:%u}", | ||
108 | (unsigned long long) data_version, | ||
109 | vnode->fid.vid, vnode->fid.vnode); | ||
110 | set_bit(AFS_VNODE_MODIFIED, &vnode->flags); | ||
111 | set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags); | ||
112 | } | ||
113 | } | ||
114 | } | ||
70 | 115 | ||
71 | /* get hold of the fileserver connection */ | 116 | /* |
72 | ret = afs_server_get_fsconn(server, &conn); | 117 | * decode an AFSCallBack block |
73 | if (ret < 0) | 118 | */ |
74 | goto out; | 119 | static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode) |
120 | { | ||
121 | const __be32 *bp = *_bp; | ||
75 | 122 | ||
76 | /* create a call through that connection */ | 123 | vnode->cb_version = ntohl(*bp++); |
77 | ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call); | 124 | vnode->cb_expiry = ntohl(*bp++); |
78 | if (ret < 0) { | 125 | vnode->cb_type = ntohl(*bp++); |
79 | printk("kAFS: Unable to create call: %d\n", ret); | 126 | vnode->cb_expires = vnode->cb_expiry + get_seconds(); |
80 | goto out_put_conn; | 127 | *_bp = bp; |
81 | } | 128 | } |
82 | call->app_opcode = FSGETROOTVOLUME; | ||
83 | 129 | ||
84 | /* we want to get event notifications from the call */ | 130 | static void xdr_decode_AFSCallBack_raw(const __be32 **_bp, |
85 | add_wait_queue(&call->waitq, &myself); | 131 | struct afs_callback *cb) |
132 | { | ||
133 | const __be32 *bp = *_bp; | ||
86 | 134 | ||
87 | /* marshall the parameters */ | 135 | cb->version = ntohl(*bp++); |
88 | param[0] = htonl(FSGETROOTVOLUME); | 136 | cb->expiry = ntohl(*bp++); |
89 | 137 | cb->type = ntohl(*bp++); | |
90 | piov[0].iov_len = sizeof(param); | 138 | *_bp = bp; |
91 | piov[0].iov_base = param; | 139 | } |
92 | |||
93 | /* send the parameters to the server */ | ||
94 | ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, | ||
95 | 0, &sent); | ||
96 | if (ret < 0) | ||
97 | goto abort; | ||
98 | |||
99 | /* wait for the reply to completely arrive */ | ||
100 | for (;;) { | ||
101 | set_current_state(TASK_INTERRUPTIBLE); | ||
102 | if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY || | ||
103 | signal_pending(current)) | ||
104 | break; | ||
105 | schedule(); | ||
106 | } | ||
107 | set_current_state(TASK_RUNNING); | ||
108 | 140 | ||
109 | ret = -EINTR; | 141 | /* |
110 | if (signal_pending(current)) | 142 | * decode an AFSVolSync block |
111 | goto abort; | 143 | */ |
144 | static void xdr_decode_AFSVolSync(const __be32 **_bp, | ||
145 | struct afs_volsync *volsync) | ||
146 | { | ||
147 | const __be32 *bp = *_bp; | ||
112 | 148 | ||
113 | switch (call->app_call_state) { | 149 | volsync->creation = ntohl(*bp++); |
114 | case RXRPC_CSTATE_ERROR: | 150 | bp++; /* spare2 */ |
115 | ret = call->app_errno; | 151 | bp++; /* spare3 */ |
116 | kdebug("Got Error: %d", ret); | 152 | bp++; /* spare4 */ |
117 | goto out_unwait; | 153 | bp++; /* spare5 */ |
154 | bp++; /* spare6 */ | ||
155 | *_bp = bp; | ||
156 | } | ||
118 | 157 | ||
119 | case RXRPC_CSTATE_CLNT_GOT_REPLY: | 158 | /* |
120 | /* read the reply */ | 159 | * deliver reply data to an FS.FetchStatus |
121 | kdebug("Got Reply: qty=%d", call->app_ready_qty); | 160 | */ |
161 | static int afs_deliver_fs_fetch_status(struct afs_call *call, | ||
162 | struct sk_buff *skb, bool last) | ||
163 | { | ||
164 | struct afs_vnode *vnode = call->reply; | ||
165 | const __be32 *bp; | ||
122 | 166 | ||
123 | ret = -EBADMSG; | 167 | _enter(",,%u", last); |
124 | if (call->app_ready_qty <= 4) | ||
125 | goto abort; | ||
126 | 168 | ||
127 | ret = rxrpc_call_read_data(call, NULL, call->app_ready_qty, 0); | 169 | afs_transfer_reply(call, skb); |
128 | if (ret < 0) | 170 | if (!last) |
129 | goto abort; | 171 | return 0; |
130 | 172 | ||
131 | #if 0 | 173 | if (call->reply_size != call->reply_max) |
132 | /* unmarshall the reply */ | 174 | return -EBADMSG; |
133 | bp = buffer; | ||
134 | for (loop = 0; loop < 65; loop++) | ||
135 | entry->name[loop] = ntohl(*bp++); | ||
136 | entry->name[64] = 0; | ||
137 | 175 | ||
138 | entry->type = ntohl(*bp++); | 176 | /* unmarshall the reply once we've received all of it */ |
139 | entry->num_servers = ntohl(*bp++); | 177 | bp = call->buffer; |
178 | xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); | ||
179 | xdr_decode_AFSCallBack(&bp, vnode); | ||
180 | if (call->reply2) | ||
181 | xdr_decode_AFSVolSync(&bp, call->reply2); | ||
140 | 182 | ||
141 | for (loop = 0; loop < 8; loop++) | 183 | _leave(" = 0 [done]"); |
142 | entry->servers[loop].addr.s_addr = *bp++; | 184 | return 0; |
185 | } | ||
143 | 186 | ||
144 | for (loop = 0; loop < 8; loop++) | 187 | /* |
145 | entry->servers[loop].partition = ntohl(*bp++); | 188 | * FS.FetchStatus operation type |
189 | */ | ||
190 | static const struct afs_call_type afs_RXFSFetchStatus = { | ||
191 | .name = "FS.FetchStatus", | ||
192 | .deliver = afs_deliver_fs_fetch_status, | ||
193 | .abort_to_error = afs_abort_to_error, | ||
194 | .destructor = afs_flat_call_destructor, | ||
195 | }; | ||
146 | 196 | ||
147 | for (loop = 0; loop < 8; loop++) | 197 | /* |
148 | entry->servers[loop].flags = ntohl(*bp++); | 198 | * fetch the status information for a file |
199 | */ | ||
200 | int afs_fs_fetch_file_status(struct afs_server *server, | ||
201 | struct key *key, | ||
202 | struct afs_vnode *vnode, | ||
203 | struct afs_volsync *volsync, | ||
204 | const struct afs_wait_mode *wait_mode) | ||
205 | { | ||
206 | struct afs_call *call; | ||
207 | __be32 *bp; | ||
149 | 208 | ||
150 | for (loop = 0; loop < 3; loop++) | 209 | _enter(",%x,{%x:%d},,", |
151 | entry->volume_ids[loop] = ntohl(*bp++); | 210 | key_serial(key), vnode->fid.vid, vnode->fid.vnode); |
152 | 211 | ||
153 | entry->clone_id = ntohl(*bp++); | 212 | call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4); |
154 | entry->flags = ntohl(*bp); | 213 | if (!call) |
155 | #endif | 214 | return -ENOMEM; |
156 | 215 | ||
157 | /* success */ | 216 | call->key = key; |
158 | ret = 0; | 217 | call->reply = vnode; |
159 | goto out_unwait; | 218 | call->reply2 = volsync; |
219 | call->service_id = FS_SERVICE; | ||
220 | call->port = htons(AFS_FS_PORT); | ||
160 | 221 | ||
161 | default: | 222 | /* marshall the parameters */ |
162 | BUG(); | 223 | bp = call->request; |
163 | } | 224 | bp[0] = htonl(FSFETCHSTATUS); |
225 | bp[1] = htonl(vnode->fid.vid); | ||
226 | bp[2] = htonl(vnode->fid.vnode); | ||
227 | bp[3] = htonl(vnode->fid.unique); | ||
228 | |||
229 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); | ||
230 | } | ||
164 | 231 | ||
165 | abort: | ||
166 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
167 | rxrpc_call_abort(call, ret); | ||
168 | schedule(); | ||
169 | out_unwait: | ||
170 | set_current_state(TASK_RUNNING); | ||
171 | remove_wait_queue(&call->waitq, &myself); | ||
172 | rxrpc_put_call(call); | ||
173 | out_put_conn: | ||
174 | afs_server_release_fsconn(server, conn); | ||
175 | out: | ||
176 | kleave(""); | ||
177 | return ret; | ||
178 | } /* end afs_rxfs_get_root_volume() */ | ||
179 | #endif | ||
180 | |||
181 | /*****************************************************************************/ | ||
182 | /* | 232 | /* |
183 | * get information about a volume | 233 | * deliver reply data to an FS.FetchData |
184 | */ | 234 | */ |
185 | #if 0 | 235 | static int afs_deliver_fs_fetch_data(struct afs_call *call, |
186 | int afs_rxfs_get_volume_info(struct afs_server *server, | 236 | struct sk_buff *skb, bool last) |
187 | const char *name, | ||
188 | struct afs_volume_info *vinfo) | ||
189 | { | 237 | { |
190 | struct rxrpc_connection *conn; | 238 | struct afs_vnode *vnode = call->reply; |
191 | struct rxrpc_call *call; | 239 | const __be32 *bp; |
192 | struct kvec piov[3]; | 240 | struct page *page; |
193 | size_t sent; | 241 | void *buffer; |
194 | int ret; | 242 | int ret; |
195 | u32 param[2], *bp, zero; | ||
196 | 243 | ||
197 | DECLARE_WAITQUEUE(myself, current); | 244 | _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); |
245 | |||
246 | switch (call->unmarshall) { | ||
247 | case 0: | ||
248 | call->offset = 0; | ||
249 | call->unmarshall++; | ||
250 | |||
251 | /* extract the returned data length */ | ||
252 | case 1: | ||
253 | _debug("extract data length"); | ||
254 | ret = afs_extract_data(call, skb, last, &call->tmp, 4); | ||
255 | switch (ret) { | ||
256 | case 0: break; | ||
257 | case -EAGAIN: return 0; | ||
258 | default: return ret; | ||
259 | } | ||
198 | 260 | ||
199 | _enter("%p,%s,%p", server, name, vinfo); | 261 | call->count = ntohl(call->tmp); |
262 | _debug("DATA length: %u", call->count); | ||
263 | if (call->count > PAGE_SIZE) | ||
264 | return -EBADMSG; | ||
265 | call->offset = 0; | ||
266 | call->unmarshall++; | ||
267 | |||
268 | if (call->count < PAGE_SIZE) { | ||
269 | buffer = kmap_atomic(call->reply3, KM_USER0); | ||
270 | memset(buffer + PAGE_SIZE - call->count, 0, | ||
271 | call->count); | ||
272 | kunmap_atomic(buffer, KM_USER0); | ||
273 | } | ||
200 | 274 | ||
201 | /* get hold of the fileserver connection */ | 275 | /* extract the returned data */ |
202 | ret = afs_server_get_fsconn(server, &conn); | 276 | case 2: |
203 | if (ret < 0) | 277 | _debug("extract data"); |
204 | goto out; | 278 | page = call->reply3; |
279 | buffer = kmap_atomic(page, KM_USER0); | ||
280 | ret = afs_extract_data(call, skb, last, buffer, call->count); | ||
281 | kunmap_atomic(buffer, KM_USER0); | ||
282 | switch (ret) { | ||
283 | case 0: break; | ||
284 | case -EAGAIN: return 0; | ||
285 | default: return ret; | ||
286 | } | ||
205 | 287 | ||
206 | /* create a call through that connection */ | 288 | call->offset = 0; |
207 | ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call); | 289 | call->unmarshall++; |
208 | if (ret < 0) { | 290 | |
209 | printk("kAFS: Unable to create call: %d\n", ret); | 291 | /* extract the metadata */ |
210 | goto out_put_conn; | 292 | case 3: |
211 | } | 293 | ret = afs_extract_data(call, skb, last, call->buffer, |
212 | call->app_opcode = FSGETVOLUMEINFO; | 294 | (21 + 3 + 6) * 4); |
295 | switch (ret) { | ||
296 | case 0: break; | ||
297 | case -EAGAIN: return 0; | ||
298 | default: return ret; | ||
299 | } | ||
213 | 300 | ||
214 | /* we want to get event notifications from the call */ | 301 | bp = call->buffer; |
215 | add_wait_queue(&call->waitq, &myself); | 302 | xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); |
303 | xdr_decode_AFSCallBack(&bp, vnode); | ||
304 | if (call->reply2) | ||
305 | xdr_decode_AFSVolSync(&bp, call->reply2); | ||
216 | 306 | ||
217 | /* marshall the parameters */ | 307 | call->offset = 0; |
218 | piov[1].iov_len = strlen(name); | 308 | call->unmarshall++; |
219 | piov[1].iov_base = (char *) name; | 309 | |
220 | 310 | case 4: | |
221 | zero = 0; | 311 | _debug("trailer"); |
222 | piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3; | 312 | if (skb->len != 0) |
223 | piov[2].iov_base = &zero; | 313 | return -EBADMSG; |
224 | 314 | break; | |
225 | param[0] = htonl(FSGETVOLUMEINFO); | ||
226 | param[1] = htonl(piov[1].iov_len); | ||
227 | |||
228 | piov[0].iov_len = sizeof(param); | ||
229 | piov[0].iov_base = param; | ||
230 | |||
231 | /* send the parameters to the server */ | ||
232 | ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS, | ||
233 | 0, &sent); | ||
234 | if (ret < 0) | ||
235 | goto abort; | ||
236 | |||
237 | /* wait for the reply to completely arrive */ | ||
238 | bp = rxrpc_call_alloc_scratch(call, 64); | ||
239 | |||
240 | ret = rxrpc_call_read_data(call, bp, 64, | ||
241 | RXRPC_CALL_READ_BLOCK | | ||
242 | RXRPC_CALL_READ_ALL); | ||
243 | if (ret < 0) { | ||
244 | if (ret == -ECONNABORTED) { | ||
245 | ret = call->app_errno; | ||
246 | goto out_unwait; | ||
247 | } | ||
248 | goto abort; | ||
249 | } | 315 | } |
250 | 316 | ||
251 | /* unmarshall the reply */ | 317 | if (!last) |
252 | vinfo->vid = ntohl(*bp++); | 318 | return 0; |
253 | vinfo->type = ntohl(*bp++); | 319 | |
254 | 320 | _leave(" = 0 [done]"); | |
255 | vinfo->type_vids[0] = ntohl(*bp++); | 321 | return 0; |
256 | vinfo->type_vids[1] = ntohl(*bp++); | 322 | } |
257 | vinfo->type_vids[2] = ntohl(*bp++); | 323 | |
258 | vinfo->type_vids[3] = ntohl(*bp++); | ||
259 | vinfo->type_vids[4] = ntohl(*bp++); | ||
260 | |||
261 | vinfo->nservers = ntohl(*bp++); | ||
262 | vinfo->servers[0].addr.s_addr = *bp++; | ||
263 | vinfo->servers[1].addr.s_addr = *bp++; | ||
264 | vinfo->servers[2].addr.s_addr = *bp++; | ||
265 | vinfo->servers[3].addr.s_addr = *bp++; | ||
266 | vinfo->servers[4].addr.s_addr = *bp++; | ||
267 | vinfo->servers[5].addr.s_addr = *bp++; | ||
268 | vinfo->servers[6].addr.s_addr = *bp++; | ||
269 | vinfo->servers[7].addr.s_addr = *bp++; | ||
270 | |||
271 | ret = -EBADMSG; | ||
272 | if (vinfo->nservers > 8) | ||
273 | goto abort; | ||
274 | |||
275 | /* success */ | ||
276 | ret = 0; | ||
277 | |||
278 | out_unwait: | ||
279 | set_current_state(TASK_RUNNING); | ||
280 | remove_wait_queue(&call->waitq, &myself); | ||
281 | rxrpc_put_call(call); | ||
282 | out_put_conn: | ||
283 | afs_server_release_fsconn(server, conn); | ||
284 | out: | ||
285 | _leave(""); | ||
286 | return ret; | ||
287 | |||
288 | abort: | ||
289 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
290 | rxrpc_call_abort(call, ret); | ||
291 | schedule(); | ||
292 | goto out_unwait; | ||
293 | |||
294 | } /* end afs_rxfs_get_volume_info() */ | ||
295 | #endif | ||
296 | |||
297 | /*****************************************************************************/ | ||
298 | /* | 324 | /* |
299 | * fetch the status information for a file | 325 | * FS.FetchData operation type |
326 | */ | ||
327 | static const struct afs_call_type afs_RXFSFetchData = { | ||
328 | .name = "FS.FetchData", | ||
329 | .deliver = afs_deliver_fs_fetch_data, | ||
330 | .abort_to_error = afs_abort_to_error, | ||
331 | .destructor = afs_flat_call_destructor, | ||
332 | }; | ||
333 | |||
334 | /* | ||
335 | * fetch data from a file | ||
300 | */ | 336 | */ |
301 | int afs_rxfs_fetch_file_status(struct afs_server *server, | 337 | int afs_fs_fetch_data(struct afs_server *server, |
302 | struct afs_vnode *vnode, | 338 | struct key *key, |
303 | struct afs_volsync *volsync) | 339 | struct afs_vnode *vnode, |
340 | off_t offset, size_t length, | ||
341 | struct page *buffer, | ||
342 | const struct afs_wait_mode *wait_mode) | ||
304 | { | 343 | { |
305 | struct afs_server_callslot callslot; | 344 | struct afs_call *call; |
306 | struct rxrpc_call *call; | ||
307 | struct kvec piov[1]; | ||
308 | size_t sent; | ||
309 | int ret; | ||
310 | __be32 *bp; | 345 | __be32 *bp; |
311 | 346 | ||
312 | DECLARE_WAITQUEUE(myself, current); | 347 | _enter(""); |
313 | 348 | ||
314 | _enter("%p,{%u,%u,%u}", | 349 | call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, (21 + 3 + 6) * 4); |
315 | server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); | 350 | if (!call) |
351 | return -ENOMEM; | ||
316 | 352 | ||
317 | /* get hold of the fileserver connection */ | 353 | call->key = key; |
318 | ret = afs_server_request_callslot(server, &callslot); | 354 | call->reply = vnode; |
319 | if (ret < 0) | 355 | call->reply2 = NULL; /* volsync */ |
320 | goto out; | 356 | call->reply3 = buffer; |
321 | 357 | call->service_id = FS_SERVICE; | |
322 | /* create a call through that connection */ | 358 | call->port = htons(AFS_FS_PORT); |
323 | ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, | ||
324 | &call); | ||
325 | if (ret < 0) { | ||
326 | printk("kAFS: Unable to create call: %d\n", ret); | ||
327 | goto out_put_conn; | ||
328 | } | ||
329 | call->app_opcode = FSFETCHSTATUS; | ||
330 | |||
331 | /* we want to get event notifications from the call */ | ||
332 | add_wait_queue(&call->waitq, &myself); | ||
333 | 359 | ||
334 | /* marshall the parameters */ | 360 | /* marshall the parameters */ |
335 | bp = rxrpc_call_alloc_scratch(call, 16); | 361 | bp = call->request; |
336 | bp[0] = htonl(FSFETCHSTATUS); | 362 | bp[0] = htonl(FSFETCHDATA); |
337 | bp[1] = htonl(vnode->fid.vid); | 363 | bp[1] = htonl(vnode->fid.vid); |
338 | bp[2] = htonl(vnode->fid.vnode); | 364 | bp[2] = htonl(vnode->fid.vnode); |
339 | bp[3] = htonl(vnode->fid.unique); | 365 | bp[3] = htonl(vnode->fid.unique); |
366 | bp[4] = htonl(offset); | ||
367 | bp[5] = htonl(length); | ||
340 | 368 | ||
341 | piov[0].iov_len = 16; | 369 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); |
342 | piov[0].iov_base = bp; | 370 | } |
343 | |||
344 | /* send the parameters to the server */ | ||
345 | ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, | ||
346 | 0, &sent); | ||
347 | if (ret < 0) | ||
348 | goto abort; | ||
349 | |||
350 | /* wait for the reply to completely arrive */ | ||
351 | bp = rxrpc_call_alloc_scratch(call, 120); | ||
352 | |||
353 | ret = rxrpc_call_read_data(call, bp, 120, | ||
354 | RXRPC_CALL_READ_BLOCK | | ||
355 | RXRPC_CALL_READ_ALL); | ||
356 | if (ret < 0) { | ||
357 | if (ret == -ECONNABORTED) { | ||
358 | ret = call->app_errno; | ||
359 | goto out_unwait; | ||
360 | } | ||
361 | goto abort; | ||
362 | } | ||
363 | 371 | ||
364 | /* unmarshall the reply */ | 372 | /* |
365 | vnode->status.if_version = ntohl(*bp++); | 373 | * deliver reply data to an FS.GiveUpCallBacks |
366 | vnode->status.type = ntohl(*bp++); | 374 | */ |
367 | vnode->status.nlink = ntohl(*bp++); | 375 | static int afs_deliver_fs_give_up_callbacks(struct afs_call *call, |
368 | vnode->status.size = ntohl(*bp++); | 376 | struct sk_buff *skb, bool last) |
369 | vnode->status.version = ntohl(*bp++); | 377 | { |
370 | vnode->status.author = ntohl(*bp++); | 378 | _enter(",{%u},%d", skb->len, last); |
371 | vnode->status.owner = ntohl(*bp++); | ||
372 | vnode->status.caller_access = ntohl(*bp++); | ||
373 | vnode->status.anon_access = ntohl(*bp++); | ||
374 | vnode->status.mode = ntohl(*bp++); | ||
375 | vnode->status.parent.vid = vnode->fid.vid; | ||
376 | vnode->status.parent.vnode = ntohl(*bp++); | ||
377 | vnode->status.parent.unique = ntohl(*bp++); | ||
378 | bp++; /* seg size */ | ||
379 | vnode->status.mtime_client = ntohl(*bp++); | ||
380 | vnode->status.mtime_server = ntohl(*bp++); | ||
381 | bp++; /* group */ | ||
382 | bp++; /* sync counter */ | ||
383 | vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; | ||
384 | bp++; /* spare2 */ | ||
385 | bp++; /* spare3 */ | ||
386 | bp++; /* spare4 */ | ||
387 | 379 | ||
388 | vnode->cb_version = ntohl(*bp++); | 380 | if (skb->len > 0) |
389 | vnode->cb_expiry = ntohl(*bp++); | 381 | return -EBADMSG; /* shouldn't be any reply data */ |
390 | vnode->cb_type = ntohl(*bp++); | 382 | return 0; |
391 | 383 | } | |
392 | if (volsync) { | ||
393 | volsync->creation = ntohl(*bp++); | ||
394 | bp++; /* spare2 */ | ||
395 | bp++; /* spare3 */ | ||
396 | bp++; /* spare4 */ | ||
397 | bp++; /* spare5 */ | ||
398 | bp++; /* spare6 */ | ||
399 | } | ||
400 | 384 | ||
401 | /* success */ | ||
402 | ret = 0; | ||
403 | |||
404 | out_unwait: | ||
405 | set_current_state(TASK_RUNNING); | ||
406 | remove_wait_queue(&call->waitq, &myself); | ||
407 | rxrpc_put_call(call); | ||
408 | out_put_conn: | ||
409 | afs_server_release_callslot(server, &callslot); | ||
410 | out: | ||
411 | _leave(""); | ||
412 | return ret; | ||
413 | |||
414 | abort: | ||
415 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
416 | rxrpc_call_abort(call, ret); | ||
417 | schedule(); | ||
418 | goto out_unwait; | ||
419 | } /* end afs_rxfs_fetch_file_status() */ | ||
420 | |||
421 | /*****************************************************************************/ | ||
422 | /* | 385 | /* |
423 | * fetch the contents of a file or directory | 386 | * FS.GiveUpCallBacks operation type |
424 | */ | 387 | */ |
425 | int afs_rxfs_fetch_file_data(struct afs_server *server, | 388 | static const struct afs_call_type afs_RXFSGiveUpCallBacks = { |
426 | struct afs_vnode *vnode, | 389 | .name = "FS.GiveUpCallBacks", |
427 | struct afs_rxfs_fetch_descriptor *desc, | 390 | .deliver = afs_deliver_fs_give_up_callbacks, |
428 | struct afs_volsync *volsync) | 391 | .abort_to_error = afs_abort_to_error, |
392 | .destructor = afs_flat_call_destructor, | ||
393 | }; | ||
394 | |||
395 | /* | ||
396 | * give up a set of callbacks | ||
397 | * - the callbacks are held in the server->cb_break ring | ||
398 | */ | ||
399 | int afs_fs_give_up_callbacks(struct afs_server *server, | ||
400 | const struct afs_wait_mode *wait_mode) | ||
429 | { | 401 | { |
430 | struct afs_server_callslot callslot; | 402 | struct afs_call *call; |
431 | struct rxrpc_call *call; | 403 | size_t ncallbacks; |
432 | struct kvec piov[1]; | 404 | __be32 *bp, *tp; |
433 | size_t sent; | 405 | int loop; |
434 | int ret; | ||
435 | __be32 *bp; | ||
436 | 406 | ||
437 | DECLARE_WAITQUEUE(myself, current); | 407 | ncallbacks = CIRC_CNT(server->cb_break_head, server->cb_break_tail, |
438 | 408 | ARRAY_SIZE(server->cb_break)); | |
439 | _enter("%p,{fid={%u,%u,%u},sz=%Zu,of=%lu}", | 409 | |
440 | server, | 410 | _enter("{%zu},", ncallbacks); |
441 | desc->fid.vid, | 411 | |
442 | desc->fid.vnode, | 412 | if (ncallbacks == 0) |
443 | desc->fid.unique, | 413 | return 0; |
444 | desc->size, | 414 | if (ncallbacks > AFSCBMAX) |
445 | desc->offset); | 415 | ncallbacks = AFSCBMAX; |
446 | 416 | ||
447 | /* get hold of the fileserver connection */ | 417 | _debug("break %zu callbacks", ncallbacks); |
448 | ret = afs_server_request_callslot(server, &callslot); | ||
449 | if (ret < 0) | ||
450 | goto out; | ||
451 | |||
452 | /* create a call through that connection */ | ||
453 | ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call); | ||
454 | if (ret < 0) { | ||
455 | printk("kAFS: Unable to create call: %d\n", ret); | ||
456 | goto out_put_conn; | ||
457 | } | ||
458 | call->app_opcode = FSFETCHDATA; | ||
459 | 418 | ||
460 | /* we want to get event notifications from the call */ | 419 | call = afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks, |
461 | add_wait_queue(&call->waitq, &myself); | 420 | 12 + ncallbacks * 6 * 4, 0); |
421 | if (!call) | ||
422 | return -ENOMEM; | ||
423 | |||
424 | call->service_id = FS_SERVICE; | ||
425 | call->port = htons(AFS_FS_PORT); | ||
462 | 426 | ||
463 | /* marshall the parameters */ | 427 | /* marshall the parameters */ |
464 | bp = rxrpc_call_alloc_scratch(call, 24); | 428 | bp = call->request; |
465 | bp[0] = htonl(FSFETCHDATA); | 429 | tp = bp + 2 + ncallbacks * 3; |
466 | bp[1] = htonl(desc->fid.vid); | 430 | *bp++ = htonl(FSGIVEUPCALLBACKS); |
467 | bp[2] = htonl(desc->fid.vnode); | 431 | *bp++ = htonl(ncallbacks); |
468 | bp[3] = htonl(desc->fid.unique); | 432 | *tp++ = htonl(ncallbacks); |
469 | bp[4] = htonl(desc->offset); | 433 | |
470 | bp[5] = htonl(desc->size); | 434 | atomic_sub(ncallbacks, &server->cb_break_n); |
471 | 435 | for (loop = ncallbacks; loop > 0; loop--) { | |
472 | piov[0].iov_len = 24; | 436 | struct afs_callback *cb = |
473 | piov[0].iov_base = bp; | 437 | &server->cb_break[server->cb_break_tail]; |
474 | 438 | ||
475 | /* send the parameters to the server */ | 439 | *bp++ = htonl(cb->fid.vid); |
476 | ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, | 440 | *bp++ = htonl(cb->fid.vnode); |
477 | 0, &sent); | 441 | *bp++ = htonl(cb->fid.unique); |
478 | if (ret < 0) | 442 | *tp++ = htonl(cb->version); |
479 | goto abort; | 443 | *tp++ = htonl(cb->expiry); |
480 | 444 | *tp++ = htonl(cb->type); | |
481 | /* wait for the data count to arrive */ | 445 | smp_mb(); |
482 | ret = rxrpc_call_read_data(call, bp, 4, RXRPC_CALL_READ_BLOCK); | 446 | server->cb_break_tail = |
483 | if (ret < 0) | 447 | (server->cb_break_tail + 1) & |
484 | goto read_failed; | 448 | (ARRAY_SIZE(server->cb_break) - 1); |
485 | |||
486 | desc->actual = ntohl(bp[0]); | ||
487 | if (desc->actual != desc->size) { | ||
488 | ret = -EBADMSG; | ||
489 | goto abort; | ||
490 | } | 449 | } |
491 | 450 | ||
492 | /* call the app to read the actual data */ | 451 | ASSERT(ncallbacks > 0); |
493 | rxrpc_call_reset_scratch(call); | 452 | wake_up_nr(&server->cb_break_waitq, ncallbacks); |
494 | |||
495 | ret = rxrpc_call_read_data(call, desc->buffer, desc->actual, | ||
496 | RXRPC_CALL_READ_BLOCK); | ||
497 | if (ret < 0) | ||
498 | goto read_failed; | ||
499 | |||
500 | /* wait for the rest of the reply to completely arrive */ | ||
501 | rxrpc_call_reset_scratch(call); | ||
502 | bp = rxrpc_call_alloc_scratch(call, 120); | ||
503 | |||
504 | ret = rxrpc_call_read_data(call, bp, 120, | ||
505 | RXRPC_CALL_READ_BLOCK | | ||
506 | RXRPC_CALL_READ_ALL); | ||
507 | if (ret < 0) | ||
508 | goto read_failed; | ||
509 | |||
510 | /* unmarshall the reply */ | ||
511 | vnode->status.if_version = ntohl(*bp++); | ||
512 | vnode->status.type = ntohl(*bp++); | ||
513 | vnode->status.nlink = ntohl(*bp++); | ||
514 | vnode->status.size = ntohl(*bp++); | ||
515 | vnode->status.version = ntohl(*bp++); | ||
516 | vnode->status.author = ntohl(*bp++); | ||
517 | vnode->status.owner = ntohl(*bp++); | ||
518 | vnode->status.caller_access = ntohl(*bp++); | ||
519 | vnode->status.anon_access = ntohl(*bp++); | ||
520 | vnode->status.mode = ntohl(*bp++); | ||
521 | vnode->status.parent.vid = desc->fid.vid; | ||
522 | vnode->status.parent.vnode = ntohl(*bp++); | ||
523 | vnode->status.parent.unique = ntohl(*bp++); | ||
524 | bp++; /* seg size */ | ||
525 | vnode->status.mtime_client = ntohl(*bp++); | ||
526 | vnode->status.mtime_server = ntohl(*bp++); | ||
527 | bp++; /* group */ | ||
528 | bp++; /* sync counter */ | ||
529 | vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; | ||
530 | bp++; /* spare2 */ | ||
531 | bp++; /* spare3 */ | ||
532 | bp++; /* spare4 */ | ||
533 | 453 | ||
534 | vnode->cb_version = ntohl(*bp++); | 454 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); |
535 | vnode->cb_expiry = ntohl(*bp++); | 455 | } |
536 | vnode->cb_type = ntohl(*bp++); | ||
537 | |||
538 | if (volsync) { | ||
539 | volsync->creation = ntohl(*bp++); | ||
540 | bp++; /* spare2 */ | ||
541 | bp++; /* spare3 */ | ||
542 | bp++; /* spare4 */ | ||
543 | bp++; /* spare5 */ | ||
544 | bp++; /* spare6 */ | ||
545 | } | ||
546 | 456 | ||
547 | /* success */ | 457 | /* |
548 | ret = 0; | 458 | * deliver reply data to an FS.CreateFile or an FS.MakeDir |
549 | 459 | */ | |
550 | out_unwait: | 460 | static int afs_deliver_fs_create_vnode(struct afs_call *call, |
551 | set_current_state(TASK_RUNNING); | 461 | struct sk_buff *skb, bool last) |
552 | remove_wait_queue(&call->waitq,&myself); | 462 | { |
553 | rxrpc_put_call(call); | 463 | struct afs_vnode *vnode = call->reply; |
554 | out_put_conn: | 464 | const __be32 *bp; |
555 | afs_server_release_callslot(server, &callslot); | 465 | |
556 | out: | 466 | _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); |
557 | _leave(" = %d", ret); | ||
558 | return ret; | ||
559 | |||
560 | read_failed: | ||
561 | if (ret == -ECONNABORTED) { | ||
562 | ret = call->app_errno; | ||
563 | goto out_unwait; | ||
564 | } | ||
565 | 467 | ||
566 | abort: | 468 | afs_transfer_reply(call, skb); |
567 | set_current_state(TASK_UNINTERRUPTIBLE); | 469 | if (!last) |
568 | rxrpc_call_abort(call, ret); | 470 | return 0; |
569 | schedule(); | ||
570 | goto out_unwait; | ||
571 | 471 | ||
572 | } /* end afs_rxfs_fetch_file_data() */ | 472 | if (call->reply_size != call->reply_max) |
473 | return -EBADMSG; | ||
474 | |||
475 | /* unmarshall the reply once we've received all of it */ | ||
476 | bp = call->buffer; | ||
477 | xdr_decode_AFSFid(&bp, call->reply2); | ||
478 | xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL); | ||
479 | xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); | ||
480 | xdr_decode_AFSCallBack_raw(&bp, call->reply4); | ||
481 | /* xdr_decode_AFSVolSync(&bp, call->replyX); */ | ||
482 | |||
483 | _leave(" = 0 [done]"); | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | * FS.CreateFile and FS.MakeDir operation type | ||
489 | */ | ||
490 | static const struct afs_call_type afs_RXFSCreateXXXX = { | ||
491 | .name = "FS.CreateXXXX", | ||
492 | .deliver = afs_deliver_fs_create_vnode, | ||
493 | .abort_to_error = afs_abort_to_error, | ||
494 | .destructor = afs_flat_call_destructor, | ||
495 | }; | ||
573 | 496 | ||
574 | /*****************************************************************************/ | ||
575 | /* | 497 | /* |
576 | * ask the AFS fileserver to discard a callback request on a file | 498 | * create a file or make a directory |
577 | */ | 499 | */ |
578 | int afs_rxfs_give_up_callback(struct afs_server *server, | 500 | int afs_fs_create(struct afs_server *server, |
579 | struct afs_vnode *vnode) | 501 | struct key *key, |
502 | struct afs_vnode *vnode, | ||
503 | const char *name, | ||
504 | umode_t mode, | ||
505 | struct afs_fid *newfid, | ||
506 | struct afs_file_status *newstatus, | ||
507 | struct afs_callback *newcb, | ||
508 | const struct afs_wait_mode *wait_mode) | ||
580 | { | 509 | { |
581 | struct afs_server_callslot callslot; | 510 | struct afs_call *call; |
582 | struct rxrpc_call *call; | 511 | size_t namesz, reqsz, padsz; |
583 | struct kvec piov[1]; | ||
584 | size_t sent; | ||
585 | int ret; | ||
586 | __be32 *bp; | 512 | __be32 *bp; |
587 | 513 | ||
588 | DECLARE_WAITQUEUE(myself, current); | 514 | _enter(""); |
589 | 515 | ||
590 | _enter("%p,{%u,%u,%u}", | 516 | namesz = strlen(name); |
591 | server, vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); | 517 | padsz = (4 - (namesz & 3)) & 3; |
518 | reqsz = (5 * 4) + namesz + padsz + (6 * 4); | ||
592 | 519 | ||
593 | /* get hold of the fileserver connection */ | 520 | call = afs_alloc_flat_call(&afs_RXFSCreateXXXX, reqsz, |
594 | ret = afs_server_request_callslot(server, &callslot); | 521 | (3 + 21 + 21 + 3 + 6) * 4); |
595 | if (ret < 0) | 522 | if (!call) |
596 | goto out; | 523 | return -ENOMEM; |
597 | 524 | ||
598 | /* create a call through that connection */ | 525 | call->key = key; |
599 | ret = rxrpc_create_call(callslot.conn, NULL, NULL, afs_rxfs_aemap, &call); | 526 | call->reply = vnode; |
600 | if (ret < 0) { | 527 | call->reply2 = newfid; |
601 | printk("kAFS: Unable to create call: %d\n", ret); | 528 | call->reply3 = newstatus; |
602 | goto out_put_conn; | 529 | call->reply4 = newcb; |
530 | call->service_id = FS_SERVICE; | ||
531 | call->port = htons(AFS_FS_PORT); | ||
532 | |||
533 | /* marshall the parameters */ | ||
534 | bp = call->request; | ||
535 | *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE); | ||
536 | *bp++ = htonl(vnode->fid.vid); | ||
537 | *bp++ = htonl(vnode->fid.vnode); | ||
538 | *bp++ = htonl(vnode->fid.unique); | ||
539 | *bp++ = htonl(namesz); | ||
540 | memcpy(bp, name, namesz); | ||
541 | bp = (void *) bp + namesz; | ||
542 | if (padsz > 0) { | ||
543 | memset(bp, 0, padsz); | ||
544 | bp = (void *) bp + padsz; | ||
603 | } | 545 | } |
604 | call->app_opcode = FSGIVEUPCALLBACKS; | 546 | *bp++ = htonl(AFS_SET_MODE); |
547 | *bp++ = 0; /* mtime */ | ||
548 | *bp++ = 0; /* owner */ | ||
549 | *bp++ = 0; /* group */ | ||
550 | *bp++ = htonl(mode & S_IALLUGO); /* unix mode */ | ||
551 | *bp++ = 0; /* segment size */ | ||
605 | 552 | ||
606 | /* we want to get event notifications from the call */ | 553 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); |
607 | add_wait_queue(&call->waitq, &myself); | 554 | } |
608 | 555 | ||
609 | /* marshall the parameters */ | 556 | /* |
610 | bp = rxrpc_call_alloc_scratch(call, (1 + 4 + 4) * 4); | 557 | * deliver reply data to an FS.RemoveFile or FS.RemoveDir |
558 | */ | ||
559 | static int afs_deliver_fs_remove(struct afs_call *call, | ||
560 | struct sk_buff *skb, bool last) | ||
561 | { | ||
562 | struct afs_vnode *vnode = call->reply; | ||
563 | const __be32 *bp; | ||
611 | 564 | ||
612 | piov[0].iov_len = (1 + 4 + 4) * 4; | 565 | _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); |
613 | piov[0].iov_base = bp; | ||
614 | 566 | ||
615 | *bp++ = htonl(FSGIVEUPCALLBACKS); | 567 | afs_transfer_reply(call, skb); |
616 | *bp++ = htonl(1); | 568 | if (!last) |
569 | return 0; | ||
570 | |||
571 | if (call->reply_size != call->reply_max) | ||
572 | return -EBADMSG; | ||
573 | |||
574 | /* unmarshall the reply once we've received all of it */ | ||
575 | bp = call->buffer; | ||
576 | xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); | ||
577 | /* xdr_decode_AFSVolSync(&bp, call->replyX); */ | ||
578 | |||
579 | _leave(" = 0 [done]"); | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | /* | ||
584 | * FS.RemoveDir/FS.RemoveFile operation type | ||
585 | */ | ||
586 | static const struct afs_call_type afs_RXFSRemoveXXXX = { | ||
587 | .name = "FS.RemoveXXXX", | ||
588 | .deliver = afs_deliver_fs_remove, | ||
589 | .abort_to_error = afs_abort_to_error, | ||
590 | .destructor = afs_flat_call_destructor, | ||
591 | }; | ||
592 | |||
593 | /* | ||
594 | * remove a file or directory | ||
595 | */ | ||
596 | int afs_fs_remove(struct afs_server *server, | ||
597 | struct key *key, | ||
598 | struct afs_vnode *vnode, | ||
599 | const char *name, | ||
600 | bool isdir, | ||
601 | const struct afs_wait_mode *wait_mode) | ||
602 | { | ||
603 | struct afs_call *call; | ||
604 | size_t namesz, reqsz, padsz; | ||
605 | __be32 *bp; | ||
606 | |||
607 | _enter(""); | ||
608 | |||
609 | namesz = strlen(name); | ||
610 | padsz = (4 - (namesz & 3)) & 3; | ||
611 | reqsz = (5 * 4) + namesz + padsz; | ||
612 | |||
613 | call = afs_alloc_flat_call(&afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4); | ||
614 | if (!call) | ||
615 | return -ENOMEM; | ||
616 | |||
617 | call->key = key; | ||
618 | call->reply = vnode; | ||
619 | call->service_id = FS_SERVICE; | ||
620 | call->port = htons(AFS_FS_PORT); | ||
621 | |||
622 | /* marshall the parameters */ | ||
623 | bp = call->request; | ||
624 | *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE); | ||
617 | *bp++ = htonl(vnode->fid.vid); | 625 | *bp++ = htonl(vnode->fid.vid); |
618 | *bp++ = htonl(vnode->fid.vnode); | 626 | *bp++ = htonl(vnode->fid.vnode); |
619 | *bp++ = htonl(vnode->fid.unique); | 627 | *bp++ = htonl(vnode->fid.unique); |
620 | *bp++ = htonl(1); | 628 | *bp++ = htonl(namesz); |
621 | *bp++ = htonl(vnode->cb_version); | 629 | memcpy(bp, name, namesz); |
622 | *bp++ = htonl(vnode->cb_expiry); | 630 | bp = (void *) bp + namesz; |
623 | *bp++ = htonl(vnode->cb_type); | 631 | if (padsz > 0) { |
624 | 632 | memset(bp, 0, padsz); | |
625 | /* send the parameters to the server */ | 633 | bp = (void *) bp + padsz; |
626 | ret = rxrpc_call_write_data(call, 1, piov, RXRPC_LAST_PACKET, GFP_NOFS, | ||
627 | 0, &sent); | ||
628 | if (ret < 0) | ||
629 | goto abort; | ||
630 | |||
631 | /* wait for the reply to completely arrive */ | ||
632 | for (;;) { | ||
633 | set_current_state(TASK_INTERRUPTIBLE); | ||
634 | if (call->app_call_state != RXRPC_CSTATE_CLNT_RCV_REPLY || | ||
635 | signal_pending(current)) | ||
636 | break; | ||
637 | schedule(); | ||
638 | } | 634 | } |
639 | set_current_state(TASK_RUNNING); | ||
640 | 635 | ||
641 | ret = -EINTR; | 636 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); |
642 | if (signal_pending(current)) | 637 | } |
643 | goto abort; | ||
644 | 638 | ||
645 | switch (call->app_call_state) { | 639 | /* |
646 | case RXRPC_CSTATE_ERROR: | 640 | * deliver reply data to an FS.Link |
647 | ret = call->app_errno; | 641 | */ |
648 | goto out_unwait; | 642 | static int afs_deliver_fs_link(struct afs_call *call, |
643 | struct sk_buff *skb, bool last) | ||
644 | { | ||
645 | struct afs_vnode *dvnode = call->reply, *vnode = call->reply2; | ||
646 | const __be32 *bp; | ||
649 | 647 | ||
650 | case RXRPC_CSTATE_CLNT_GOT_REPLY: | 648 | _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); |
651 | ret = 0; | ||
652 | goto out_unwait; | ||
653 | 649 | ||
654 | default: | 650 | afs_transfer_reply(call, skb); |
655 | BUG(); | 651 | if (!last) |
656 | } | 652 | return 0; |
653 | |||
654 | if (call->reply_size != call->reply_max) | ||
655 | return -EBADMSG; | ||
656 | |||
657 | /* unmarshall the reply once we've received all of it */ | ||
658 | bp = call->buffer; | ||
659 | xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); | ||
660 | xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode); | ||
661 | /* xdr_decode_AFSVolSync(&bp, call->replyX); */ | ||
662 | |||
663 | _leave(" = 0 [done]"); | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | /* | ||
668 | * FS.Link operation type | ||
669 | */ | ||
670 | static const struct afs_call_type afs_RXFSLink = { | ||
671 | .name = "FS.Link", | ||
672 | .deliver = afs_deliver_fs_link, | ||
673 | .abort_to_error = afs_abort_to_error, | ||
674 | .destructor = afs_flat_call_destructor, | ||
675 | }; | ||
657 | 676 | ||
658 | out_unwait: | ||
659 | set_current_state(TASK_RUNNING); | ||
660 | remove_wait_queue(&call->waitq, &myself); | ||
661 | rxrpc_put_call(call); | ||
662 | out_put_conn: | ||
663 | afs_server_release_callslot(server, &callslot); | ||
664 | out: | ||
665 | _leave(""); | ||
666 | return ret; | ||
667 | |||
668 | abort: | ||
669 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
670 | rxrpc_call_abort(call, ret); | ||
671 | schedule(); | ||
672 | goto out_unwait; | ||
673 | } /* end afs_rxfs_give_up_callback() */ | ||
674 | |||
675 | /*****************************************************************************/ | ||
676 | /* | 677 | /* |
677 | * look a filename up in a directory | 678 | * make a hard link |
678 | * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2 | ||
679 | */ | 679 | */ |
680 | #if 0 | 680 | int afs_fs_link(struct afs_server *server, |
681 | int afs_rxfs_lookup(struct afs_server *server, | 681 | struct key *key, |
682 | struct afs_vnode *dir, | 682 | struct afs_vnode *dvnode, |
683 | const char *filename, | 683 | struct afs_vnode *vnode, |
684 | struct afs_vnode *vnode, | 684 | const char *name, |
685 | struct afs_volsync *volsync) | 685 | const struct afs_wait_mode *wait_mode) |
686 | { | 686 | { |
687 | struct rxrpc_connection *conn; | 687 | struct afs_call *call; |
688 | struct rxrpc_call *call; | 688 | size_t namesz, reqsz, padsz; |
689 | struct kvec piov[3]; | 689 | __be32 *bp; |
690 | size_t sent; | ||
691 | int ret; | ||
692 | u32 *bp, zero; | ||
693 | 690 | ||
694 | DECLARE_WAITQUEUE(myself, current); | 691 | _enter(""); |
695 | 692 | ||
696 | kenter("%p,{%u,%u,%u},%s", | 693 | namesz = strlen(name); |
697 | server, fid->vid, fid->vnode, fid->unique, filename); | 694 | padsz = (4 - (namesz & 3)) & 3; |
695 | reqsz = (5 * 4) + namesz + padsz + (3 * 4); | ||
698 | 696 | ||
699 | /* get hold of the fileserver connection */ | 697 | call = afs_alloc_flat_call(&afs_RXFSLink, reqsz, (21 + 21 + 6) * 4); |
700 | ret = afs_server_get_fsconn(server, &conn); | 698 | if (!call) |
701 | if (ret < 0) | 699 | return -ENOMEM; |
702 | goto out; | ||
703 | 700 | ||
704 | /* create a call through that connection */ | 701 | call->key = key; |
705 | ret = rxrpc_create_call(conn, NULL, NULL, afs_rxfs_aemap, &call); | 702 | call->reply = dvnode; |
706 | if (ret < 0) { | 703 | call->reply2 = vnode; |
707 | printk("kAFS: Unable to create call: %d\n", ret); | 704 | call->service_id = FS_SERVICE; |
708 | goto out_put_conn; | 705 | call->port = htons(AFS_FS_PORT); |
706 | |||
707 | /* marshall the parameters */ | ||
708 | bp = call->request; | ||
709 | *bp++ = htonl(FSLINK); | ||
710 | *bp++ = htonl(dvnode->fid.vid); | ||
711 | *bp++ = htonl(dvnode->fid.vnode); | ||
712 | *bp++ = htonl(dvnode->fid.unique); | ||
713 | *bp++ = htonl(namesz); | ||
714 | memcpy(bp, name, namesz); | ||
715 | bp = (void *) bp + namesz; | ||
716 | if (padsz > 0) { | ||
717 | memset(bp, 0, padsz); | ||
718 | bp = (void *) bp + padsz; | ||
709 | } | 719 | } |
710 | call->app_opcode = FSLOOKUP; | 720 | *bp++ = htonl(vnode->fid.vid); |
721 | *bp++ = htonl(vnode->fid.vnode); | ||
722 | *bp++ = htonl(vnode->fid.unique); | ||
723 | |||
724 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); | ||
725 | } | ||
726 | |||
727 | /* | ||
728 | * deliver reply data to an FS.Symlink | ||
729 | */ | ||
730 | static int afs_deliver_fs_symlink(struct afs_call *call, | ||
731 | struct sk_buff *skb, bool last) | ||
732 | { | ||
733 | struct afs_vnode *vnode = call->reply; | ||
734 | const __be32 *bp; | ||
711 | 735 | ||
712 | /* we want to get event notifications from the call */ | 736 | _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); |
713 | add_wait_queue(&call->waitq,&myself); | 737 | |
738 | afs_transfer_reply(call, skb); | ||
739 | if (!last) | ||
740 | return 0; | ||
741 | |||
742 | if (call->reply_size != call->reply_max) | ||
743 | return -EBADMSG; | ||
744 | |||
745 | /* unmarshall the reply once we've received all of it */ | ||
746 | bp = call->buffer; | ||
747 | xdr_decode_AFSFid(&bp, call->reply2); | ||
748 | xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL); | ||
749 | xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode); | ||
750 | /* xdr_decode_AFSVolSync(&bp, call->replyX); */ | ||
751 | |||
752 | _leave(" = 0 [done]"); | ||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | /* | ||
757 | * FS.Symlink operation type | ||
758 | */ | ||
759 | static const struct afs_call_type afs_RXFSSymlink = { | ||
760 | .name = "FS.Symlink", | ||
761 | .deliver = afs_deliver_fs_symlink, | ||
762 | .abort_to_error = afs_abort_to_error, | ||
763 | .destructor = afs_flat_call_destructor, | ||
764 | }; | ||
765 | |||
766 | /* | ||
767 | * create a symbolic link | ||
768 | */ | ||
769 | int afs_fs_symlink(struct afs_server *server, | ||
770 | struct key *key, | ||
771 | struct afs_vnode *vnode, | ||
772 | const char *name, | ||
773 | const char *contents, | ||
774 | struct afs_fid *newfid, | ||
775 | struct afs_file_status *newstatus, | ||
776 | const struct afs_wait_mode *wait_mode) | ||
777 | { | ||
778 | struct afs_call *call; | ||
779 | size_t namesz, reqsz, padsz, c_namesz, c_padsz; | ||
780 | __be32 *bp; | ||
781 | |||
782 | _enter(""); | ||
783 | |||
784 | namesz = strlen(name); | ||
785 | padsz = (4 - (namesz & 3)) & 3; | ||
786 | |||
787 | c_namesz = strlen(contents); | ||
788 | c_padsz = (4 - (c_namesz & 3)) & 3; | ||
789 | |||
790 | reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4); | ||
791 | |||
792 | call = afs_alloc_flat_call(&afs_RXFSSymlink, reqsz, | ||
793 | (3 + 21 + 21 + 6) * 4); | ||
794 | if (!call) | ||
795 | return -ENOMEM; | ||
796 | |||
797 | call->key = key; | ||
798 | call->reply = vnode; | ||
799 | call->reply2 = newfid; | ||
800 | call->reply3 = newstatus; | ||
801 | call->service_id = FS_SERVICE; | ||
802 | call->port = htons(AFS_FS_PORT); | ||
714 | 803 | ||
715 | /* marshall the parameters */ | 804 | /* marshall the parameters */ |
716 | bp = rxrpc_call_alloc_scratch(call, 20); | 805 | bp = call->request; |
717 | 806 | *bp++ = htonl(FSSYMLINK); | |
718 | zero = 0; | 807 | *bp++ = htonl(vnode->fid.vid); |
719 | 808 | *bp++ = htonl(vnode->fid.vnode); | |
720 | piov[0].iov_len = 20; | 809 | *bp++ = htonl(vnode->fid.unique); |
721 | piov[0].iov_base = bp; | 810 | *bp++ = htonl(namesz); |
722 | piov[1].iov_len = strlen(filename); | 811 | memcpy(bp, name, namesz); |
723 | piov[1].iov_base = (char *) filename; | 812 | bp = (void *) bp + namesz; |
724 | piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3; | 813 | if (padsz > 0) { |
725 | piov[2].iov_base = &zero; | 814 | memset(bp, 0, padsz); |
726 | 815 | bp = (void *) bp + padsz; | |
727 | *bp++ = htonl(FSLOOKUP); | ||
728 | *bp++ = htonl(dirfid->vid); | ||
729 | *bp++ = htonl(dirfid->vnode); | ||
730 | *bp++ = htonl(dirfid->unique); | ||
731 | *bp++ = htonl(piov[1].iov_len); | ||
732 | |||
733 | /* send the parameters to the server */ | ||
734 | ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS, | ||
735 | 0, &sent); | ||
736 | if (ret < 0) | ||
737 | goto abort; | ||
738 | |||
739 | /* wait for the reply to completely arrive */ | ||
740 | bp = rxrpc_call_alloc_scratch(call, 220); | ||
741 | |||
742 | ret = rxrpc_call_read_data(call, bp, 220, | ||
743 | RXRPC_CALL_READ_BLOCK | | ||
744 | RXRPC_CALL_READ_ALL); | ||
745 | if (ret < 0) { | ||
746 | if (ret == -ECONNABORTED) { | ||
747 | ret = call->app_errno; | ||
748 | goto out_unwait; | ||
749 | } | ||
750 | goto abort; | ||
751 | } | 816 | } |
817 | *bp++ = htonl(c_namesz); | ||
818 | memcpy(bp, contents, c_namesz); | ||
819 | bp = (void *) bp + c_namesz; | ||
820 | if (c_padsz > 0) { | ||
821 | memset(bp, 0, c_padsz); | ||
822 | bp = (void *) bp + c_padsz; | ||
823 | } | ||
824 | *bp++ = htonl(AFS_SET_MODE); | ||
825 | *bp++ = 0; /* mtime */ | ||
826 | *bp++ = 0; /* owner */ | ||
827 | *bp++ = 0; /* group */ | ||
828 | *bp++ = htonl(S_IRWXUGO); /* unix mode */ | ||
829 | *bp++ = 0; /* segment size */ | ||
752 | 830 | ||
753 | /* unmarshall the reply */ | 831 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); |
754 | fid->vid = ntohl(*bp++); | 832 | } |
755 | fid->vnode = ntohl(*bp++); | ||
756 | fid->unique = ntohl(*bp++); | ||
757 | 833 | ||
758 | vnode->status.if_version = ntohl(*bp++); | 834 | /* |
759 | vnode->status.type = ntohl(*bp++); | 835 | * deliver reply data to an FS.Rename |
760 | vnode->status.nlink = ntohl(*bp++); | 836 | */ |
761 | vnode->status.size = ntohl(*bp++); | 837 | static int afs_deliver_fs_rename(struct afs_call *call, |
762 | vnode->status.version = ntohl(*bp++); | 838 | struct sk_buff *skb, bool last) |
763 | vnode->status.author = ntohl(*bp++); | 839 | { |
764 | vnode->status.owner = ntohl(*bp++); | 840 | struct afs_vnode *orig_dvnode = call->reply, *new_dvnode = call->reply2; |
765 | vnode->status.caller_access = ntohl(*bp++); | 841 | const __be32 *bp; |
766 | vnode->status.anon_access = ntohl(*bp++); | ||
767 | vnode->status.mode = ntohl(*bp++); | ||
768 | vnode->status.parent.vid = dirfid->vid; | ||
769 | vnode->status.parent.vnode = ntohl(*bp++); | ||
770 | vnode->status.parent.unique = ntohl(*bp++); | ||
771 | bp++; /* seg size */ | ||
772 | vnode->status.mtime_client = ntohl(*bp++); | ||
773 | vnode->status.mtime_server = ntohl(*bp++); | ||
774 | bp++; /* group */ | ||
775 | bp++; /* sync counter */ | ||
776 | vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; | ||
777 | bp++; /* spare2 */ | ||
778 | bp++; /* spare3 */ | ||
779 | bp++; /* spare4 */ | ||
780 | 842 | ||
781 | dir->status.if_version = ntohl(*bp++); | 843 | _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); |
782 | dir->status.type = ntohl(*bp++); | 844 | |
783 | dir->status.nlink = ntohl(*bp++); | 845 | afs_transfer_reply(call, skb); |
784 | dir->status.size = ntohl(*bp++); | 846 | if (!last) |
785 | dir->status.version = ntohl(*bp++); | 847 | return 0; |
786 | dir->status.author = ntohl(*bp++); | 848 | |
787 | dir->status.owner = ntohl(*bp++); | 849 | if (call->reply_size != call->reply_max) |
788 | dir->status.caller_access = ntohl(*bp++); | 850 | return -EBADMSG; |
789 | dir->status.anon_access = ntohl(*bp++); | 851 | |
790 | dir->status.mode = ntohl(*bp++); | 852 | /* unmarshall the reply once we've received all of it */ |
791 | dir->status.parent.vid = dirfid->vid; | 853 | bp = call->buffer; |
792 | dir->status.parent.vnode = ntohl(*bp++); | 854 | xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode); |
793 | dir->status.parent.unique = ntohl(*bp++); | 855 | if (new_dvnode != orig_dvnode) |
794 | bp++; /* seg size */ | 856 | xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode); |
795 | dir->status.mtime_client = ntohl(*bp++); | 857 | /* xdr_decode_AFSVolSync(&bp, call->replyX); */ |
796 | dir->status.mtime_server = ntohl(*bp++); | 858 | |
797 | bp++; /* group */ | 859 | _leave(" = 0 [done]"); |
798 | bp++; /* sync counter */ | 860 | return 0; |
799 | dir->status.version |= ((unsigned long long) ntohl(*bp++)) << 32; | 861 | } |
800 | bp++; /* spare2 */ | 862 | |
801 | bp++; /* spare3 */ | 863 | /* |
802 | bp++; /* spare4 */ | 864 | * FS.Rename operation type |
865 | */ | ||
866 | static const struct afs_call_type afs_RXFSRename = { | ||
867 | .name = "FS.Rename", | ||
868 | .deliver = afs_deliver_fs_rename, | ||
869 | .abort_to_error = afs_abort_to_error, | ||
870 | .destructor = afs_flat_call_destructor, | ||
871 | }; | ||
872 | |||
873 | /* | ||
874 | * create a symbolic link | ||
875 | */ | ||
876 | int afs_fs_rename(struct afs_server *server, | ||
877 | struct key *key, | ||
878 | struct afs_vnode *orig_dvnode, | ||
879 | const char *orig_name, | ||
880 | struct afs_vnode *new_dvnode, | ||
881 | const char *new_name, | ||
882 | const struct afs_wait_mode *wait_mode) | ||
883 | { | ||
884 | struct afs_call *call; | ||
885 | size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz; | ||
886 | __be32 *bp; | ||
887 | |||
888 | _enter(""); | ||
889 | |||
890 | o_namesz = strlen(orig_name); | ||
891 | o_padsz = (4 - (o_namesz & 3)) & 3; | ||
892 | |||
893 | n_namesz = strlen(new_name); | ||
894 | n_padsz = (4 - (n_namesz & 3)) & 3; | ||
895 | |||
896 | reqsz = (4 * 4) + | ||
897 | 4 + o_namesz + o_padsz + | ||
898 | (3 * 4) + | ||
899 | 4 + n_namesz + n_padsz; | ||
900 | |||
901 | call = afs_alloc_flat_call(&afs_RXFSRename, reqsz, (21 + 21 + 6) * 4); | ||
902 | if (!call) | ||
903 | return -ENOMEM; | ||
904 | |||
905 | call->key = key; | ||
906 | call->reply = orig_dvnode; | ||
907 | call->reply2 = new_dvnode; | ||
908 | call->service_id = FS_SERVICE; | ||
909 | call->port = htons(AFS_FS_PORT); | ||
910 | |||
911 | /* marshall the parameters */ | ||
912 | bp = call->request; | ||
913 | *bp++ = htonl(FSRENAME); | ||
914 | *bp++ = htonl(orig_dvnode->fid.vid); | ||
915 | *bp++ = htonl(orig_dvnode->fid.vnode); | ||
916 | *bp++ = htonl(orig_dvnode->fid.unique); | ||
917 | *bp++ = htonl(o_namesz); | ||
918 | memcpy(bp, orig_name, o_namesz); | ||
919 | bp = (void *) bp + o_namesz; | ||
920 | if (o_padsz > 0) { | ||
921 | memset(bp, 0, o_padsz); | ||
922 | bp = (void *) bp + o_padsz; | ||
923 | } | ||
803 | 924 | ||
804 | callback->fid = *fid; | 925 | *bp++ = htonl(new_dvnode->fid.vid); |
805 | callback->version = ntohl(*bp++); | 926 | *bp++ = htonl(new_dvnode->fid.vnode); |
806 | callback->expiry = ntohl(*bp++); | 927 | *bp++ = htonl(new_dvnode->fid.unique); |
807 | callback->type = ntohl(*bp++); | 928 | *bp++ = htonl(n_namesz); |
808 | 929 | memcpy(bp, new_name, n_namesz); | |
809 | if (volsync) { | 930 | bp = (void *) bp + n_namesz; |
810 | volsync->creation = ntohl(*bp++); | 931 | if (n_padsz > 0) { |
811 | bp++; /* spare2 */ | 932 | memset(bp, 0, n_padsz); |
812 | bp++; /* spare3 */ | 933 | bp = (void *) bp + n_padsz; |
813 | bp++; /* spare4 */ | ||
814 | bp++; /* spare5 */ | ||
815 | bp++; /* spare6 */ | ||
816 | } | 934 | } |
817 | 935 | ||
818 | /* success */ | 936 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); |
819 | ret = 0; | 937 | } |
820 | |||
821 | out_unwait: | ||
822 | set_current_state(TASK_RUNNING); | ||
823 | remove_wait_queue(&call->waitq, &myself); | ||
824 | rxrpc_put_call(call); | ||
825 | out_put_conn: | ||
826 | afs_server_release_fsconn(server, conn); | ||
827 | out: | ||
828 | kleave(""); | ||
829 | return ret; | ||
830 | |||
831 | abort: | ||
832 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
833 | rxrpc_call_abort(call, ret); | ||
834 | schedule(); | ||
835 | goto out_unwait; | ||
836 | } /* end afs_rxfs_lookup() */ | ||
837 | #endif | ||