1 /* AFS File Server client stubs
3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/init.h>
13 #include <linux/slab.h>
14 #include <linux/sched.h>
15 #include <linux/circ_buf.h>
20 * decode an AFSFid block
22 static void xdr_decode_AFSFid(const __be32
**_bp
, struct afs_fid
*fid
)
24 const __be32
*bp
= *_bp
;
26 fid
->vid
= ntohl(*bp
++);
27 fid
->vnode
= ntohl(*bp
++);
28 fid
->unique
= ntohl(*bp
++);
33 * decode an AFSFetchStatus block
35 static void xdr_decode_AFSFetchStatus(const __be32
**_bp
,
36 struct afs_file_status
*status
,
37 struct afs_vnode
*vnode
,
38 afs_dataversion_t
*store_version
)
40 afs_dataversion_t expected_version
;
41 const __be32
*bp
= *_bp
;
43 u64 data_version
, size
;
44 u32 changed
= 0; /* becomes non-zero if ctime-type changes seen */
48 #define EXTRACT(DST) \
50 u32 x = ntohl(*bp++); \
55 status
->if_version
= ntohl(*bp
++);
56 EXTRACT(status
->type
);
57 EXTRACT(status
->nlink
);
59 data_version
= ntohl(*bp
++);
60 EXTRACT(status
->author
);
61 owner
= make_kuid(&init_user_ns
, ntohl(*bp
++));
62 changed
|= !uid_eq(owner
, status
->owner
);
63 status
->owner
= owner
;
64 EXTRACT(status
->caller_access
); /* call ticket dependent */
65 EXTRACT(status
->anon_access
);
66 EXTRACT(status
->mode
);
67 EXTRACT(status
->parent
.vnode
);
68 EXTRACT(status
->parent
.unique
);
70 status
->mtime_client
= ntohl(*bp
++);
71 status
->mtime_server
= ntohl(*bp
++);
72 group
= make_kgid(&init_user_ns
, ntohl(*bp
++));
73 changed
|= !gid_eq(group
, status
->group
);
74 status
->group
= group
;
75 bp
++; /* sync counter */
76 data_version
|= (u64
) ntohl(*bp
++) << 32;
77 EXTRACT(status
->lock_count
);
78 size
|= (u64
) ntohl(*bp
++) << 32;
82 if (size
!= status
->size
) {
86 status
->mode
&= S_IALLUGO
;
88 _debug("vnode time %lx, %lx",
89 status
->mtime_client
, status
->mtime_server
);
92 status
->parent
.vid
= vnode
->fid
.vid
;
93 if (changed
&& !test_bit(AFS_VNODE_UNSET
, &vnode
->flags
)) {
94 _debug("vnode changed");
95 i_size_write(&vnode
->vfs_inode
, size
);
96 vnode
->vfs_inode
.i_uid
= status
->owner
;
97 vnode
->vfs_inode
.i_gid
= status
->group
;
98 vnode
->vfs_inode
.i_generation
= vnode
->fid
.unique
;
99 set_nlink(&vnode
->vfs_inode
, status
->nlink
);
101 mode
= vnode
->vfs_inode
.i_mode
;
103 mode
|= status
->mode
;
105 vnode
->vfs_inode
.i_mode
= mode
;
108 vnode
->vfs_inode
.i_ctime
.tv_sec
= status
->mtime_server
;
109 vnode
->vfs_inode
.i_mtime
= vnode
->vfs_inode
.i_ctime
;
110 vnode
->vfs_inode
.i_atime
= vnode
->vfs_inode
.i_ctime
;
111 vnode
->vfs_inode
.i_version
= data_version
;
114 expected_version
= status
->data_version
;
116 expected_version
= *store_version
;
118 if (expected_version
!= data_version
) {
119 status
->data_version
= data_version
;
120 if (vnode
&& !test_bit(AFS_VNODE_UNSET
, &vnode
->flags
)) {
121 _debug("vnode modified %llx on {%x:%u}",
122 (unsigned long long) data_version
,
123 vnode
->fid
.vid
, vnode
->fid
.vnode
);
124 set_bit(AFS_VNODE_MODIFIED
, &vnode
->flags
);
125 set_bit(AFS_VNODE_ZAP_DATA
, &vnode
->flags
);
127 } else if (store_version
) {
128 status
->data_version
= data_version
;
133 * decode an AFSCallBack block
135 static void xdr_decode_AFSCallBack(const __be32
**_bp
, struct afs_vnode
*vnode
)
137 const __be32
*bp
= *_bp
;
139 vnode
->cb_version
= ntohl(*bp
++);
140 vnode
->cb_expiry
= ntohl(*bp
++);
141 vnode
->cb_type
= ntohl(*bp
++);
142 vnode
->cb_expires
= vnode
->cb_expiry
+ get_seconds();
146 static void xdr_decode_AFSCallBack_raw(const __be32
**_bp
,
147 struct afs_callback
*cb
)
149 const __be32
*bp
= *_bp
;
151 cb
->version
= ntohl(*bp
++);
152 cb
->expiry
= ntohl(*bp
++);
153 cb
->type
= ntohl(*bp
++);
158 * decode an AFSVolSync block
160 static void xdr_decode_AFSVolSync(const __be32
**_bp
,
161 struct afs_volsync
*volsync
)
163 const __be32
*bp
= *_bp
;
165 volsync
->creation
= ntohl(*bp
++);
175 * encode the requested attributes into an AFSStoreStatus block
177 static void xdr_encode_AFS_StoreStatus(__be32
**_bp
, struct iattr
*attr
)
180 u32 mask
= 0, mtime
= 0, owner
= 0, group
= 0, mode
= 0;
183 if (attr
->ia_valid
& ATTR_MTIME
) {
184 mask
|= AFS_SET_MTIME
;
185 mtime
= attr
->ia_mtime
.tv_sec
;
188 if (attr
->ia_valid
& ATTR_UID
) {
189 mask
|= AFS_SET_OWNER
;
190 owner
= from_kuid(&init_user_ns
, attr
->ia_uid
);
193 if (attr
->ia_valid
& ATTR_GID
) {
194 mask
|= AFS_SET_GROUP
;
195 group
= from_kgid(&init_user_ns
, attr
->ia_gid
);
198 if (attr
->ia_valid
& ATTR_MODE
) {
199 mask
|= AFS_SET_MODE
;
200 mode
= attr
->ia_mode
& S_IALLUGO
;
204 *bp
++ = htonl(mtime
);
205 *bp
++ = htonl(owner
);
206 *bp
++ = htonl(group
);
208 *bp
++ = 0; /* segment size */
213 * decode an AFSFetchVolumeStatus block
215 static void xdr_decode_AFSFetchVolumeStatus(const __be32
**_bp
,
216 struct afs_volume_status
*vs
)
218 const __be32
*bp
= *_bp
;
220 vs
->vid
= ntohl(*bp
++);
221 vs
->parent_id
= ntohl(*bp
++);
222 vs
->online
= ntohl(*bp
++);
223 vs
->in_service
= ntohl(*bp
++);
224 vs
->blessed
= ntohl(*bp
++);
225 vs
->needs_salvage
= ntohl(*bp
++);
226 vs
->type
= ntohl(*bp
++);
227 vs
->min_quota
= ntohl(*bp
++);
228 vs
->max_quota
= ntohl(*bp
++);
229 vs
->blocks_in_use
= ntohl(*bp
++);
230 vs
->part_blocks_avail
= ntohl(*bp
++);
231 vs
->part_max_blocks
= ntohl(*bp
++);
236 * deliver reply data to an FS.FetchStatus
238 static int afs_deliver_fs_fetch_status(struct afs_call
*call
)
240 struct afs_vnode
*vnode
= call
->reply
;
246 ret
= afs_transfer_reply(call
);
250 /* unmarshall the reply once we've received all of it */
252 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
, NULL
);
253 xdr_decode_AFSCallBack(&bp
, vnode
);
255 xdr_decode_AFSVolSync(&bp
, call
->reply2
);
257 _leave(" = 0 [done]");
262 * FS.FetchStatus operation type
264 static const struct afs_call_type afs_RXFSFetchStatus
= {
265 .name
= "FS.FetchStatus",
266 .deliver
= afs_deliver_fs_fetch_status
,
267 .abort_to_error
= afs_abort_to_error
,
268 .destructor
= afs_flat_call_destructor
,
272 * fetch the status information for a file
274 int afs_fs_fetch_file_status(struct afs_server
*server
,
276 struct afs_vnode
*vnode
,
277 struct afs_volsync
*volsync
,
280 struct afs_call
*call
;
283 _enter(",%x,{%x:%u},,",
284 key_serial(key
), vnode
->fid
.vid
, vnode
->fid
.vnode
);
286 call
= afs_alloc_flat_call(&afs_RXFSFetchStatus
, 16, (21 + 3 + 6) * 4);
292 call
->reply2
= volsync
;
293 call
->service_id
= FS_SERVICE
;
294 call
->port
= htons(AFS_FS_PORT
);
296 /* marshall the parameters */
298 bp
[0] = htonl(FSFETCHSTATUS
);
299 bp
[1] = htonl(vnode
->fid
.vid
);
300 bp
[2] = htonl(vnode
->fid
.vnode
);
301 bp
[3] = htonl(vnode
->fid
.unique
);
303 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
307 * deliver reply data to an FS.FetchData
309 static int afs_deliver_fs_fetch_data(struct afs_call
*call
)
311 struct afs_vnode
*vnode
= call
->reply
;
312 struct afs_read
*req
= call
->reply3
;
318 _enter("{%u,%zu/%u;%u/%llu}",
319 call
->unmarshall
, call
->offset
, call
->count
,
320 req
->remain
, req
->actual_len
);
322 switch (call
->unmarshall
) {
327 if (call
->operation_ID
!= FSFETCHDATA64
) {
332 /* extract the upper part of the returned data length of an
333 * FSFETCHDATA64 op (which should always be 0 using this
336 _debug("extract data length (MSW)");
337 ret
= afs_extract_data(call
, &call
->tmp
, 4, true);
341 req
->actual_len
= ntohl(call
->tmp
);
342 req
->actual_len
<<= 32;
347 /* extract the returned data length */
349 _debug("extract data length");
350 ret
= afs_extract_data(call
, &call
->tmp
, 4, true);
354 req
->actual_len
|= ntohl(call
->tmp
);
355 _debug("DATA length: %llu", req
->actual_len
);
356 /* Check that the server didn't want to send us extra. We
357 * might want to just discard instead, but that requires
358 * cooperation from AF_RXRPC.
360 if (req
->actual_len
> req
->len
)
363 req
->remain
= req
->actual_len
;
364 call
->offset
= req
->pos
& (PAGE_SIZE
- 1);
366 if (req
->actual_len
== 0)
371 if (req
->remain
> PAGE_SIZE
- call
->offset
)
372 size
= PAGE_SIZE
- call
->offset
;
375 call
->count
= call
->offset
+ size
;
376 ASSERTCMP(call
->count
, <=, PAGE_SIZE
);
379 /* extract the returned data */
381 _debug("extract data %u/%llu %zu/%u",
382 req
->remain
, req
->actual_len
, call
->offset
, call
->count
);
384 buffer
= kmap(req
->pages
[req
->index
]);
385 ret
= afs_extract_data(call
, buffer
, call
->count
, true);
386 kunmap(req
->pages
[req
->index
]);
389 if (call
->offset
== PAGE_SIZE
) {
391 req
->page_done(call
, req
);
392 if (req
->remain
> 0) {
403 /* extract the metadata */
405 ret
= afs_extract_data(call
, call
->buffer
,
406 (21 + 3 + 6) * 4, false);
411 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
, NULL
);
412 xdr_decode_AFSCallBack(&bp
, vnode
);
414 xdr_decode_AFSVolSync(&bp
, call
->reply2
);
423 if (call
->count
< PAGE_SIZE
) {
424 buffer
= kmap(req
->pages
[req
->index
]);
425 memset(buffer
+ call
->count
, 0, PAGE_SIZE
- call
->count
);
426 kunmap(req
->pages
[req
->index
]);
428 req
->page_done(call
, req
);
431 _leave(" = 0 [done]");
435 static void afs_fetch_data_destructor(struct afs_call
*call
)
437 struct afs_read
*req
= call
->reply3
;
440 afs_flat_call_destructor(call
);
444 * FS.FetchData operation type
446 static const struct afs_call_type afs_RXFSFetchData
= {
447 .name
= "FS.FetchData",
448 .deliver
= afs_deliver_fs_fetch_data
,
449 .abort_to_error
= afs_abort_to_error
,
450 .destructor
= afs_fetch_data_destructor
,
453 static const struct afs_call_type afs_RXFSFetchData64
= {
454 .name
= "FS.FetchData64",
455 .deliver
= afs_deliver_fs_fetch_data
,
456 .abort_to_error
= afs_abort_to_error
,
457 .destructor
= afs_fetch_data_destructor
,
461 * fetch data from a very large file
463 static int afs_fs_fetch_data64(struct afs_server
*server
,
465 struct afs_vnode
*vnode
,
466 struct afs_read
*req
,
469 struct afs_call
*call
;
474 call
= afs_alloc_flat_call(&afs_RXFSFetchData64
, 32, (21 + 3 + 6) * 4);
480 call
->reply2
= NULL
; /* volsync */
482 call
->service_id
= FS_SERVICE
;
483 call
->port
= htons(AFS_FS_PORT
);
484 call
->operation_ID
= FSFETCHDATA64
;
486 /* marshall the parameters */
488 bp
[0] = htonl(FSFETCHDATA64
);
489 bp
[1] = htonl(vnode
->fid
.vid
);
490 bp
[2] = htonl(vnode
->fid
.vnode
);
491 bp
[3] = htonl(vnode
->fid
.unique
);
492 bp
[4] = htonl(upper_32_bits(req
->pos
));
493 bp
[5] = htonl(lower_32_bits(req
->pos
));
495 bp
[7] = htonl(lower_32_bits(req
->len
));
497 atomic_inc(&req
->usage
);
498 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
502 * fetch data from a file
504 int afs_fs_fetch_data(struct afs_server
*server
,
506 struct afs_vnode
*vnode
,
507 struct afs_read
*req
,
510 struct afs_call
*call
;
513 if (upper_32_bits(req
->pos
) ||
514 upper_32_bits(req
->len
) ||
515 upper_32_bits(req
->pos
+ req
->len
))
516 return afs_fs_fetch_data64(server
, key
, vnode
, req
, async
);
520 call
= afs_alloc_flat_call(&afs_RXFSFetchData
, 24, (21 + 3 + 6) * 4);
526 call
->reply2
= NULL
; /* volsync */
528 call
->service_id
= FS_SERVICE
;
529 call
->port
= htons(AFS_FS_PORT
);
530 call
->operation_ID
= FSFETCHDATA
;
532 /* marshall the parameters */
534 bp
[0] = htonl(FSFETCHDATA
);
535 bp
[1] = htonl(vnode
->fid
.vid
);
536 bp
[2] = htonl(vnode
->fid
.vnode
);
537 bp
[3] = htonl(vnode
->fid
.unique
);
538 bp
[4] = htonl(lower_32_bits(req
->pos
));
539 bp
[5] = htonl(lower_32_bits(req
->len
));
541 atomic_inc(&req
->usage
);
542 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
546 * deliver reply data to an FS.GiveUpCallBacks
548 static int afs_deliver_fs_give_up_callbacks(struct afs_call
*call
)
552 /* shouldn't be any reply data */
553 return afs_extract_data(call
, NULL
, 0, false);
557 * FS.GiveUpCallBacks operation type
559 static const struct afs_call_type afs_RXFSGiveUpCallBacks
= {
560 .name
= "FS.GiveUpCallBacks",
561 .deliver
= afs_deliver_fs_give_up_callbacks
,
562 .abort_to_error
= afs_abort_to_error
,
563 .destructor
= afs_flat_call_destructor
,
567 * give up a set of callbacks
568 * - the callbacks are held in the server->cb_break ring
570 int afs_fs_give_up_callbacks(struct afs_server
*server
,
573 struct afs_call
*call
;
578 ncallbacks
= CIRC_CNT(server
->cb_break_head
, server
->cb_break_tail
,
579 ARRAY_SIZE(server
->cb_break
));
581 _enter("{%zu},", ncallbacks
);
585 if (ncallbacks
> AFSCBMAX
)
586 ncallbacks
= AFSCBMAX
;
588 _debug("break %zu callbacks", ncallbacks
);
590 call
= afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks
,
591 12 + ncallbacks
* 6 * 4, 0);
595 call
->service_id
= FS_SERVICE
;
596 call
->port
= htons(AFS_FS_PORT
);
598 /* marshall the parameters */
600 tp
= bp
+ 2 + ncallbacks
* 3;
601 *bp
++ = htonl(FSGIVEUPCALLBACKS
);
602 *bp
++ = htonl(ncallbacks
);
603 *tp
++ = htonl(ncallbacks
);
605 atomic_sub(ncallbacks
, &server
->cb_break_n
);
606 for (loop
= ncallbacks
; loop
> 0; loop
--) {
607 struct afs_callback
*cb
=
608 &server
->cb_break
[server
->cb_break_tail
];
610 *bp
++ = htonl(cb
->fid
.vid
);
611 *bp
++ = htonl(cb
->fid
.vnode
);
612 *bp
++ = htonl(cb
->fid
.unique
);
613 *tp
++ = htonl(cb
->version
);
614 *tp
++ = htonl(cb
->expiry
);
615 *tp
++ = htonl(cb
->type
);
617 server
->cb_break_tail
=
618 (server
->cb_break_tail
+ 1) &
619 (ARRAY_SIZE(server
->cb_break
) - 1);
622 ASSERT(ncallbacks
> 0);
623 wake_up_nr(&server
->cb_break_waitq
, ncallbacks
);
625 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
629 * deliver reply data to an FS.CreateFile or an FS.MakeDir
631 static int afs_deliver_fs_create_vnode(struct afs_call
*call
)
633 struct afs_vnode
*vnode
= call
->reply
;
637 _enter("{%u}", call
->unmarshall
);
639 ret
= afs_transfer_reply(call
);
643 /* unmarshall the reply once we've received all of it */
645 xdr_decode_AFSFid(&bp
, call
->reply2
);
646 xdr_decode_AFSFetchStatus(&bp
, call
->reply3
, NULL
, NULL
);
647 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
, NULL
);
648 xdr_decode_AFSCallBack_raw(&bp
, call
->reply4
);
649 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
651 _leave(" = 0 [done]");
656 * FS.CreateFile and FS.MakeDir operation type
658 static const struct afs_call_type afs_RXFSCreateXXXX
= {
659 .name
= "FS.CreateXXXX",
660 .deliver
= afs_deliver_fs_create_vnode
,
661 .abort_to_error
= afs_abort_to_error
,
662 .destructor
= afs_flat_call_destructor
,
666 * create a file or make a directory
668 int afs_fs_create(struct afs_server
*server
,
670 struct afs_vnode
*vnode
,
673 struct afs_fid
*newfid
,
674 struct afs_file_status
*newstatus
,
675 struct afs_callback
*newcb
,
678 struct afs_call
*call
;
679 size_t namesz
, reqsz
, padsz
;
684 namesz
= strlen(name
);
685 padsz
= (4 - (namesz
& 3)) & 3;
686 reqsz
= (5 * 4) + namesz
+ padsz
+ (6 * 4);
688 call
= afs_alloc_flat_call(&afs_RXFSCreateXXXX
, reqsz
,
689 (3 + 21 + 21 + 3 + 6) * 4);
695 call
->reply2
= newfid
;
696 call
->reply3
= newstatus
;
697 call
->reply4
= newcb
;
698 call
->service_id
= FS_SERVICE
;
699 call
->port
= htons(AFS_FS_PORT
);
701 /* marshall the parameters */
703 *bp
++ = htonl(S_ISDIR(mode
) ? FSMAKEDIR
: FSCREATEFILE
);
704 *bp
++ = htonl(vnode
->fid
.vid
);
705 *bp
++ = htonl(vnode
->fid
.vnode
);
706 *bp
++ = htonl(vnode
->fid
.unique
);
707 *bp
++ = htonl(namesz
);
708 memcpy(bp
, name
, namesz
);
709 bp
= (void *) bp
+ namesz
;
711 memset(bp
, 0, padsz
);
712 bp
= (void *) bp
+ padsz
;
714 *bp
++ = htonl(AFS_SET_MODE
);
715 *bp
++ = 0; /* mtime */
716 *bp
++ = 0; /* owner */
717 *bp
++ = 0; /* group */
718 *bp
++ = htonl(mode
& S_IALLUGO
); /* unix mode */
719 *bp
++ = 0; /* segment size */
721 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
725 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
727 static int afs_deliver_fs_remove(struct afs_call
*call
)
729 struct afs_vnode
*vnode
= call
->reply
;
733 _enter("{%u}", call
->unmarshall
);
735 ret
= afs_transfer_reply(call
);
739 /* unmarshall the reply once we've received all of it */
741 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
, NULL
);
742 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
744 _leave(" = 0 [done]");
749 * FS.RemoveDir/FS.RemoveFile operation type
751 static const struct afs_call_type afs_RXFSRemoveXXXX
= {
752 .name
= "FS.RemoveXXXX",
753 .deliver
= afs_deliver_fs_remove
,
754 .abort_to_error
= afs_abort_to_error
,
755 .destructor
= afs_flat_call_destructor
,
759 * remove a file or directory
761 int afs_fs_remove(struct afs_server
*server
,
763 struct afs_vnode
*vnode
,
768 struct afs_call
*call
;
769 size_t namesz
, reqsz
, padsz
;
774 namesz
= strlen(name
);
775 padsz
= (4 - (namesz
& 3)) & 3;
776 reqsz
= (5 * 4) + namesz
+ padsz
;
778 call
= afs_alloc_flat_call(&afs_RXFSRemoveXXXX
, reqsz
, (21 + 6) * 4);
784 call
->service_id
= FS_SERVICE
;
785 call
->port
= htons(AFS_FS_PORT
);
787 /* marshall the parameters */
789 *bp
++ = htonl(isdir
? FSREMOVEDIR
: FSREMOVEFILE
);
790 *bp
++ = htonl(vnode
->fid
.vid
);
791 *bp
++ = htonl(vnode
->fid
.vnode
);
792 *bp
++ = htonl(vnode
->fid
.unique
);
793 *bp
++ = htonl(namesz
);
794 memcpy(bp
, name
, namesz
);
795 bp
= (void *) bp
+ namesz
;
797 memset(bp
, 0, padsz
);
798 bp
= (void *) bp
+ padsz
;
801 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
805 * deliver reply data to an FS.Link
807 static int afs_deliver_fs_link(struct afs_call
*call
)
809 struct afs_vnode
*dvnode
= call
->reply
, *vnode
= call
->reply2
;
813 _enter("{%u}", call
->unmarshall
);
815 ret
= afs_transfer_reply(call
);
819 /* unmarshall the reply once we've received all of it */
821 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
, NULL
);
822 xdr_decode_AFSFetchStatus(&bp
, &dvnode
->status
, dvnode
, NULL
);
823 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
825 _leave(" = 0 [done]");
830 * FS.Link operation type
832 static const struct afs_call_type afs_RXFSLink
= {
834 .deliver
= afs_deliver_fs_link
,
835 .abort_to_error
= afs_abort_to_error
,
836 .destructor
= afs_flat_call_destructor
,
842 int afs_fs_link(struct afs_server
*server
,
844 struct afs_vnode
*dvnode
,
845 struct afs_vnode
*vnode
,
849 struct afs_call
*call
;
850 size_t namesz
, reqsz
, padsz
;
855 namesz
= strlen(name
);
856 padsz
= (4 - (namesz
& 3)) & 3;
857 reqsz
= (5 * 4) + namesz
+ padsz
+ (3 * 4);
859 call
= afs_alloc_flat_call(&afs_RXFSLink
, reqsz
, (21 + 21 + 6) * 4);
864 call
->reply
= dvnode
;
865 call
->reply2
= vnode
;
866 call
->service_id
= FS_SERVICE
;
867 call
->port
= htons(AFS_FS_PORT
);
869 /* marshall the parameters */
871 *bp
++ = htonl(FSLINK
);
872 *bp
++ = htonl(dvnode
->fid
.vid
);
873 *bp
++ = htonl(dvnode
->fid
.vnode
);
874 *bp
++ = htonl(dvnode
->fid
.unique
);
875 *bp
++ = htonl(namesz
);
876 memcpy(bp
, name
, namesz
);
877 bp
= (void *) bp
+ namesz
;
879 memset(bp
, 0, padsz
);
880 bp
= (void *) bp
+ padsz
;
882 *bp
++ = htonl(vnode
->fid
.vid
);
883 *bp
++ = htonl(vnode
->fid
.vnode
);
884 *bp
++ = htonl(vnode
->fid
.unique
);
886 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
890 * deliver reply data to an FS.Symlink
892 static int afs_deliver_fs_symlink(struct afs_call
*call
)
894 struct afs_vnode
*vnode
= call
->reply
;
898 _enter("{%u}", call
->unmarshall
);
900 ret
= afs_transfer_reply(call
);
904 /* unmarshall the reply once we've received all of it */
906 xdr_decode_AFSFid(&bp
, call
->reply2
);
907 xdr_decode_AFSFetchStatus(&bp
, call
->reply3
, NULL
, NULL
);
908 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
, NULL
);
909 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
911 _leave(" = 0 [done]");
916 * FS.Symlink operation type
918 static const struct afs_call_type afs_RXFSSymlink
= {
919 .name
= "FS.Symlink",
920 .deliver
= afs_deliver_fs_symlink
,
921 .abort_to_error
= afs_abort_to_error
,
922 .destructor
= afs_flat_call_destructor
,
926 * create a symbolic link
928 int afs_fs_symlink(struct afs_server
*server
,
930 struct afs_vnode
*vnode
,
932 const char *contents
,
933 struct afs_fid
*newfid
,
934 struct afs_file_status
*newstatus
,
937 struct afs_call
*call
;
938 size_t namesz
, reqsz
, padsz
, c_namesz
, c_padsz
;
943 namesz
= strlen(name
);
944 padsz
= (4 - (namesz
& 3)) & 3;
946 c_namesz
= strlen(contents
);
947 c_padsz
= (4 - (c_namesz
& 3)) & 3;
949 reqsz
= (6 * 4) + namesz
+ padsz
+ c_namesz
+ c_padsz
+ (6 * 4);
951 call
= afs_alloc_flat_call(&afs_RXFSSymlink
, reqsz
,
952 (3 + 21 + 21 + 6) * 4);
958 call
->reply2
= newfid
;
959 call
->reply3
= newstatus
;
960 call
->service_id
= FS_SERVICE
;
961 call
->port
= htons(AFS_FS_PORT
);
963 /* marshall the parameters */
965 *bp
++ = htonl(FSSYMLINK
);
966 *bp
++ = htonl(vnode
->fid
.vid
);
967 *bp
++ = htonl(vnode
->fid
.vnode
);
968 *bp
++ = htonl(vnode
->fid
.unique
);
969 *bp
++ = htonl(namesz
);
970 memcpy(bp
, name
, namesz
);
971 bp
= (void *) bp
+ namesz
;
973 memset(bp
, 0, padsz
);
974 bp
= (void *) bp
+ padsz
;
976 *bp
++ = htonl(c_namesz
);
977 memcpy(bp
, contents
, c_namesz
);
978 bp
= (void *) bp
+ c_namesz
;
980 memset(bp
, 0, c_padsz
);
981 bp
= (void *) bp
+ c_padsz
;
983 *bp
++ = htonl(AFS_SET_MODE
);
984 *bp
++ = 0; /* mtime */
985 *bp
++ = 0; /* owner */
986 *bp
++ = 0; /* group */
987 *bp
++ = htonl(S_IRWXUGO
); /* unix mode */
988 *bp
++ = 0; /* segment size */
990 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
994 * deliver reply data to an FS.Rename
996 static int afs_deliver_fs_rename(struct afs_call
*call
)
998 struct afs_vnode
*orig_dvnode
= call
->reply
, *new_dvnode
= call
->reply2
;
1002 _enter("{%u}", call
->unmarshall
);
1004 ret
= afs_transfer_reply(call
);
1008 /* unmarshall the reply once we've received all of it */
1010 xdr_decode_AFSFetchStatus(&bp
, &orig_dvnode
->status
, orig_dvnode
, NULL
);
1011 if (new_dvnode
!= orig_dvnode
)
1012 xdr_decode_AFSFetchStatus(&bp
, &new_dvnode
->status
, new_dvnode
,
1014 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1016 _leave(" = 0 [done]");
1021 * FS.Rename operation type
1023 static const struct afs_call_type afs_RXFSRename
= {
1024 .name
= "FS.Rename",
1025 .deliver
= afs_deliver_fs_rename
,
1026 .abort_to_error
= afs_abort_to_error
,
1027 .destructor
= afs_flat_call_destructor
,
1031 * create a symbolic link
1033 int afs_fs_rename(struct afs_server
*server
,
1035 struct afs_vnode
*orig_dvnode
,
1036 const char *orig_name
,
1037 struct afs_vnode
*new_dvnode
,
1038 const char *new_name
,
1041 struct afs_call
*call
;
1042 size_t reqsz
, o_namesz
, o_padsz
, n_namesz
, n_padsz
;
1047 o_namesz
= strlen(orig_name
);
1048 o_padsz
= (4 - (o_namesz
& 3)) & 3;
1050 n_namesz
= strlen(new_name
);
1051 n_padsz
= (4 - (n_namesz
& 3)) & 3;
1054 4 + o_namesz
+ o_padsz
+
1056 4 + n_namesz
+ n_padsz
;
1058 call
= afs_alloc_flat_call(&afs_RXFSRename
, reqsz
, (21 + 21 + 6) * 4);
1063 call
->reply
= orig_dvnode
;
1064 call
->reply2
= new_dvnode
;
1065 call
->service_id
= FS_SERVICE
;
1066 call
->port
= htons(AFS_FS_PORT
);
1068 /* marshall the parameters */
1070 *bp
++ = htonl(FSRENAME
);
1071 *bp
++ = htonl(orig_dvnode
->fid
.vid
);
1072 *bp
++ = htonl(orig_dvnode
->fid
.vnode
);
1073 *bp
++ = htonl(orig_dvnode
->fid
.unique
);
1074 *bp
++ = htonl(o_namesz
);
1075 memcpy(bp
, orig_name
, o_namesz
);
1076 bp
= (void *) bp
+ o_namesz
;
1078 memset(bp
, 0, o_padsz
);
1079 bp
= (void *) bp
+ o_padsz
;
1082 *bp
++ = htonl(new_dvnode
->fid
.vid
);
1083 *bp
++ = htonl(new_dvnode
->fid
.vnode
);
1084 *bp
++ = htonl(new_dvnode
->fid
.unique
);
1085 *bp
++ = htonl(n_namesz
);
1086 memcpy(bp
, new_name
, n_namesz
);
1087 bp
= (void *) bp
+ n_namesz
;
1089 memset(bp
, 0, n_padsz
);
1090 bp
= (void *) bp
+ n_padsz
;
1093 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
1097 * deliver reply data to an FS.StoreData
1099 static int afs_deliver_fs_store_data(struct afs_call
*call
)
1101 struct afs_vnode
*vnode
= call
->reply
;
1107 ret
= afs_transfer_reply(call
);
1111 /* unmarshall the reply once we've received all of it */
1113 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
,
1114 &call
->store_version
);
1115 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1117 afs_pages_written_back(vnode
, call
);
1119 _leave(" = 0 [done]");
1124 * FS.StoreData operation type
1126 static const struct afs_call_type afs_RXFSStoreData
= {
1127 .name
= "FS.StoreData",
1128 .deliver
= afs_deliver_fs_store_data
,
1129 .abort_to_error
= afs_abort_to_error
,
1130 .destructor
= afs_flat_call_destructor
,
1133 static const struct afs_call_type afs_RXFSStoreData64
= {
1134 .name
= "FS.StoreData64",
1135 .deliver
= afs_deliver_fs_store_data
,
1136 .abort_to_error
= afs_abort_to_error
,
1137 .destructor
= afs_flat_call_destructor
,
1141 * store a set of pages to a very large file
1143 static int afs_fs_store_data64(struct afs_server
*server
,
1144 struct afs_writeback
*wb
,
1145 pgoff_t first
, pgoff_t last
,
1146 unsigned offset
, unsigned to
,
1147 loff_t size
, loff_t pos
, loff_t i_size
,
1150 struct afs_vnode
*vnode
= wb
->vnode
;
1151 struct afs_call
*call
;
1154 _enter(",%x,{%x:%u},,",
1155 key_serial(wb
->key
), vnode
->fid
.vid
, vnode
->fid
.vnode
);
1157 call
= afs_alloc_flat_call(&afs_RXFSStoreData64
,
1158 (4 + 6 + 3 * 2) * 4,
1164 call
->key
= wb
->key
;
1165 call
->reply
= vnode
;
1166 call
->service_id
= FS_SERVICE
;
1167 call
->port
= htons(AFS_FS_PORT
);
1168 call
->mapping
= vnode
->vfs_inode
.i_mapping
;
1169 call
->first
= first
;
1171 call
->first_offset
= offset
;
1173 call
->send_pages
= true;
1174 call
->store_version
= vnode
->status
.data_version
+ 1;
1176 /* marshall the parameters */
1178 *bp
++ = htonl(FSSTOREDATA64
);
1179 *bp
++ = htonl(vnode
->fid
.vid
);
1180 *bp
++ = htonl(vnode
->fid
.vnode
);
1181 *bp
++ = htonl(vnode
->fid
.unique
);
1183 *bp
++ = 0; /* mask */
1184 *bp
++ = 0; /* mtime */
1185 *bp
++ = 0; /* owner */
1186 *bp
++ = 0; /* group */
1187 *bp
++ = 0; /* unix mode */
1188 *bp
++ = 0; /* segment size */
1190 *bp
++ = htonl(pos
>> 32);
1191 *bp
++ = htonl((u32
) pos
);
1192 *bp
++ = htonl(size
>> 32);
1193 *bp
++ = htonl((u32
) size
);
1194 *bp
++ = htonl(i_size
>> 32);
1195 *bp
++ = htonl((u32
) i_size
);
1197 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
1201 * store a set of pages
1203 int afs_fs_store_data(struct afs_server
*server
, struct afs_writeback
*wb
,
1204 pgoff_t first
, pgoff_t last
,
1205 unsigned offset
, unsigned to
,
1208 struct afs_vnode
*vnode
= wb
->vnode
;
1209 struct afs_call
*call
;
1210 loff_t size
, pos
, i_size
;
1213 _enter(",%x,{%x:%u},,",
1214 key_serial(wb
->key
), vnode
->fid
.vid
, vnode
->fid
.vnode
);
1218 size
+= (loff_t
)(last
- first
) << PAGE_SHIFT
;
1219 pos
= (loff_t
)first
<< PAGE_SHIFT
;
1222 i_size
= i_size_read(&vnode
->vfs_inode
);
1223 if (pos
+ size
> i_size
)
1224 i_size
= size
+ pos
;
1226 _debug("size %llx, at %llx, i_size %llx",
1227 (unsigned long long) size
, (unsigned long long) pos
,
1228 (unsigned long long) i_size
);
1230 if (pos
>> 32 || i_size
>> 32 || size
>> 32 || (pos
+ size
) >> 32)
1231 return afs_fs_store_data64(server
, wb
, first
, last
, offset
, to
,
1232 size
, pos
, i_size
, async
);
1234 call
= afs_alloc_flat_call(&afs_RXFSStoreData
,
1241 call
->key
= wb
->key
;
1242 call
->reply
= vnode
;
1243 call
->service_id
= FS_SERVICE
;
1244 call
->port
= htons(AFS_FS_PORT
);
1245 call
->mapping
= vnode
->vfs_inode
.i_mapping
;
1246 call
->first
= first
;
1248 call
->first_offset
= offset
;
1250 call
->send_pages
= true;
1251 call
->store_version
= vnode
->status
.data_version
+ 1;
1253 /* marshall the parameters */
1255 *bp
++ = htonl(FSSTOREDATA
);
1256 *bp
++ = htonl(vnode
->fid
.vid
);
1257 *bp
++ = htonl(vnode
->fid
.vnode
);
1258 *bp
++ = htonl(vnode
->fid
.unique
);
1260 *bp
++ = 0; /* mask */
1261 *bp
++ = 0; /* mtime */
1262 *bp
++ = 0; /* owner */
1263 *bp
++ = 0; /* group */
1264 *bp
++ = 0; /* unix mode */
1265 *bp
++ = 0; /* segment size */
1268 *bp
++ = htonl(size
);
1269 *bp
++ = htonl(i_size
);
1271 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
1275 * deliver reply data to an FS.StoreStatus
1277 static int afs_deliver_fs_store_status(struct afs_call
*call
)
1279 afs_dataversion_t
*store_version
;
1280 struct afs_vnode
*vnode
= call
->reply
;
1286 ret
= afs_transfer_reply(call
);
1290 /* unmarshall the reply once we've received all of it */
1291 store_version
= NULL
;
1292 if (call
->operation_ID
== FSSTOREDATA
)
1293 store_version
= &call
->store_version
;
1296 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
, store_version
);
1297 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1299 _leave(" = 0 [done]");
1304 * FS.StoreStatus operation type
1306 static const struct afs_call_type afs_RXFSStoreStatus
= {
1307 .name
= "FS.StoreStatus",
1308 .deliver
= afs_deliver_fs_store_status
,
1309 .abort_to_error
= afs_abort_to_error
,
1310 .destructor
= afs_flat_call_destructor
,
1313 static const struct afs_call_type afs_RXFSStoreData_as_Status
= {
1314 .name
= "FS.StoreData",
1315 .deliver
= afs_deliver_fs_store_status
,
1316 .abort_to_error
= afs_abort_to_error
,
1317 .destructor
= afs_flat_call_destructor
,
1320 static const struct afs_call_type afs_RXFSStoreData64_as_Status
= {
1321 .name
= "FS.StoreData64",
1322 .deliver
= afs_deliver_fs_store_status
,
1323 .abort_to_error
= afs_abort_to_error
,
1324 .destructor
= afs_flat_call_destructor
,
1328 * set the attributes on a very large file, using FS.StoreData rather than
1329 * FS.StoreStatus so as to alter the file size also
1331 static int afs_fs_setattr_size64(struct afs_server
*server
, struct key
*key
,
1332 struct afs_vnode
*vnode
, struct iattr
*attr
,
1335 struct afs_call
*call
;
1338 _enter(",%x,{%x:%u},,",
1339 key_serial(key
), vnode
->fid
.vid
, vnode
->fid
.vnode
);
1341 ASSERT(attr
->ia_valid
& ATTR_SIZE
);
1343 call
= afs_alloc_flat_call(&afs_RXFSStoreData64_as_Status
,
1344 (4 + 6 + 3 * 2) * 4,
1350 call
->reply
= vnode
;
1351 call
->service_id
= FS_SERVICE
;
1352 call
->port
= htons(AFS_FS_PORT
);
1353 call
->store_version
= vnode
->status
.data_version
+ 1;
1354 call
->operation_ID
= FSSTOREDATA
;
1356 /* marshall the parameters */
1358 *bp
++ = htonl(FSSTOREDATA64
);
1359 *bp
++ = htonl(vnode
->fid
.vid
);
1360 *bp
++ = htonl(vnode
->fid
.vnode
);
1361 *bp
++ = htonl(vnode
->fid
.unique
);
1363 xdr_encode_AFS_StoreStatus(&bp
, attr
);
1365 *bp
++ = 0; /* position of start of write */
1367 *bp
++ = 0; /* size of write */
1369 *bp
++ = htonl(attr
->ia_size
>> 32); /* new file length */
1370 *bp
++ = htonl((u32
) attr
->ia_size
);
1372 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
1376 * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
1377 * so as to alter the file size also
1379 static int afs_fs_setattr_size(struct afs_server
*server
, struct key
*key
,
1380 struct afs_vnode
*vnode
, struct iattr
*attr
,
1383 struct afs_call
*call
;
1386 _enter(",%x,{%x:%u},,",
1387 key_serial(key
), vnode
->fid
.vid
, vnode
->fid
.vnode
);
1389 ASSERT(attr
->ia_valid
& ATTR_SIZE
);
1390 if (attr
->ia_size
>> 32)
1391 return afs_fs_setattr_size64(server
, key
, vnode
, attr
,
1394 call
= afs_alloc_flat_call(&afs_RXFSStoreData_as_Status
,
1401 call
->reply
= vnode
;
1402 call
->service_id
= FS_SERVICE
;
1403 call
->port
= htons(AFS_FS_PORT
);
1404 call
->store_version
= vnode
->status
.data_version
+ 1;
1405 call
->operation_ID
= FSSTOREDATA
;
1407 /* marshall the parameters */
1409 *bp
++ = htonl(FSSTOREDATA
);
1410 *bp
++ = htonl(vnode
->fid
.vid
);
1411 *bp
++ = htonl(vnode
->fid
.vnode
);
1412 *bp
++ = htonl(vnode
->fid
.unique
);
1414 xdr_encode_AFS_StoreStatus(&bp
, attr
);
1416 *bp
++ = 0; /* position of start of write */
1417 *bp
++ = 0; /* size of write */
1418 *bp
++ = htonl(attr
->ia_size
); /* new file length */
1420 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
1424 * set the attributes on a file, using FS.StoreData if there's a change in file
1425 * size, and FS.StoreStatus otherwise
1427 int afs_fs_setattr(struct afs_server
*server
, struct key
*key
,
1428 struct afs_vnode
*vnode
, struct iattr
*attr
,
1431 struct afs_call
*call
;
1434 if (attr
->ia_valid
& ATTR_SIZE
)
1435 return afs_fs_setattr_size(server
, key
, vnode
, attr
,
1438 _enter(",%x,{%x:%u},,",
1439 key_serial(key
), vnode
->fid
.vid
, vnode
->fid
.vnode
);
1441 call
= afs_alloc_flat_call(&afs_RXFSStoreStatus
,
1448 call
->reply
= vnode
;
1449 call
->service_id
= FS_SERVICE
;
1450 call
->port
= htons(AFS_FS_PORT
);
1451 call
->operation_ID
= FSSTORESTATUS
;
1453 /* marshall the parameters */
1455 *bp
++ = htonl(FSSTORESTATUS
);
1456 *bp
++ = htonl(vnode
->fid
.vid
);
1457 *bp
++ = htonl(vnode
->fid
.vnode
);
1458 *bp
++ = htonl(vnode
->fid
.unique
);
1460 xdr_encode_AFS_StoreStatus(&bp
, attr
);
1462 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
1466 * deliver reply data to an FS.GetVolumeStatus
1468 static int afs_deliver_fs_get_volume_status(struct afs_call
*call
)
1474 _enter("{%u}", call
->unmarshall
);
1476 switch (call
->unmarshall
) {
1481 /* extract the returned status record */
1483 _debug("extract status");
1484 ret
= afs_extract_data(call
, call
->buffer
,
1490 xdr_decode_AFSFetchVolumeStatus(&bp
, call
->reply2
);
1494 /* extract the volume name length */
1496 ret
= afs_extract_data(call
, &call
->tmp
, 4, true);
1500 call
->count
= ntohl(call
->tmp
);
1501 _debug("volname length: %u", call
->count
);
1502 if (call
->count
>= AFSNAMEMAX
)
1507 /* extract the volume name */
1509 _debug("extract volname");
1510 if (call
->count
> 0) {
1511 ret
= afs_extract_data(call
, call
->reply3
,
1519 _debug("volname '%s'", p
);
1524 /* extract the volume name padding */
1525 if ((call
->count
& 3) == 0) {
1527 goto no_volname_padding
;
1529 call
->count
= 4 - (call
->count
& 3);
1532 ret
= afs_extract_data(call
, call
->buffer
,
1541 /* extract the offline message length */
1543 ret
= afs_extract_data(call
, &call
->tmp
, 4, true);
1547 call
->count
= ntohl(call
->tmp
);
1548 _debug("offline msg length: %u", call
->count
);
1549 if (call
->count
>= AFSNAMEMAX
)
1554 /* extract the offline message */
1556 _debug("extract offline");
1557 if (call
->count
> 0) {
1558 ret
= afs_extract_data(call
, call
->reply3
,
1566 _debug("offline '%s'", p
);
1571 /* extract the offline message padding */
1572 if ((call
->count
& 3) == 0) {
1574 goto no_offline_padding
;
1576 call
->count
= 4 - (call
->count
& 3);
1579 ret
= afs_extract_data(call
, call
->buffer
,
1588 /* extract the message of the day length */
1590 ret
= afs_extract_data(call
, &call
->tmp
, 4, true);
1594 call
->count
= ntohl(call
->tmp
);
1595 _debug("motd length: %u", call
->count
);
1596 if (call
->count
>= AFSNAMEMAX
)
1601 /* extract the message of the day */
1603 _debug("extract motd");
1604 if (call
->count
> 0) {
1605 ret
= afs_extract_data(call
, call
->reply3
,
1613 _debug("motd '%s'", p
);
1618 /* extract the message of the day padding */
1619 call
->count
= (4 - (call
->count
& 3)) & 3;
1622 ret
= afs_extract_data(call
, call
->buffer
,
1623 call
->count
, false);
1633 _leave(" = 0 [done]");
1638 * destroy an FS.GetVolumeStatus call
1640 static void afs_get_volume_status_call_destructor(struct afs_call
*call
)
1642 kfree(call
->reply3
);
1643 call
->reply3
= NULL
;
1644 afs_flat_call_destructor(call
);
1648 * FS.GetVolumeStatus operation type
1650 static const struct afs_call_type afs_RXFSGetVolumeStatus
= {
1651 .name
= "FS.GetVolumeStatus",
1652 .deliver
= afs_deliver_fs_get_volume_status
,
1653 .abort_to_error
= afs_abort_to_error
,
1654 .destructor
= afs_get_volume_status_call_destructor
,
1658 * fetch the status of a volume
1660 int afs_fs_get_volume_status(struct afs_server
*server
,
1662 struct afs_vnode
*vnode
,
1663 struct afs_volume_status
*vs
,
1666 struct afs_call
*call
;
1672 tmpbuf
= kmalloc(AFSOPAQUEMAX
, GFP_KERNEL
);
1676 call
= afs_alloc_flat_call(&afs_RXFSGetVolumeStatus
, 2 * 4, 12 * 4);
1683 call
->reply
= vnode
;
1685 call
->reply3
= tmpbuf
;
1686 call
->service_id
= FS_SERVICE
;
1687 call
->port
= htons(AFS_FS_PORT
);
1689 /* marshall the parameters */
1691 bp
[0] = htonl(FSGETVOLUMESTATUS
);
1692 bp
[1] = htonl(vnode
->fid
.vid
);
1694 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
1698 * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock
1700 static int afs_deliver_fs_xxxx_lock(struct afs_call
*call
)
1705 _enter("{%u}", call
->unmarshall
);
1707 ret
= afs_transfer_reply(call
);
1711 /* unmarshall the reply once we've received all of it */
1713 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
1715 _leave(" = 0 [done]");
1720 * FS.SetLock operation type
1722 static const struct afs_call_type afs_RXFSSetLock
= {
1723 .name
= "FS.SetLock",
1724 .deliver
= afs_deliver_fs_xxxx_lock
,
1725 .abort_to_error
= afs_abort_to_error
,
1726 .destructor
= afs_flat_call_destructor
,
1730 * FS.ExtendLock operation type
1732 static const struct afs_call_type afs_RXFSExtendLock
= {
1733 .name
= "FS.ExtendLock",
1734 .deliver
= afs_deliver_fs_xxxx_lock
,
1735 .abort_to_error
= afs_abort_to_error
,
1736 .destructor
= afs_flat_call_destructor
,
1740 * FS.ReleaseLock operation type
1742 static const struct afs_call_type afs_RXFSReleaseLock
= {
1743 .name
= "FS.ReleaseLock",
1744 .deliver
= afs_deliver_fs_xxxx_lock
,
1745 .abort_to_error
= afs_abort_to_error
,
1746 .destructor
= afs_flat_call_destructor
,
1750 * get a lock on a file
1752 int afs_fs_set_lock(struct afs_server
*server
,
1754 struct afs_vnode
*vnode
,
1755 afs_lock_type_t type
,
1758 struct afs_call
*call
;
1763 call
= afs_alloc_flat_call(&afs_RXFSSetLock
, 5 * 4, 6 * 4);
1768 call
->reply
= vnode
;
1769 call
->service_id
= FS_SERVICE
;
1770 call
->port
= htons(AFS_FS_PORT
);
1772 /* marshall the parameters */
1774 *bp
++ = htonl(FSSETLOCK
);
1775 *bp
++ = htonl(vnode
->fid
.vid
);
1776 *bp
++ = htonl(vnode
->fid
.vnode
);
1777 *bp
++ = htonl(vnode
->fid
.unique
);
1778 *bp
++ = htonl(type
);
1780 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
1784 * extend a lock on a file
1786 int afs_fs_extend_lock(struct afs_server
*server
,
1788 struct afs_vnode
*vnode
,
1791 struct afs_call
*call
;
1796 call
= afs_alloc_flat_call(&afs_RXFSExtendLock
, 4 * 4, 6 * 4);
1801 call
->reply
= vnode
;
1802 call
->service_id
= FS_SERVICE
;
1803 call
->port
= htons(AFS_FS_PORT
);
1805 /* marshall the parameters */
1807 *bp
++ = htonl(FSEXTENDLOCK
);
1808 *bp
++ = htonl(vnode
->fid
.vid
);
1809 *bp
++ = htonl(vnode
->fid
.vnode
);
1810 *bp
++ = htonl(vnode
->fid
.unique
);
1812 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);
1816 * release a lock on a file
1818 int afs_fs_release_lock(struct afs_server
*server
,
1820 struct afs_vnode
*vnode
,
1823 struct afs_call
*call
;
1828 call
= afs_alloc_flat_call(&afs_RXFSReleaseLock
, 4 * 4, 6 * 4);
1833 call
->reply
= vnode
;
1834 call
->service_id
= FS_SERVICE
;
1835 call
->port
= htons(AFS_FS_PORT
);
1837 /* marshall the parameters */
1839 *bp
++ = htonl(FSRELEASELOCK
);
1840 *bp
++ = htonl(vnode
->fid
.vid
);
1841 *bp
++ = htonl(vnode
->fid
.vnode
);
1842 *bp
++ = htonl(vnode
->fid
.unique
);
1844 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, async
);