blob: 4bd0218473a9bb407a9c86be49f0400461621f24 [file] [log] [blame]
David Howells08e0e7c2007-04-26 15:55:03 -07001/* AFS File Server client stubs
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
David Howells08e0e7c2007-04-26 15:55:03 -07003 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/init.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/sched.h>
David Howells08e0e7c2007-04-26 15:55:03 -070015#include <linux/circ_buf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include "internal.h"
David Howells08e0e7c2007-04-26 15:55:03 -070017#include "afs_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Linus Torvalds1da177e2005-04-16 15:20:36 -070019/*
David Howells260a9802007-04-26 15:59:35 -070020 * decode an AFSFid block
21 */
22static void xdr_decode_AFSFid(const __be32 **_bp, struct afs_fid *fid)
23{
24 const __be32 *bp = *_bp;
25
26 fid->vid = ntohl(*bp++);
27 fid->vnode = ntohl(*bp++);
28 fid->unique = ntohl(*bp++);
29 *_bp = bp;
30}
31
32/*
David Howells08e0e7c2007-04-26 15:55:03 -070033 * decode an AFSFetchStatus block
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 */
David Howells08e0e7c2007-04-26 15:55:03 -070035static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
David Howells260a9802007-04-26 15:59:35 -070036 struct afs_file_status *status,
David Howells31143d52007-05-09 02:33:46 -070037 struct afs_vnode *vnode,
38 afs_dataversion_t *store_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -070039{
David Howells31143d52007-05-09 02:33:46 -070040 afs_dataversion_t expected_version;
David Howells08e0e7c2007-04-26 15:55:03 -070041 const __be32 *bp = *_bp;
42 umode_t mode;
David Howells260a9802007-04-26 15:59:35 -070043 u64 data_version, size;
David Howells08e0e7c2007-04-26 15:55:03 -070044 u32 changed = 0; /* becomes non-zero if ctime-type changes seen */
45
46#define EXTRACT(DST) \
47 do { \
48 u32 x = ntohl(*bp++); \
49 changed |= DST - x; \
50 DST = x; \
51 } while (0)
52
David Howells260a9802007-04-26 15:59:35 -070053 status->if_version = ntohl(*bp++);
54 EXTRACT(status->type);
55 EXTRACT(status->nlink);
56 size = ntohl(*bp++);
David Howells08e0e7c2007-04-26 15:55:03 -070057 data_version = ntohl(*bp++);
David Howells260a9802007-04-26 15:59:35 -070058 EXTRACT(status->author);
59 EXTRACT(status->owner);
60 EXTRACT(status->caller_access); /* call ticket dependent */
61 EXTRACT(status->anon_access);
62 EXTRACT(status->mode);
63 EXTRACT(status->parent.vnode);
64 EXTRACT(status->parent.unique);
David Howells08e0e7c2007-04-26 15:55:03 -070065 bp++; /* seg size */
David Howells260a9802007-04-26 15:59:35 -070066 status->mtime_client = ntohl(*bp++);
67 status->mtime_server = ntohl(*bp++);
68 EXTRACT(status->group);
David Howells08e0e7c2007-04-26 15:55:03 -070069 bp++; /* sync counter */
70 data_version |= (u64) ntohl(*bp++) << 32;
David Howellse8d6c552007-07-15 23:40:12 -070071 EXTRACT(status->lock_count);
David Howells260a9802007-04-26 15:59:35 -070072 size |= (u64) ntohl(*bp++) << 32;
73 bp++; /* spare 4 */
David Howells08e0e7c2007-04-26 15:55:03 -070074 *_bp = bp;
75
David Howells260a9802007-04-26 15:59:35 -070076 if (size != status->size) {
77 status->size = size;
78 changed |= true;
David Howells08e0e7c2007-04-26 15:55:03 -070079 }
David Howells260a9802007-04-26 15:59:35 -070080 status->mode &= S_IALLUGO;
David Howells08e0e7c2007-04-26 15:55:03 -070081
82 _debug("vnode time %lx, %lx",
David Howells260a9802007-04-26 15:59:35 -070083 status->mtime_client, status->mtime_server);
David Howells08e0e7c2007-04-26 15:55:03 -070084
David Howells260a9802007-04-26 15:59:35 -070085 if (vnode) {
86 status->parent.vid = vnode->fid.vid;
87 if (changed && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
88 _debug("vnode changed");
89 i_size_write(&vnode->vfs_inode, size);
90 vnode->vfs_inode.i_uid = status->owner;
91 vnode->vfs_inode.i_gid = status->group;
92 vnode->vfs_inode.i_version = vnode->fid.unique;
93 vnode->vfs_inode.i_nlink = status->nlink;
94
95 mode = vnode->vfs_inode.i_mode;
96 mode &= ~S_IALLUGO;
97 mode |= status->mode;
98 barrier();
99 vnode->vfs_inode.i_mode = mode;
100 }
101
102 vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server;
103 vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime;
104 vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime;
105 }
106
David Howells31143d52007-05-09 02:33:46 -0700107 expected_version = status->data_version;
108 if (store_version)
109 expected_version = *store_version;
110
111 if (expected_version != data_version) {
David Howells260a9802007-04-26 15:59:35 -0700112 status->data_version = data_version;
113 if (vnode && !test_bit(AFS_VNODE_UNSET, &vnode->flags)) {
114 _debug("vnode modified %llx on {%x:%u}",
David S. Millerba3e0e12007-04-26 16:06:22 -0700115 (unsigned long long) data_version,
116 vnode->fid.vid, vnode->fid.vnode);
David Howells260a9802007-04-26 15:59:35 -0700117 set_bit(AFS_VNODE_MODIFIED, &vnode->flags);
118 set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
119 }
David Howells31143d52007-05-09 02:33:46 -0700120 } else if (store_version) {
121 status->data_version = data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 }
David Howellsec268152007-04-26 15:49:28 -0700123}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125/*
David Howells08e0e7c2007-04-26 15:55:03 -0700126 * decode an AFSCallBack block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 */
David Howells08e0e7c2007-04-26 15:55:03 -0700128static void xdr_decode_AFSCallBack(const __be32 **_bp, struct afs_vnode *vnode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
David Howells08e0e7c2007-04-26 15:55:03 -0700130 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
David Howells08e0e7c2007-04-26 15:55:03 -0700132 vnode->cb_version = ntohl(*bp++);
133 vnode->cb_expiry = ntohl(*bp++);
134 vnode->cb_type = ntohl(*bp++);
135 vnode->cb_expires = vnode->cb_expiry + get_seconds();
136 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700137}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
David Howells260a9802007-04-26 15:59:35 -0700139static void xdr_decode_AFSCallBack_raw(const __be32 **_bp,
140 struct afs_callback *cb)
141{
142 const __be32 *bp = *_bp;
143
144 cb->version = ntohl(*bp++);
145 cb->expiry = ntohl(*bp++);
146 cb->type = ntohl(*bp++);
147 *_bp = bp;
148}
149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150/*
David Howells08e0e7c2007-04-26 15:55:03 -0700151 * decode an AFSVolSync block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 */
David Howells08e0e7c2007-04-26 15:55:03 -0700153static void xdr_decode_AFSVolSync(const __be32 **_bp,
154 struct afs_volsync *volsync)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155{
David Howells08e0e7c2007-04-26 15:55:03 -0700156 const __be32 *bp = *_bp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
David Howells08e0e7c2007-04-26 15:55:03 -0700158 volsync->creation = ntohl(*bp++);
159 bp++; /* spare2 */
160 bp++; /* spare3 */
161 bp++; /* spare4 */
162 bp++; /* spare5 */
163 bp++; /* spare6 */
164 *_bp = bp;
David Howellsec268152007-04-26 15:49:28 -0700165}
David Howells08e0e7c2007-04-26 15:55:03 -0700166
167/*
David Howells31143d52007-05-09 02:33:46 -0700168 * encode the requested attributes into an AFSStoreStatus block
169 */
170static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr)
171{
172 __be32 *bp = *_bp;
173 u32 mask = 0, mtime = 0, owner = 0, group = 0, mode = 0;
174
175 mask = 0;
176 if (attr->ia_valid & ATTR_MTIME) {
177 mask |= AFS_SET_MTIME;
178 mtime = attr->ia_mtime.tv_sec;
179 }
180
181 if (attr->ia_valid & ATTR_UID) {
182 mask |= AFS_SET_OWNER;
183 owner = attr->ia_uid;
184 }
185
186 if (attr->ia_valid & ATTR_GID) {
187 mask |= AFS_SET_GROUP;
188 group = attr->ia_gid;
189 }
190
191 if (attr->ia_valid & ATTR_MODE) {
192 mask |= AFS_SET_MODE;
193 mode = attr->ia_mode & S_IALLUGO;
194 }
195
196 *bp++ = htonl(mask);
197 *bp++ = htonl(mtime);
198 *bp++ = htonl(owner);
199 *bp++ = htonl(group);
200 *bp++ = htonl(mode);
201 *bp++ = 0; /* segment size */
202 *_bp = bp;
203}
204
205/*
David Howells45222b92007-05-10 22:22:20 -0700206 * decode an AFSFetchVolumeStatus block
207 */
208static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
209 struct afs_volume_status *vs)
210{
211 const __be32 *bp = *_bp;
212
213 vs->vid = ntohl(*bp++);
214 vs->parent_id = ntohl(*bp++);
215 vs->online = ntohl(*bp++);
216 vs->in_service = ntohl(*bp++);
217 vs->blessed = ntohl(*bp++);
218 vs->needs_salvage = ntohl(*bp++);
219 vs->type = ntohl(*bp++);
220 vs->min_quota = ntohl(*bp++);
221 vs->max_quota = ntohl(*bp++);
222 vs->blocks_in_use = ntohl(*bp++);
223 vs->part_blocks_avail = ntohl(*bp++);
224 vs->part_max_blocks = ntohl(*bp++);
225 *_bp = bp;
226}
227
228/*
David Howells08e0e7c2007-04-26 15:55:03 -0700229 * deliver reply data to an FS.FetchStatus
230 */
231static int afs_deliver_fs_fetch_status(struct afs_call *call,
232 struct sk_buff *skb, bool last)
233{
David Howells260a9802007-04-26 15:59:35 -0700234 struct afs_vnode *vnode = call->reply;
David Howells08e0e7c2007-04-26 15:55:03 -0700235 const __be32 *bp;
236
237 _enter(",,%u", last);
238
239 afs_transfer_reply(call, skb);
240 if (!last)
241 return 0;
242
243 if (call->reply_size != call->reply_max)
244 return -EBADMSG;
245
246 /* unmarshall the reply once we've received all of it */
247 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700248 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700249 xdr_decode_AFSCallBack(&bp, vnode);
David Howells08e0e7c2007-04-26 15:55:03 -0700250 if (call->reply2)
251 xdr_decode_AFSVolSync(&bp, call->reply2);
252
253 _leave(" = 0 [done]");
254 return 0;
255}
256
257/*
258 * FS.FetchStatus operation type
259 */
260static const struct afs_call_type afs_RXFSFetchStatus = {
David Howells00d3b7a2007-04-26 15:57:07 -0700261 .name = "FS.FetchStatus",
David Howells08e0e7c2007-04-26 15:55:03 -0700262 .deliver = afs_deliver_fs_fetch_status,
263 .abort_to_error = afs_abort_to_error,
264 .destructor = afs_flat_call_destructor,
265};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267/*
268 * fetch the status information for a file
269 */
David Howells08e0e7c2007-04-26 15:55:03 -0700270int afs_fs_fetch_file_status(struct afs_server *server,
David Howells00d3b7a2007-04-26 15:57:07 -0700271 struct key *key,
David Howells08e0e7c2007-04-26 15:55:03 -0700272 struct afs_vnode *vnode,
273 struct afs_volsync *volsync,
274 const struct afs_wait_mode *wait_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
David Howells08e0e7c2007-04-26 15:55:03 -0700276 struct afs_call *call;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 __be32 *bp;
278
David Howells416351f2007-05-09 02:33:45 -0700279 _enter(",%x,{%x:%u},,",
David Howells260a9802007-04-26 15:59:35 -0700280 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
David Howells260a9802007-04-26 15:59:35 -0700282 call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700283 if (!call)
284 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
David Howells00d3b7a2007-04-26 15:57:07 -0700286 call->key = key;
David Howells08e0e7c2007-04-26 15:55:03 -0700287 call->reply = vnode;
288 call->reply2 = volsync;
289 call->service_id = FS_SERVICE;
290 call->port = htons(AFS_FS_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
292 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700293 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 bp[0] = htonl(FSFETCHSTATUS);
295 bp[1] = htonl(vnode->fid.vid);
296 bp[2] = htonl(vnode->fid.vnode);
297 bp[3] = htonl(vnode->fid.unique);
298
David Howells08e0e7c2007-04-26 15:55:03 -0700299 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
David Howellsec268152007-04-26 15:49:28 -0700300}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302/*
David Howells08e0e7c2007-04-26 15:55:03 -0700303 * deliver reply data to an FS.FetchData
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 */
David Howells08e0e7c2007-04-26 15:55:03 -0700305static int afs_deliver_fs_fetch_data(struct afs_call *call,
306 struct sk_buff *skb, bool last)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307{
David Howells260a9802007-04-26 15:59:35 -0700308 struct afs_vnode *vnode = call->reply;
David Howells08e0e7c2007-04-26 15:55:03 -0700309 const __be32 *bp;
310 struct page *page;
311 void *buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 int ret;
David Howells08e0e7c2007-04-26 15:55:03 -0700313
314 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
315
316 switch (call->unmarshall) {
317 case 0:
318 call->offset = 0;
319 call->unmarshall++;
David Howellsb9b1f8d2007-05-10 03:15:21 -0700320 if (call->operation_ID != FSFETCHDATA64) {
321 call->unmarshall++;
322 goto no_msw;
323 }
David Howells08e0e7c2007-04-26 15:55:03 -0700324
David Howellsb9b1f8d2007-05-10 03:15:21 -0700325 /* extract the upper part of the returned data length of an
326 * FSFETCHDATA64 op (which should always be 0 using this
327 * client) */
David Howells08e0e7c2007-04-26 15:55:03 -0700328 case 1:
David Howellsb9b1f8d2007-05-10 03:15:21 -0700329 _debug("extract data length (MSW)");
330 ret = afs_extract_data(call, skb, last, &call->tmp, 4);
331 switch (ret) {
332 case 0: break;
333 case -EAGAIN: return 0;
334 default: return ret;
335 }
336
337 call->count = ntohl(call->tmp);
338 _debug("DATA length MSW: %u", call->count);
339 if (call->count > 0)
340 return -EBADMSG;
341 call->offset = 0;
342 call->unmarshall++;
343
344 no_msw:
345 /* extract the returned data length */
346 case 2:
David Howells08e0e7c2007-04-26 15:55:03 -0700347 _debug("extract data length");
348 ret = afs_extract_data(call, skb, last, &call->tmp, 4);
349 switch (ret) {
350 case 0: break;
351 case -EAGAIN: return 0;
352 default: return ret;
353 }
354
355 call->count = ntohl(call->tmp);
356 _debug("DATA length: %u", call->count);
357 if (call->count > PAGE_SIZE)
358 return -EBADMSG;
359 call->offset = 0;
360 call->unmarshall++;
361
David Howells08e0e7c2007-04-26 15:55:03 -0700362 /* extract the returned data */
David Howellsb9b1f8d2007-05-10 03:15:21 -0700363 case 3:
David Howells08e0e7c2007-04-26 15:55:03 -0700364 _debug("extract data");
David Howells416351f2007-05-09 02:33:45 -0700365 if (call->count > 0) {
366 page = call->reply3;
367 buffer = kmap_atomic(page, KM_USER0);
368 ret = afs_extract_data(call, skb, last, buffer,
369 call->count);
370 kunmap_atomic(buffer, KM_USER0);
371 switch (ret) {
372 case 0: break;
373 case -EAGAIN: return 0;
374 default: return ret;
375 }
David Howells08e0e7c2007-04-26 15:55:03 -0700376 }
377
378 call->offset = 0;
379 call->unmarshall++;
380
381 /* extract the metadata */
David Howellsb9b1f8d2007-05-10 03:15:21 -0700382 case 4:
David Howells260a9802007-04-26 15:59:35 -0700383 ret = afs_extract_data(call, skb, last, call->buffer,
384 (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700385 switch (ret) {
386 case 0: break;
387 case -EAGAIN: return 0;
388 default: return ret;
389 }
390
391 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700392 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700393 xdr_decode_AFSCallBack(&bp, vnode);
David Howells08e0e7c2007-04-26 15:55:03 -0700394 if (call->reply2)
395 xdr_decode_AFSVolSync(&bp, call->reply2);
396
397 call->offset = 0;
398 call->unmarshall++;
399
David Howellsb9b1f8d2007-05-10 03:15:21 -0700400 case 5:
David Howells08e0e7c2007-04-26 15:55:03 -0700401 _debug("trailer");
402 if (skb->len != 0)
403 return -EBADMSG;
404 break;
405 }
406
407 if (!last)
408 return 0;
409
David Howells416351f2007-05-09 02:33:45 -0700410 if (call->count < PAGE_SIZE) {
411 _debug("clear");
412 page = call->reply3;
413 buffer = kmap_atomic(page, KM_USER0);
414 memset(buffer + call->count, 0, PAGE_SIZE - call->count);
415 kunmap_atomic(buffer, KM_USER0);
416 }
417
David Howells08e0e7c2007-04-26 15:55:03 -0700418 _leave(" = 0 [done]");
419 return 0;
420}
421
422/*
423 * FS.FetchData operation type
424 */
425static const struct afs_call_type afs_RXFSFetchData = {
David Howells00d3b7a2007-04-26 15:57:07 -0700426 .name = "FS.FetchData",
David Howells08e0e7c2007-04-26 15:55:03 -0700427 .deliver = afs_deliver_fs_fetch_data,
428 .abort_to_error = afs_abort_to_error,
429 .destructor = afs_flat_call_destructor,
430};
431
David Howellsb9b1f8d2007-05-10 03:15:21 -0700432static const struct afs_call_type afs_RXFSFetchData64 = {
433 .name = "FS.FetchData64",
434 .deliver = afs_deliver_fs_fetch_data,
435 .abort_to_error = afs_abort_to_error,
436 .destructor = afs_flat_call_destructor,
437};
438
439/*
440 * fetch data from a very large file
441 */
442static int afs_fs_fetch_data64(struct afs_server *server,
443 struct key *key,
444 struct afs_vnode *vnode,
445 off_t offset, size_t length,
446 struct page *buffer,
447 const struct afs_wait_mode *wait_mode)
448{
449 struct afs_call *call;
450 __be32 *bp;
451
452 _enter("");
453
454 ASSERTCMP(length, <, ULONG_MAX);
455
456 call = afs_alloc_flat_call(&afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
457 if (!call)
458 return -ENOMEM;
459
460 call->key = key;
461 call->reply = vnode;
462 call->reply2 = NULL; /* volsync */
463 call->reply3 = buffer;
464 call->service_id = FS_SERVICE;
465 call->port = htons(AFS_FS_PORT);
466 call->operation_ID = FSFETCHDATA64;
467
468 /* marshall the parameters */
469 bp = call->request;
470 bp[0] = htonl(FSFETCHDATA64);
471 bp[1] = htonl(vnode->fid.vid);
472 bp[2] = htonl(vnode->fid.vnode);
473 bp[3] = htonl(vnode->fid.unique);
474 bp[4] = htonl(upper_32_bits(offset));
475 bp[5] = htonl((u32) offset);
476 bp[6] = 0;
477 bp[7] = htonl((u32) length);
478
479 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
480}
481
David Howells08e0e7c2007-04-26 15:55:03 -0700482/*
483 * fetch data from a file
484 */
485int afs_fs_fetch_data(struct afs_server *server,
David Howells00d3b7a2007-04-26 15:57:07 -0700486 struct key *key,
David Howells08e0e7c2007-04-26 15:55:03 -0700487 struct afs_vnode *vnode,
488 off_t offset, size_t length,
489 struct page *buffer,
David Howells08e0e7c2007-04-26 15:55:03 -0700490 const struct afs_wait_mode *wait_mode)
491{
492 struct afs_call *call;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 __be32 *bp;
494
David Howellsb9b1f8d2007-05-10 03:15:21 -0700495 if (upper_32_bits(offset) || upper_32_bits(offset + length))
496 return afs_fs_fetch_data64(server, key, vnode, offset, length,
497 buffer, wait_mode);
498
David Howells08e0e7c2007-04-26 15:55:03 -0700499 _enter("");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
David Howells260a9802007-04-26 15:59:35 -0700501 call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
David Howells08e0e7c2007-04-26 15:55:03 -0700502 if (!call)
503 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504
David Howells00d3b7a2007-04-26 15:57:07 -0700505 call->key = key;
David Howells08e0e7c2007-04-26 15:55:03 -0700506 call->reply = vnode;
David Howells260a9802007-04-26 15:59:35 -0700507 call->reply2 = NULL; /* volsync */
David Howells08e0e7c2007-04-26 15:55:03 -0700508 call->reply3 = buffer;
509 call->service_id = FS_SERVICE;
510 call->port = htons(AFS_FS_PORT);
David Howellsb9b1f8d2007-05-10 03:15:21 -0700511 call->operation_ID = FSFETCHDATA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700514 bp = call->request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 bp[0] = htonl(FSFETCHDATA);
David Howells08e0e7c2007-04-26 15:55:03 -0700516 bp[1] = htonl(vnode->fid.vid);
517 bp[2] = htonl(vnode->fid.vnode);
518 bp[3] = htonl(vnode->fid.unique);
519 bp[4] = htonl(offset);
520 bp[5] = htonl(length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
David Howells08e0e7c2007-04-26 15:55:03 -0700522 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
David Howellsec268152007-04-26 15:49:28 -0700523}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525/*
David Howells08e0e7c2007-04-26 15:55:03 -0700526 * deliver reply data to an FS.GiveUpCallBacks
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 */
David Howells08e0e7c2007-04-26 15:55:03 -0700528static int afs_deliver_fs_give_up_callbacks(struct afs_call *call,
529 struct sk_buff *skb, bool last)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
David Howells08e0e7c2007-04-26 15:55:03 -0700531 _enter(",{%u},%d", skb->len, last);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
David Howells08e0e7c2007-04-26 15:55:03 -0700533 if (skb->len > 0)
534 return -EBADMSG; /* shouldn't be any reply data */
535 return 0;
536}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
David Howells08e0e7c2007-04-26 15:55:03 -0700538/*
539 * FS.GiveUpCallBacks operation type
540 */
541static const struct afs_call_type afs_RXFSGiveUpCallBacks = {
David Howells00d3b7a2007-04-26 15:57:07 -0700542 .name = "FS.GiveUpCallBacks",
David Howells08e0e7c2007-04-26 15:55:03 -0700543 .deliver = afs_deliver_fs_give_up_callbacks,
544 .abort_to_error = afs_abort_to_error,
545 .destructor = afs_flat_call_destructor,
546};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
David Howells08e0e7c2007-04-26 15:55:03 -0700548/*
549 * give up a set of callbacks
550 * - the callbacks are held in the server->cb_break ring
551 */
552int afs_fs_give_up_callbacks(struct afs_server *server,
553 const struct afs_wait_mode *wait_mode)
554{
555 struct afs_call *call;
556 size_t ncallbacks;
557 __be32 *bp, *tp;
558 int loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
David Howells08e0e7c2007-04-26 15:55:03 -0700560 ncallbacks = CIRC_CNT(server->cb_break_head, server->cb_break_tail,
561 ARRAY_SIZE(server->cb_break));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
David Howells08e0e7c2007-04-26 15:55:03 -0700563 _enter("{%zu},", ncallbacks);
564
565 if (ncallbacks == 0)
566 return 0;
567 if (ncallbacks > AFSCBMAX)
568 ncallbacks = AFSCBMAX;
569
570 _debug("break %zu callbacks", ncallbacks);
571
572 call = afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks,
573 12 + ncallbacks * 6 * 4, 0);
574 if (!call)
575 return -ENOMEM;
576
577 call->service_id = FS_SERVICE;
578 call->port = htons(AFS_FS_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
580 /* marshall the parameters */
David Howells08e0e7c2007-04-26 15:55:03 -0700581 bp = call->request;
582 tp = bp + 2 + ncallbacks * 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 *bp++ = htonl(FSGIVEUPCALLBACKS);
David Howells08e0e7c2007-04-26 15:55:03 -0700584 *bp++ = htonl(ncallbacks);
585 *tp++ = htonl(ncallbacks);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586
David Howells08e0e7c2007-04-26 15:55:03 -0700587 atomic_sub(ncallbacks, &server->cb_break_n);
588 for (loop = ncallbacks; loop > 0; loop--) {
589 struct afs_callback *cb =
590 &server->cb_break[server->cb_break_tail];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
David Howells08e0e7c2007-04-26 15:55:03 -0700592 *bp++ = htonl(cb->fid.vid);
593 *bp++ = htonl(cb->fid.vnode);
594 *bp++ = htonl(cb->fid.unique);
595 *tp++ = htonl(cb->version);
596 *tp++ = htonl(cb->expiry);
597 *tp++ = htonl(cb->type);
598 smp_mb();
599 server->cb_break_tail =
600 (server->cb_break_tail + 1) &
601 (ARRAY_SIZE(server->cb_break) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 }
603
David Howells08e0e7c2007-04-26 15:55:03 -0700604 ASSERT(ncallbacks > 0);
605 wake_up_nr(&server->cb_break_waitq, ncallbacks);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
David Howells08e0e7c2007-04-26 15:55:03 -0700607 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
David Howellsec268152007-04-26 15:49:28 -0700608}
David Howells260a9802007-04-26 15:59:35 -0700609
610/*
611 * deliver reply data to an FS.CreateFile or an FS.MakeDir
612 */
613static int afs_deliver_fs_create_vnode(struct afs_call *call,
614 struct sk_buff *skb, bool last)
615{
616 struct afs_vnode *vnode = call->reply;
617 const __be32 *bp;
618
619 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
620
621 afs_transfer_reply(call, skb);
622 if (!last)
623 return 0;
624
625 if (call->reply_size != call->reply_max)
626 return -EBADMSG;
627
628 /* unmarshall the reply once we've received all of it */
629 bp = call->buffer;
630 xdr_decode_AFSFid(&bp, call->reply2);
David Howells31143d52007-05-09 02:33:46 -0700631 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
632 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700633 xdr_decode_AFSCallBack_raw(&bp, call->reply4);
634 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
635
636 _leave(" = 0 [done]");
637 return 0;
638}
639
640/*
641 * FS.CreateFile and FS.MakeDir operation type
642 */
643static const struct afs_call_type afs_RXFSCreateXXXX = {
644 .name = "FS.CreateXXXX",
645 .deliver = afs_deliver_fs_create_vnode,
646 .abort_to_error = afs_abort_to_error,
647 .destructor = afs_flat_call_destructor,
648};
649
650/*
651 * create a file or make a directory
652 */
653int afs_fs_create(struct afs_server *server,
654 struct key *key,
655 struct afs_vnode *vnode,
656 const char *name,
657 umode_t mode,
658 struct afs_fid *newfid,
659 struct afs_file_status *newstatus,
660 struct afs_callback *newcb,
661 const struct afs_wait_mode *wait_mode)
662{
663 struct afs_call *call;
664 size_t namesz, reqsz, padsz;
665 __be32 *bp;
666
667 _enter("");
668
669 namesz = strlen(name);
670 padsz = (4 - (namesz & 3)) & 3;
671 reqsz = (5 * 4) + namesz + padsz + (6 * 4);
672
673 call = afs_alloc_flat_call(&afs_RXFSCreateXXXX, reqsz,
674 (3 + 21 + 21 + 3 + 6) * 4);
675 if (!call)
676 return -ENOMEM;
677
678 call->key = key;
679 call->reply = vnode;
680 call->reply2 = newfid;
681 call->reply3 = newstatus;
682 call->reply4 = newcb;
683 call->service_id = FS_SERVICE;
684 call->port = htons(AFS_FS_PORT);
685
686 /* marshall the parameters */
687 bp = call->request;
688 *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE);
689 *bp++ = htonl(vnode->fid.vid);
690 *bp++ = htonl(vnode->fid.vnode);
691 *bp++ = htonl(vnode->fid.unique);
692 *bp++ = htonl(namesz);
693 memcpy(bp, name, namesz);
694 bp = (void *) bp + namesz;
695 if (padsz > 0) {
696 memset(bp, 0, padsz);
697 bp = (void *) bp + padsz;
698 }
699 *bp++ = htonl(AFS_SET_MODE);
700 *bp++ = 0; /* mtime */
701 *bp++ = 0; /* owner */
702 *bp++ = 0; /* group */
703 *bp++ = htonl(mode & S_IALLUGO); /* unix mode */
704 *bp++ = 0; /* segment size */
705
706 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
707}
708
709/*
710 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
711 */
712static int afs_deliver_fs_remove(struct afs_call *call,
713 struct sk_buff *skb, bool last)
714{
715 struct afs_vnode *vnode = call->reply;
716 const __be32 *bp;
717
718 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
719
720 afs_transfer_reply(call, skb);
721 if (!last)
722 return 0;
723
724 if (call->reply_size != call->reply_max)
725 return -EBADMSG;
726
727 /* unmarshall the reply once we've received all of it */
728 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700729 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700730 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
731
732 _leave(" = 0 [done]");
733 return 0;
734}
735
736/*
737 * FS.RemoveDir/FS.RemoveFile operation type
738 */
739static const struct afs_call_type afs_RXFSRemoveXXXX = {
740 .name = "FS.RemoveXXXX",
741 .deliver = afs_deliver_fs_remove,
742 .abort_to_error = afs_abort_to_error,
743 .destructor = afs_flat_call_destructor,
744};
745
746/*
747 * remove a file or directory
748 */
749int afs_fs_remove(struct afs_server *server,
750 struct key *key,
751 struct afs_vnode *vnode,
752 const char *name,
753 bool isdir,
754 const struct afs_wait_mode *wait_mode)
755{
756 struct afs_call *call;
757 size_t namesz, reqsz, padsz;
758 __be32 *bp;
759
760 _enter("");
761
762 namesz = strlen(name);
763 padsz = (4 - (namesz & 3)) & 3;
764 reqsz = (5 * 4) + namesz + padsz;
765
766 call = afs_alloc_flat_call(&afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4);
767 if (!call)
768 return -ENOMEM;
769
770 call->key = key;
771 call->reply = vnode;
772 call->service_id = FS_SERVICE;
773 call->port = htons(AFS_FS_PORT);
774
775 /* marshall the parameters */
776 bp = call->request;
777 *bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
778 *bp++ = htonl(vnode->fid.vid);
779 *bp++ = htonl(vnode->fid.vnode);
780 *bp++ = htonl(vnode->fid.unique);
781 *bp++ = htonl(namesz);
782 memcpy(bp, name, namesz);
783 bp = (void *) bp + namesz;
784 if (padsz > 0) {
785 memset(bp, 0, padsz);
786 bp = (void *) bp + padsz;
787 }
788
789 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
790}
791
792/*
793 * deliver reply data to an FS.Link
794 */
795static int afs_deliver_fs_link(struct afs_call *call,
796 struct sk_buff *skb, bool last)
797{
798 struct afs_vnode *dvnode = call->reply, *vnode = call->reply2;
799 const __be32 *bp;
800
801 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
802
803 afs_transfer_reply(call, skb);
804 if (!last)
805 return 0;
806
807 if (call->reply_size != call->reply_max)
808 return -EBADMSG;
809
810 /* unmarshall the reply once we've received all of it */
811 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -0700812 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
813 xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700814 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
815
816 _leave(" = 0 [done]");
817 return 0;
818}
819
820/*
821 * FS.Link operation type
822 */
823static const struct afs_call_type afs_RXFSLink = {
824 .name = "FS.Link",
825 .deliver = afs_deliver_fs_link,
826 .abort_to_error = afs_abort_to_error,
827 .destructor = afs_flat_call_destructor,
828};
829
830/*
831 * make a hard link
832 */
833int afs_fs_link(struct afs_server *server,
834 struct key *key,
835 struct afs_vnode *dvnode,
836 struct afs_vnode *vnode,
837 const char *name,
838 const struct afs_wait_mode *wait_mode)
839{
840 struct afs_call *call;
841 size_t namesz, reqsz, padsz;
842 __be32 *bp;
843
844 _enter("");
845
846 namesz = strlen(name);
847 padsz = (4 - (namesz & 3)) & 3;
848 reqsz = (5 * 4) + namesz + padsz + (3 * 4);
849
850 call = afs_alloc_flat_call(&afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
851 if (!call)
852 return -ENOMEM;
853
854 call->key = key;
855 call->reply = dvnode;
856 call->reply2 = vnode;
857 call->service_id = FS_SERVICE;
858 call->port = htons(AFS_FS_PORT);
859
860 /* marshall the parameters */
861 bp = call->request;
862 *bp++ = htonl(FSLINK);
863 *bp++ = htonl(dvnode->fid.vid);
864 *bp++ = htonl(dvnode->fid.vnode);
865 *bp++ = htonl(dvnode->fid.unique);
866 *bp++ = htonl(namesz);
867 memcpy(bp, name, namesz);
868 bp = (void *) bp + namesz;
869 if (padsz > 0) {
870 memset(bp, 0, padsz);
871 bp = (void *) bp + padsz;
872 }
873 *bp++ = htonl(vnode->fid.vid);
874 *bp++ = htonl(vnode->fid.vnode);
875 *bp++ = htonl(vnode->fid.unique);
876
877 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
878}
879
880/*
881 * deliver reply data to an FS.Symlink
882 */
883static int afs_deliver_fs_symlink(struct afs_call *call,
884 struct sk_buff *skb, bool last)
885{
886 struct afs_vnode *vnode = call->reply;
887 const __be32 *bp;
888
889 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
890
891 afs_transfer_reply(call, skb);
892 if (!last)
893 return 0;
894
895 if (call->reply_size != call->reply_max)
896 return -EBADMSG;
897
898 /* unmarshall the reply once we've received all of it */
899 bp = call->buffer;
900 xdr_decode_AFSFid(&bp, call->reply2);
David Howells31143d52007-05-09 02:33:46 -0700901 xdr_decode_AFSFetchStatus(&bp, call->reply3, NULL, NULL);
902 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, NULL);
David Howells260a9802007-04-26 15:59:35 -0700903 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
904
905 _leave(" = 0 [done]");
906 return 0;
907}
908
909/*
910 * FS.Symlink operation type
911 */
912static const struct afs_call_type afs_RXFSSymlink = {
913 .name = "FS.Symlink",
914 .deliver = afs_deliver_fs_symlink,
915 .abort_to_error = afs_abort_to_error,
916 .destructor = afs_flat_call_destructor,
917};
918
919/*
920 * create a symbolic link
921 */
922int afs_fs_symlink(struct afs_server *server,
923 struct key *key,
924 struct afs_vnode *vnode,
925 const char *name,
926 const char *contents,
927 struct afs_fid *newfid,
928 struct afs_file_status *newstatus,
929 const struct afs_wait_mode *wait_mode)
930{
931 struct afs_call *call;
932 size_t namesz, reqsz, padsz, c_namesz, c_padsz;
933 __be32 *bp;
934
935 _enter("");
936
937 namesz = strlen(name);
938 padsz = (4 - (namesz & 3)) & 3;
939
940 c_namesz = strlen(contents);
941 c_padsz = (4 - (c_namesz & 3)) & 3;
942
943 reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
944
945 call = afs_alloc_flat_call(&afs_RXFSSymlink, reqsz,
946 (3 + 21 + 21 + 6) * 4);
947 if (!call)
948 return -ENOMEM;
949
950 call->key = key;
951 call->reply = vnode;
952 call->reply2 = newfid;
953 call->reply3 = newstatus;
954 call->service_id = FS_SERVICE;
955 call->port = htons(AFS_FS_PORT);
956
957 /* marshall the parameters */
958 bp = call->request;
959 *bp++ = htonl(FSSYMLINK);
960 *bp++ = htonl(vnode->fid.vid);
961 *bp++ = htonl(vnode->fid.vnode);
962 *bp++ = htonl(vnode->fid.unique);
963 *bp++ = htonl(namesz);
964 memcpy(bp, name, namesz);
965 bp = (void *) bp + namesz;
966 if (padsz > 0) {
967 memset(bp, 0, padsz);
968 bp = (void *) bp + padsz;
969 }
970 *bp++ = htonl(c_namesz);
971 memcpy(bp, contents, c_namesz);
972 bp = (void *) bp + c_namesz;
973 if (c_padsz > 0) {
974 memset(bp, 0, c_padsz);
975 bp = (void *) bp + c_padsz;
976 }
977 *bp++ = htonl(AFS_SET_MODE);
978 *bp++ = 0; /* mtime */
979 *bp++ = 0; /* owner */
980 *bp++ = 0; /* group */
981 *bp++ = htonl(S_IRWXUGO); /* unix mode */
982 *bp++ = 0; /* segment size */
983
984 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
985}
986
987/*
988 * deliver reply data to an FS.Rename
989 */
990static int afs_deliver_fs_rename(struct afs_call *call,
991 struct sk_buff *skb, bool last)
992{
993 struct afs_vnode *orig_dvnode = call->reply, *new_dvnode = call->reply2;
994 const __be32 *bp;
995
996 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
997
998 afs_transfer_reply(call, skb);
999 if (!last)
1000 return 0;
1001
1002 if (call->reply_size != call->reply_max)
1003 return -EBADMSG;
1004
1005 /* unmarshall the reply once we've received all of it */
1006 bp = call->buffer;
David Howells31143d52007-05-09 02:33:46 -07001007 xdr_decode_AFSFetchStatus(&bp, &orig_dvnode->status, orig_dvnode, NULL);
David Howells260a9802007-04-26 15:59:35 -07001008 if (new_dvnode != orig_dvnode)
David Howells31143d52007-05-09 02:33:46 -07001009 xdr_decode_AFSFetchStatus(&bp, &new_dvnode->status, new_dvnode,
1010 NULL);
David Howells260a9802007-04-26 15:59:35 -07001011 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1012
1013 _leave(" = 0 [done]");
1014 return 0;
1015}
1016
1017/*
1018 * FS.Rename operation type
1019 */
1020static const struct afs_call_type afs_RXFSRename = {
1021 .name = "FS.Rename",
1022 .deliver = afs_deliver_fs_rename,
1023 .abort_to_error = afs_abort_to_error,
1024 .destructor = afs_flat_call_destructor,
1025};
1026
1027/*
1028 * create a symbolic link
1029 */
1030int afs_fs_rename(struct afs_server *server,
1031 struct key *key,
1032 struct afs_vnode *orig_dvnode,
1033 const char *orig_name,
1034 struct afs_vnode *new_dvnode,
1035 const char *new_name,
1036 const struct afs_wait_mode *wait_mode)
1037{
1038 struct afs_call *call;
1039 size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
1040 __be32 *bp;
1041
1042 _enter("");
1043
1044 o_namesz = strlen(orig_name);
1045 o_padsz = (4 - (o_namesz & 3)) & 3;
1046
1047 n_namesz = strlen(new_name);
1048 n_padsz = (4 - (n_namesz & 3)) & 3;
1049
1050 reqsz = (4 * 4) +
1051 4 + o_namesz + o_padsz +
1052 (3 * 4) +
1053 4 + n_namesz + n_padsz;
1054
1055 call = afs_alloc_flat_call(&afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
1056 if (!call)
1057 return -ENOMEM;
1058
1059 call->key = key;
1060 call->reply = orig_dvnode;
1061 call->reply2 = new_dvnode;
1062 call->service_id = FS_SERVICE;
1063 call->port = htons(AFS_FS_PORT);
1064
1065 /* marshall the parameters */
1066 bp = call->request;
1067 *bp++ = htonl(FSRENAME);
1068 *bp++ = htonl(orig_dvnode->fid.vid);
1069 *bp++ = htonl(orig_dvnode->fid.vnode);
1070 *bp++ = htonl(orig_dvnode->fid.unique);
1071 *bp++ = htonl(o_namesz);
1072 memcpy(bp, orig_name, o_namesz);
1073 bp = (void *) bp + o_namesz;
1074 if (o_padsz > 0) {
1075 memset(bp, 0, o_padsz);
1076 bp = (void *) bp + o_padsz;
1077 }
1078
1079 *bp++ = htonl(new_dvnode->fid.vid);
1080 *bp++ = htonl(new_dvnode->fid.vnode);
1081 *bp++ = htonl(new_dvnode->fid.unique);
1082 *bp++ = htonl(n_namesz);
1083 memcpy(bp, new_name, n_namesz);
1084 bp = (void *) bp + n_namesz;
1085 if (n_padsz > 0) {
1086 memset(bp, 0, n_padsz);
1087 bp = (void *) bp + n_padsz;
1088 }
1089
1090 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1091}
David Howells31143d52007-05-09 02:33:46 -07001092
1093/*
1094 * deliver reply data to an FS.StoreData
1095 */
1096static int afs_deliver_fs_store_data(struct afs_call *call,
1097 struct sk_buff *skb, bool last)
1098{
1099 struct afs_vnode *vnode = call->reply;
1100 const __be32 *bp;
1101
1102 _enter(",,%u", last);
1103
1104 afs_transfer_reply(call, skb);
1105 if (!last) {
1106 _leave(" = 0 [more]");
1107 return 0;
1108 }
1109
1110 if (call->reply_size != call->reply_max) {
1111 _leave(" = -EBADMSG [%u != %u]",
1112 call->reply_size, call->reply_max);
1113 return -EBADMSG;
1114 }
1115
1116 /* unmarshall the reply once we've received all of it */
1117 bp = call->buffer;
1118 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode,
1119 &call->store_version);
1120 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1121
1122 afs_pages_written_back(vnode, call);
1123
1124 _leave(" = 0 [done]");
1125 return 0;
1126}
1127
1128/*
1129 * FS.StoreData operation type
1130 */
1131static const struct afs_call_type afs_RXFSStoreData = {
1132 .name = "FS.StoreData",
1133 .deliver = afs_deliver_fs_store_data,
1134 .abort_to_error = afs_abort_to_error,
1135 .destructor = afs_flat_call_destructor,
1136};
1137
David Howellsb9b1f8d2007-05-10 03:15:21 -07001138static const struct afs_call_type afs_RXFSStoreData64 = {
1139 .name = "FS.StoreData64",
1140 .deliver = afs_deliver_fs_store_data,
1141 .abort_to_error = afs_abort_to_error,
1142 .destructor = afs_flat_call_destructor,
1143};
1144
1145/*
1146 * store a set of pages to a very large file
1147 */
1148static int afs_fs_store_data64(struct afs_server *server,
1149 struct afs_writeback *wb,
1150 pgoff_t first, pgoff_t last,
1151 unsigned offset, unsigned to,
1152 loff_t size, loff_t pos, loff_t i_size,
1153 const struct afs_wait_mode *wait_mode)
1154{
1155 struct afs_vnode *vnode = wb->vnode;
1156 struct afs_call *call;
1157 __be32 *bp;
1158
1159 _enter(",%x,{%x:%u},,",
1160 key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1161
1162 call = afs_alloc_flat_call(&afs_RXFSStoreData64,
1163 (4 + 6 + 3 * 2) * 4,
1164 (21 + 6) * 4);
1165 if (!call)
1166 return -ENOMEM;
1167
1168 call->wb = wb;
1169 call->key = wb->key;
1170 call->reply = vnode;
1171 call->service_id = FS_SERVICE;
1172 call->port = htons(AFS_FS_PORT);
1173 call->mapping = vnode->vfs_inode.i_mapping;
1174 call->first = first;
1175 call->last = last;
1176 call->first_offset = offset;
1177 call->last_to = to;
1178 call->send_pages = true;
1179 call->store_version = vnode->status.data_version + 1;
1180
1181 /* marshall the parameters */
1182 bp = call->request;
1183 *bp++ = htonl(FSSTOREDATA64);
1184 *bp++ = htonl(vnode->fid.vid);
1185 *bp++ = htonl(vnode->fid.vnode);
1186 *bp++ = htonl(vnode->fid.unique);
1187
1188 *bp++ = 0; /* mask */
1189 *bp++ = 0; /* mtime */
1190 *bp++ = 0; /* owner */
1191 *bp++ = 0; /* group */
1192 *bp++ = 0; /* unix mode */
1193 *bp++ = 0; /* segment size */
1194
1195 *bp++ = htonl(pos >> 32);
1196 *bp++ = htonl((u32) pos);
1197 *bp++ = htonl(size >> 32);
1198 *bp++ = htonl((u32) size);
1199 *bp++ = htonl(i_size >> 32);
1200 *bp++ = htonl((u32) i_size);
1201
1202 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1203}
1204
David Howells31143d52007-05-09 02:33:46 -07001205/*
1206 * store a set of pages
1207 */
1208int afs_fs_store_data(struct afs_server *server, struct afs_writeback *wb,
1209 pgoff_t first, pgoff_t last,
1210 unsigned offset, unsigned to,
1211 const struct afs_wait_mode *wait_mode)
1212{
1213 struct afs_vnode *vnode = wb->vnode;
1214 struct afs_call *call;
1215 loff_t size, pos, i_size;
1216 __be32 *bp;
1217
1218 _enter(",%x,{%x:%u},,",
1219 key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1220
1221 size = to - offset;
1222 if (first != last)
1223 size += (loff_t)(last - first) << PAGE_SHIFT;
1224 pos = (loff_t)first << PAGE_SHIFT;
1225 pos += offset;
1226
1227 i_size = i_size_read(&vnode->vfs_inode);
1228 if (pos + size > i_size)
1229 i_size = size + pos;
1230
1231 _debug("size %llx, at %llx, i_size %llx",
1232 (unsigned long long) size, (unsigned long long) pos,
1233 (unsigned long long) i_size);
1234
David Howellsb9b1f8d2007-05-10 03:15:21 -07001235 if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
1236 return afs_fs_store_data64(server, wb, first, last, offset, to,
1237 size, pos, i_size, wait_mode);
David Howells31143d52007-05-09 02:33:46 -07001238
1239 call = afs_alloc_flat_call(&afs_RXFSStoreData,
1240 (4 + 6 + 3) * 4,
1241 (21 + 6) * 4);
1242 if (!call)
1243 return -ENOMEM;
1244
1245 call->wb = wb;
1246 call->key = wb->key;
1247 call->reply = vnode;
1248 call->service_id = FS_SERVICE;
1249 call->port = htons(AFS_FS_PORT);
1250 call->mapping = vnode->vfs_inode.i_mapping;
1251 call->first = first;
1252 call->last = last;
1253 call->first_offset = offset;
1254 call->last_to = to;
1255 call->send_pages = true;
1256 call->store_version = vnode->status.data_version + 1;
1257
1258 /* marshall the parameters */
1259 bp = call->request;
1260 *bp++ = htonl(FSSTOREDATA);
1261 *bp++ = htonl(vnode->fid.vid);
1262 *bp++ = htonl(vnode->fid.vnode);
1263 *bp++ = htonl(vnode->fid.unique);
1264
1265 *bp++ = 0; /* mask */
1266 *bp++ = 0; /* mtime */
1267 *bp++ = 0; /* owner */
1268 *bp++ = 0; /* group */
1269 *bp++ = 0; /* unix mode */
1270 *bp++ = 0; /* segment size */
1271
1272 *bp++ = htonl(pos);
1273 *bp++ = htonl(size);
1274 *bp++ = htonl(i_size);
1275
1276 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1277}
1278
1279/*
1280 * deliver reply data to an FS.StoreStatus
1281 */
1282static int afs_deliver_fs_store_status(struct afs_call *call,
1283 struct sk_buff *skb, bool last)
1284{
1285 afs_dataversion_t *store_version;
1286 struct afs_vnode *vnode = call->reply;
1287 const __be32 *bp;
1288
1289 _enter(",,%u", last);
1290
1291 afs_transfer_reply(call, skb);
1292 if (!last) {
1293 _leave(" = 0 [more]");
1294 return 0;
1295 }
1296
1297 if (call->reply_size != call->reply_max) {
1298 _leave(" = -EBADMSG [%u != %u]",
1299 call->reply_size, call->reply_max);
1300 return -EBADMSG;
1301 }
1302
1303 /* unmarshall the reply once we've received all of it */
1304 store_version = NULL;
1305 if (call->operation_ID == FSSTOREDATA)
1306 store_version = &call->store_version;
1307
1308 bp = call->buffer;
1309 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode, store_version);
1310 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1311
1312 _leave(" = 0 [done]");
1313 return 0;
1314}
1315
1316/*
1317 * FS.StoreStatus operation type
1318 */
1319static const struct afs_call_type afs_RXFSStoreStatus = {
1320 .name = "FS.StoreStatus",
1321 .deliver = afs_deliver_fs_store_status,
1322 .abort_to_error = afs_abort_to_error,
1323 .destructor = afs_flat_call_destructor,
1324};
1325
1326static const struct afs_call_type afs_RXFSStoreData_as_Status = {
1327 .name = "FS.StoreData",
1328 .deliver = afs_deliver_fs_store_status,
1329 .abort_to_error = afs_abort_to_error,
1330 .destructor = afs_flat_call_destructor,
1331};
1332
David Howellsb9b1f8d2007-05-10 03:15:21 -07001333static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
1334 .name = "FS.StoreData64",
1335 .deliver = afs_deliver_fs_store_status,
1336 .abort_to_error = afs_abort_to_error,
1337 .destructor = afs_flat_call_destructor,
1338};
1339
1340/*
1341 * set the attributes on a very large file, using FS.StoreData rather than
1342 * FS.StoreStatus so as to alter the file size also
1343 */
1344static int afs_fs_setattr_size64(struct afs_server *server, struct key *key,
1345 struct afs_vnode *vnode, struct iattr *attr,
1346 const struct afs_wait_mode *wait_mode)
1347{
1348 struct afs_call *call;
1349 __be32 *bp;
1350
1351 _enter(",%x,{%x:%u},,",
1352 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1353
1354 ASSERT(attr->ia_valid & ATTR_SIZE);
1355
1356 call = afs_alloc_flat_call(&afs_RXFSStoreData64_as_Status,
1357 (4 + 6 + 3 * 2) * 4,
1358 (21 + 6) * 4);
1359 if (!call)
1360 return -ENOMEM;
1361
1362 call->key = key;
1363 call->reply = vnode;
1364 call->service_id = FS_SERVICE;
1365 call->port = htons(AFS_FS_PORT);
1366 call->store_version = vnode->status.data_version + 1;
1367 call->operation_ID = FSSTOREDATA;
1368
1369 /* marshall the parameters */
1370 bp = call->request;
1371 *bp++ = htonl(FSSTOREDATA64);
1372 *bp++ = htonl(vnode->fid.vid);
1373 *bp++ = htonl(vnode->fid.vnode);
1374 *bp++ = htonl(vnode->fid.unique);
1375
1376 xdr_encode_AFS_StoreStatus(&bp, attr);
1377
1378 *bp++ = 0; /* position of start of write */
1379 *bp++ = 0;
1380 *bp++ = 0; /* size of write */
1381 *bp++ = 0;
1382 *bp++ = htonl(attr->ia_size >> 32); /* new file length */
1383 *bp++ = htonl((u32) attr->ia_size);
1384
1385 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1386}
1387
David Howells31143d52007-05-09 02:33:46 -07001388/*
1389 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1390 * so as to alter the file size also
1391 */
1392static int afs_fs_setattr_size(struct afs_server *server, struct key *key,
1393 struct afs_vnode *vnode, struct iattr *attr,
1394 const struct afs_wait_mode *wait_mode)
1395{
1396 struct afs_call *call;
1397 __be32 *bp;
1398
1399 _enter(",%x,{%x:%u},,",
1400 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1401
1402 ASSERT(attr->ia_valid & ATTR_SIZE);
David Howellsb9b1f8d2007-05-10 03:15:21 -07001403 if (attr->ia_size >> 32)
1404 return afs_fs_setattr_size64(server, key, vnode, attr,
1405 wait_mode);
David Howells31143d52007-05-09 02:33:46 -07001406
1407 call = afs_alloc_flat_call(&afs_RXFSStoreData_as_Status,
1408 (4 + 6 + 3) * 4,
1409 (21 + 6) * 4);
1410 if (!call)
1411 return -ENOMEM;
1412
1413 call->key = key;
1414 call->reply = vnode;
1415 call->service_id = FS_SERVICE;
1416 call->port = htons(AFS_FS_PORT);
1417 call->store_version = vnode->status.data_version + 1;
1418 call->operation_ID = FSSTOREDATA;
1419
1420 /* marshall the parameters */
1421 bp = call->request;
1422 *bp++ = htonl(FSSTOREDATA);
1423 *bp++ = htonl(vnode->fid.vid);
1424 *bp++ = htonl(vnode->fid.vnode);
1425 *bp++ = htonl(vnode->fid.unique);
1426
1427 xdr_encode_AFS_StoreStatus(&bp, attr);
1428
1429 *bp++ = 0; /* position of start of write */
1430 *bp++ = 0; /* size of write */
1431 *bp++ = htonl(attr->ia_size); /* new file length */
1432
1433 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1434}
1435
1436/*
1437 * set the attributes on a file, using FS.StoreData if there's a change in file
1438 * size, and FS.StoreStatus otherwise
1439 */
1440int afs_fs_setattr(struct afs_server *server, struct key *key,
1441 struct afs_vnode *vnode, struct iattr *attr,
1442 const struct afs_wait_mode *wait_mode)
1443{
1444 struct afs_call *call;
1445 __be32 *bp;
1446
1447 if (attr->ia_valid & ATTR_SIZE)
1448 return afs_fs_setattr_size(server, key, vnode, attr,
1449 wait_mode);
1450
1451 _enter(",%x,{%x:%u},,",
1452 key_serial(key), vnode->fid.vid, vnode->fid.vnode);
1453
1454 call = afs_alloc_flat_call(&afs_RXFSStoreStatus,
1455 (4 + 6) * 4,
1456 (21 + 6) * 4);
1457 if (!call)
1458 return -ENOMEM;
1459
1460 call->key = key;
1461 call->reply = vnode;
1462 call->service_id = FS_SERVICE;
1463 call->port = htons(AFS_FS_PORT);
1464 call->operation_ID = FSSTORESTATUS;
1465
1466 /* marshall the parameters */
1467 bp = call->request;
1468 *bp++ = htonl(FSSTORESTATUS);
1469 *bp++ = htonl(vnode->fid.vid);
1470 *bp++ = htonl(vnode->fid.vnode);
1471 *bp++ = htonl(vnode->fid.unique);
1472
1473 xdr_encode_AFS_StoreStatus(&bp, attr);
1474
1475 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1476}
David Howells45222b92007-05-10 22:22:20 -07001477
1478/*
1479 * deliver reply data to an FS.GetVolumeStatus
1480 */
1481static int afs_deliver_fs_get_volume_status(struct afs_call *call,
1482 struct sk_buff *skb, bool last)
1483{
1484 const __be32 *bp;
1485 char *p;
1486 int ret;
1487
1488 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
1489
1490 switch (call->unmarshall) {
1491 case 0:
1492 call->offset = 0;
1493 call->unmarshall++;
1494
1495 /* extract the returned status record */
1496 case 1:
1497 _debug("extract status");
1498 ret = afs_extract_data(call, skb, last, call->buffer,
1499 12 * 4);
1500 switch (ret) {
1501 case 0: break;
1502 case -EAGAIN: return 0;
1503 default: return ret;
1504 }
1505
1506 bp = call->buffer;
1507 xdr_decode_AFSFetchVolumeStatus(&bp, call->reply2);
1508 call->offset = 0;
1509 call->unmarshall++;
1510
1511 /* extract the volume name length */
1512 case 2:
1513 ret = afs_extract_data(call, skb, last, &call->tmp, 4);
1514 switch (ret) {
1515 case 0: break;
1516 case -EAGAIN: return 0;
1517 default: return ret;
1518 }
1519
1520 call->count = ntohl(call->tmp);
1521 _debug("volname length: %u", call->count);
1522 if (call->count >= AFSNAMEMAX)
1523 return -EBADMSG;
1524 call->offset = 0;
1525 call->unmarshall++;
1526
1527 /* extract the volume name */
1528 case 3:
1529 _debug("extract volname");
1530 if (call->count > 0) {
1531 ret = afs_extract_data(call, skb, last, call->reply3,
1532 call->count);
1533 switch (ret) {
1534 case 0: break;
1535 case -EAGAIN: return 0;
1536 default: return ret;
1537 }
1538 }
1539
1540 p = call->reply3;
1541 p[call->count] = 0;
1542 _debug("volname '%s'", p);
1543
1544 call->offset = 0;
1545 call->unmarshall++;
1546
1547 /* extract the volume name padding */
1548 if ((call->count & 3) == 0) {
1549 call->unmarshall++;
1550 goto no_volname_padding;
1551 }
1552 call->count = 4 - (call->count & 3);
1553
1554 case 4:
1555 ret = afs_extract_data(call, skb, last, call->buffer,
1556 call->count);
1557 switch (ret) {
1558 case 0: break;
1559 case -EAGAIN: return 0;
1560 default: return ret;
1561 }
1562
1563 call->offset = 0;
1564 call->unmarshall++;
1565 no_volname_padding:
1566
1567 /* extract the offline message length */
1568 case 5:
1569 ret = afs_extract_data(call, skb, last, &call->tmp, 4);
1570 switch (ret) {
1571 case 0: break;
1572 case -EAGAIN: return 0;
1573 default: return ret;
1574 }
1575
1576 call->count = ntohl(call->tmp);
1577 _debug("offline msg length: %u", call->count);
1578 if (call->count >= AFSNAMEMAX)
1579 return -EBADMSG;
1580 call->offset = 0;
1581 call->unmarshall++;
1582
1583 /* extract the offline message */
1584 case 6:
1585 _debug("extract offline");
1586 if (call->count > 0) {
1587 ret = afs_extract_data(call, skb, last, call->reply3,
1588 call->count);
1589 switch (ret) {
1590 case 0: break;
1591 case -EAGAIN: return 0;
1592 default: return ret;
1593 }
1594 }
1595
1596 p = call->reply3;
1597 p[call->count] = 0;
1598 _debug("offline '%s'", p);
1599
1600 call->offset = 0;
1601 call->unmarshall++;
1602
1603 /* extract the offline message padding */
1604 if ((call->count & 3) == 0) {
1605 call->unmarshall++;
1606 goto no_offline_padding;
1607 }
1608 call->count = 4 - (call->count & 3);
1609
1610 case 7:
1611 ret = afs_extract_data(call, skb, last, call->buffer,
1612 call->count);
1613 switch (ret) {
1614 case 0: break;
1615 case -EAGAIN: return 0;
1616 default: return ret;
1617 }
1618
1619 call->offset = 0;
1620 call->unmarshall++;
1621 no_offline_padding:
1622
1623 /* extract the message of the day length */
1624 case 8:
1625 ret = afs_extract_data(call, skb, last, &call->tmp, 4);
1626 switch (ret) {
1627 case 0: break;
1628 case -EAGAIN: return 0;
1629 default: return ret;
1630 }
1631
1632 call->count = ntohl(call->tmp);
1633 _debug("motd length: %u", call->count);
1634 if (call->count >= AFSNAMEMAX)
1635 return -EBADMSG;
1636 call->offset = 0;
1637 call->unmarshall++;
1638
1639 /* extract the message of the day */
1640 case 9:
1641 _debug("extract motd");
1642 if (call->count > 0) {
1643 ret = afs_extract_data(call, skb, last, call->reply3,
1644 call->count);
1645 switch (ret) {
1646 case 0: break;
1647 case -EAGAIN: return 0;
1648 default: return ret;
1649 }
1650 }
1651
1652 p = call->reply3;
1653 p[call->count] = 0;
1654 _debug("motd '%s'", p);
1655
1656 call->offset = 0;
1657 call->unmarshall++;
1658
1659 /* extract the message of the day padding */
1660 if ((call->count & 3) == 0) {
1661 call->unmarshall++;
1662 goto no_motd_padding;
1663 }
1664 call->count = 4 - (call->count & 3);
1665
1666 case 10:
1667 ret = afs_extract_data(call, skb, last, call->buffer,
1668 call->count);
1669 switch (ret) {
1670 case 0: break;
1671 case -EAGAIN: return 0;
1672 default: return ret;
1673 }
1674
1675 call->offset = 0;
1676 call->unmarshall++;
1677 no_motd_padding:
1678
1679 case 11:
1680 _debug("trailer %d", skb->len);
1681 if (skb->len != 0)
1682 return -EBADMSG;
1683 break;
1684 }
1685
1686 if (!last)
1687 return 0;
1688
1689 _leave(" = 0 [done]");
1690 return 0;
1691}
1692
1693/*
1694 * destroy an FS.GetVolumeStatus call
1695 */
1696static void afs_get_volume_status_call_destructor(struct afs_call *call)
1697{
1698 kfree(call->reply3);
1699 call->reply3 = NULL;
1700 afs_flat_call_destructor(call);
1701}
1702
1703/*
1704 * FS.GetVolumeStatus operation type
1705 */
1706static const struct afs_call_type afs_RXFSGetVolumeStatus = {
1707 .name = "FS.GetVolumeStatus",
1708 .deliver = afs_deliver_fs_get_volume_status,
1709 .abort_to_error = afs_abort_to_error,
1710 .destructor = afs_get_volume_status_call_destructor,
1711};
1712
1713/*
1714 * fetch the status of a volume
1715 */
1716int afs_fs_get_volume_status(struct afs_server *server,
1717 struct key *key,
1718 struct afs_vnode *vnode,
1719 struct afs_volume_status *vs,
1720 const struct afs_wait_mode *wait_mode)
1721{
1722 struct afs_call *call;
1723 __be32 *bp;
1724 void *tmpbuf;
1725
1726 _enter("");
1727
1728 tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
1729 if (!tmpbuf)
1730 return -ENOMEM;
1731
1732 call = afs_alloc_flat_call(&afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
1733 if (!call) {
1734 kfree(tmpbuf);
1735 return -ENOMEM;
1736 }
1737
1738 call->key = key;
1739 call->reply = vnode;
1740 call->reply2 = vs;
1741 call->reply3 = tmpbuf;
1742 call->service_id = FS_SERVICE;
1743 call->port = htons(AFS_FS_PORT);
1744
1745 /* marshall the parameters */
1746 bp = call->request;
1747 bp[0] = htonl(FSGETVOLUMESTATUS);
1748 bp[1] = htonl(vnode->fid.vid);
1749
1750 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1751}
David Howellse8d6c552007-07-15 23:40:12 -07001752
1753/*
1754 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1755 */
1756static int afs_deliver_fs_xxxx_lock(struct afs_call *call,
1757 struct sk_buff *skb, bool last)
1758{
1759 const __be32 *bp;
1760
1761 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
1762
1763 afs_transfer_reply(call, skb);
1764 if (!last)
1765 return 0;
1766
1767 if (call->reply_size != call->reply_max)
1768 return -EBADMSG;
1769
1770 /* unmarshall the reply once we've received all of it */
1771 bp = call->buffer;
1772 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1773
1774 _leave(" = 0 [done]");
1775 return 0;
1776}
1777
1778/*
1779 * FS.SetLock operation type
1780 */
1781static const struct afs_call_type afs_RXFSSetLock = {
1782 .name = "FS.SetLock",
1783 .deliver = afs_deliver_fs_xxxx_lock,
1784 .abort_to_error = afs_abort_to_error,
1785 .destructor = afs_flat_call_destructor,
1786};
1787
1788/*
1789 * FS.ExtendLock operation type
1790 */
1791static const struct afs_call_type afs_RXFSExtendLock = {
1792 .name = "FS.ExtendLock",
1793 .deliver = afs_deliver_fs_xxxx_lock,
1794 .abort_to_error = afs_abort_to_error,
1795 .destructor = afs_flat_call_destructor,
1796};
1797
1798/*
1799 * FS.ReleaseLock operation type
1800 */
1801static const struct afs_call_type afs_RXFSReleaseLock = {
1802 .name = "FS.ReleaseLock",
1803 .deliver = afs_deliver_fs_xxxx_lock,
1804 .abort_to_error = afs_abort_to_error,
1805 .destructor = afs_flat_call_destructor,
1806};
1807
1808/*
1809 * get a lock on a file
1810 */
1811int afs_fs_set_lock(struct afs_server *server,
1812 struct key *key,
1813 struct afs_vnode *vnode,
1814 afs_lock_type_t type,
1815 const struct afs_wait_mode *wait_mode)
1816{
1817 struct afs_call *call;
1818 __be32 *bp;
1819
1820 _enter("");
1821
1822 call = afs_alloc_flat_call(&afs_RXFSSetLock, 5 * 4, 6 * 4);
1823 if (!call)
1824 return -ENOMEM;
1825
1826 call->key = key;
1827 call->reply = vnode;
1828 call->service_id = FS_SERVICE;
1829 call->port = htons(AFS_FS_PORT);
1830
1831 /* marshall the parameters */
1832 bp = call->request;
1833 *bp++ = htonl(FSSETLOCK);
1834 *bp++ = htonl(vnode->fid.vid);
1835 *bp++ = htonl(vnode->fid.vnode);
1836 *bp++ = htonl(vnode->fid.unique);
1837 *bp++ = htonl(type);
1838
1839 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1840}
1841
1842/*
1843 * extend a lock on a file
1844 */
1845int afs_fs_extend_lock(struct afs_server *server,
1846 struct key *key,
1847 struct afs_vnode *vnode,
1848 const struct afs_wait_mode *wait_mode)
1849{
1850 struct afs_call *call;
1851 __be32 *bp;
1852
1853 _enter("");
1854
1855 call = afs_alloc_flat_call(&afs_RXFSExtendLock, 4 * 4, 6 * 4);
1856 if (!call)
1857 return -ENOMEM;
1858
1859 call->key = key;
1860 call->reply = vnode;
1861 call->service_id = FS_SERVICE;
1862 call->port = htons(AFS_FS_PORT);
1863
1864 /* marshall the parameters */
1865 bp = call->request;
1866 *bp++ = htonl(FSEXTENDLOCK);
1867 *bp++ = htonl(vnode->fid.vid);
1868 *bp++ = htonl(vnode->fid.vnode);
1869 *bp++ = htonl(vnode->fid.unique);
1870
1871 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1872}
1873
1874/*
1875 * release a lock on a file
1876 */
1877int afs_fs_release_lock(struct afs_server *server,
1878 struct key *key,
1879 struct afs_vnode *vnode,
1880 const struct afs_wait_mode *wait_mode)
1881{
1882 struct afs_call *call;
1883 __be32 *bp;
1884
1885 _enter("");
1886
1887 call = afs_alloc_flat_call(&afs_RXFSReleaseLock, 4 * 4, 6 * 4);
1888 if (!call)
1889 return -ENOMEM;
1890
1891 call->key = key;
1892 call->reply = vnode;
1893 call->service_id = FS_SERVICE;
1894 call->port = htons(AFS_FS_PORT);
1895
1896 /* marshall the parameters */
1897 bp = call->request;
1898 *bp++ = htonl(FSRELEASELOCK);
1899 *bp++ = htonl(vnode->fid.vid);
1900 *bp++ = htonl(vnode->fid.vnode);
1901 *bp++ = htonl(vnode->fid.unique);
1902
1903 return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
1904}