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/sched.h>
14 #include <linux/circ_buf.h>
19 * decode an AFSFid block
21 static void xdr_decode_AFSFid(const __be32
**_bp
, struct afs_fid
*fid
)
23 const __be32
*bp
= *_bp
;
25 fid
->vid
= ntohl(*bp
++);
26 fid
->vnode
= ntohl(*bp
++);
27 fid
->unique
= ntohl(*bp
++);
32 * decode an AFSFetchStatus block
34 static void xdr_decode_AFSFetchStatus(const __be32
**_bp
,
35 struct afs_file_status
*status
,
36 struct afs_vnode
*vnode
)
38 const __be32
*bp
= *_bp
;
40 u64 data_version
, size
;
41 u32 changed
= 0; /* becomes non-zero if ctime-type changes seen */
43 #define EXTRACT(DST) \
45 u32 x = ntohl(*bp++); \
50 status
->if_version
= ntohl(*bp
++);
51 EXTRACT(status
->type
);
52 EXTRACT(status
->nlink
);
54 data_version
= ntohl(*bp
++);
55 EXTRACT(status
->author
);
56 EXTRACT(status
->owner
);
57 EXTRACT(status
->caller_access
); /* call ticket dependent */
58 EXTRACT(status
->anon_access
);
59 EXTRACT(status
->mode
);
60 EXTRACT(status
->parent
.vnode
);
61 EXTRACT(status
->parent
.unique
);
63 status
->mtime_client
= ntohl(*bp
++);
64 status
->mtime_server
= ntohl(*bp
++);
65 EXTRACT(status
->group
);
66 bp
++; /* sync counter */
67 data_version
|= (u64
) ntohl(*bp
++) << 32;
68 bp
++; /* lock count */
69 size
|= (u64
) ntohl(*bp
++) << 32;
73 if (size
!= status
->size
) {
77 status
->mode
&= S_IALLUGO
;
79 _debug("vnode time %lx, %lx",
80 status
->mtime_client
, status
->mtime_server
);
83 status
->parent
.vid
= vnode
->fid
.vid
;
84 if (changed
&& !test_bit(AFS_VNODE_UNSET
, &vnode
->flags
)) {
85 _debug("vnode changed");
86 i_size_write(&vnode
->vfs_inode
, size
);
87 vnode
->vfs_inode
.i_uid
= status
->owner
;
88 vnode
->vfs_inode
.i_gid
= status
->group
;
89 vnode
->vfs_inode
.i_version
= vnode
->fid
.unique
;
90 vnode
->vfs_inode
.i_nlink
= status
->nlink
;
92 mode
= vnode
->vfs_inode
.i_mode
;
96 vnode
->vfs_inode
.i_mode
= mode
;
99 vnode
->vfs_inode
.i_ctime
.tv_sec
= status
->mtime_server
;
100 vnode
->vfs_inode
.i_mtime
= vnode
->vfs_inode
.i_ctime
;
101 vnode
->vfs_inode
.i_atime
= vnode
->vfs_inode
.i_ctime
;
104 if (status
->data_version
!= data_version
) {
105 status
->data_version
= data_version
;
106 if (vnode
&& !test_bit(AFS_VNODE_UNSET
, &vnode
->flags
)) {
107 _debug("vnode modified %llx on {%x:%u}",
108 (unsigned long long) data_version
,
109 vnode
->fid
.vid
, vnode
->fid
.vnode
);
110 set_bit(AFS_VNODE_MODIFIED
, &vnode
->flags
);
111 set_bit(AFS_VNODE_ZAP_DATA
, &vnode
->flags
);
117 * decode an AFSCallBack block
119 static void xdr_decode_AFSCallBack(const __be32
**_bp
, struct afs_vnode
*vnode
)
121 const __be32
*bp
= *_bp
;
123 vnode
->cb_version
= ntohl(*bp
++);
124 vnode
->cb_expiry
= ntohl(*bp
++);
125 vnode
->cb_type
= ntohl(*bp
++);
126 vnode
->cb_expires
= vnode
->cb_expiry
+ get_seconds();
130 static void xdr_decode_AFSCallBack_raw(const __be32
**_bp
,
131 struct afs_callback
*cb
)
133 const __be32
*bp
= *_bp
;
135 cb
->version
= ntohl(*bp
++);
136 cb
->expiry
= ntohl(*bp
++);
137 cb
->type
= ntohl(*bp
++);
142 * decode an AFSVolSync block
144 static void xdr_decode_AFSVolSync(const __be32
**_bp
,
145 struct afs_volsync
*volsync
)
147 const __be32
*bp
= *_bp
;
149 volsync
->creation
= ntohl(*bp
++);
159 * deliver reply data to an FS.FetchStatus
161 static int afs_deliver_fs_fetch_status(struct afs_call
*call
,
162 struct sk_buff
*skb
, bool last
)
164 struct afs_vnode
*vnode
= call
->reply
;
167 _enter(",,%u", last
);
169 afs_transfer_reply(call
, skb
);
173 if (call
->reply_size
!= call
->reply_max
)
176 /* unmarshall the reply once we've received all of it */
178 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
179 xdr_decode_AFSCallBack(&bp
, vnode
);
181 xdr_decode_AFSVolSync(&bp
, call
->reply2
);
183 _leave(" = 0 [done]");
188 * FS.FetchStatus operation type
190 static const struct afs_call_type afs_RXFSFetchStatus
= {
191 .name
= "FS.FetchStatus",
192 .deliver
= afs_deliver_fs_fetch_status
,
193 .abort_to_error
= afs_abort_to_error
,
194 .destructor
= afs_flat_call_destructor
,
198 * fetch the status information for a file
200 int afs_fs_fetch_file_status(struct afs_server
*server
,
202 struct afs_vnode
*vnode
,
203 struct afs_volsync
*volsync
,
204 const struct afs_wait_mode
*wait_mode
)
206 struct afs_call
*call
;
209 _enter(",%x,{%x:%d},,",
210 key_serial(key
), vnode
->fid
.vid
, vnode
->fid
.vnode
);
212 call
= afs_alloc_flat_call(&afs_RXFSFetchStatus
, 16, (21 + 3 + 6) * 4);
218 call
->reply2
= volsync
;
219 call
->service_id
= FS_SERVICE
;
220 call
->port
= htons(AFS_FS_PORT
);
222 /* marshall the parameters */
224 bp
[0] = htonl(FSFETCHSTATUS
);
225 bp
[1] = htonl(vnode
->fid
.vid
);
226 bp
[2] = htonl(vnode
->fid
.vnode
);
227 bp
[3] = htonl(vnode
->fid
.unique
);
229 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
233 * deliver reply data to an FS.FetchData
235 static int afs_deliver_fs_fetch_data(struct afs_call
*call
,
236 struct sk_buff
*skb
, bool last
)
238 struct afs_vnode
*vnode
= call
->reply
;
244 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
246 switch (call
->unmarshall
) {
251 /* extract the returned data length */
253 _debug("extract data length");
254 ret
= afs_extract_data(call
, skb
, last
, &call
->tmp
, 4);
257 case -EAGAIN
: return 0;
261 call
->count
= ntohl(call
->tmp
);
262 _debug("DATA length: %u", call
->count
);
263 if (call
->count
> PAGE_SIZE
)
268 if (call
->count
< PAGE_SIZE
) {
269 buffer
= kmap_atomic(call
->reply3
, KM_USER0
);
270 memset(buffer
+ PAGE_SIZE
- call
->count
, 0,
272 kunmap_atomic(buffer
, KM_USER0
);
275 /* extract the returned data */
277 _debug("extract data");
279 buffer
= kmap_atomic(page
, KM_USER0
);
280 ret
= afs_extract_data(call
, skb
, last
, buffer
, call
->count
);
281 kunmap_atomic(buffer
, KM_USER0
);
284 case -EAGAIN
: return 0;
291 /* extract the metadata */
293 ret
= afs_extract_data(call
, skb
, last
, call
->buffer
,
297 case -EAGAIN
: return 0;
302 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
303 xdr_decode_AFSCallBack(&bp
, vnode
);
305 xdr_decode_AFSVolSync(&bp
, call
->reply2
);
320 _leave(" = 0 [done]");
325 * FS.FetchData operation type
327 static const struct afs_call_type afs_RXFSFetchData
= {
328 .name
= "FS.FetchData",
329 .deliver
= afs_deliver_fs_fetch_data
,
330 .abort_to_error
= afs_abort_to_error
,
331 .destructor
= afs_flat_call_destructor
,
335 * fetch data from a file
337 int afs_fs_fetch_data(struct afs_server
*server
,
339 struct afs_vnode
*vnode
,
340 off_t offset
, size_t length
,
342 const struct afs_wait_mode
*wait_mode
)
344 struct afs_call
*call
;
349 call
= afs_alloc_flat_call(&afs_RXFSFetchData
, 24, (21 + 3 + 6) * 4);
355 call
->reply2
= NULL
; /* volsync */
356 call
->reply3
= buffer
;
357 call
->service_id
= FS_SERVICE
;
358 call
->port
= htons(AFS_FS_PORT
);
360 /* marshall the parameters */
362 bp
[0] = htonl(FSFETCHDATA
);
363 bp
[1] = htonl(vnode
->fid
.vid
);
364 bp
[2] = htonl(vnode
->fid
.vnode
);
365 bp
[3] = htonl(vnode
->fid
.unique
);
366 bp
[4] = htonl(offset
);
367 bp
[5] = htonl(length
);
369 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
373 * deliver reply data to an FS.GiveUpCallBacks
375 static int afs_deliver_fs_give_up_callbacks(struct afs_call
*call
,
376 struct sk_buff
*skb
, bool last
)
378 _enter(",{%u},%d", skb
->len
, last
);
381 return -EBADMSG
; /* shouldn't be any reply data */
386 * FS.GiveUpCallBacks operation type
388 static const struct afs_call_type afs_RXFSGiveUpCallBacks
= {
389 .name
= "FS.GiveUpCallBacks",
390 .deliver
= afs_deliver_fs_give_up_callbacks
,
391 .abort_to_error
= afs_abort_to_error
,
392 .destructor
= afs_flat_call_destructor
,
396 * give up a set of callbacks
397 * - the callbacks are held in the server->cb_break ring
399 int afs_fs_give_up_callbacks(struct afs_server
*server
,
400 const struct afs_wait_mode
*wait_mode
)
402 struct afs_call
*call
;
407 ncallbacks
= CIRC_CNT(server
->cb_break_head
, server
->cb_break_tail
,
408 ARRAY_SIZE(server
->cb_break
));
410 _enter("{%zu},", ncallbacks
);
414 if (ncallbacks
> AFSCBMAX
)
415 ncallbacks
= AFSCBMAX
;
417 _debug("break %zu callbacks", ncallbacks
);
419 call
= afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks
,
420 12 + ncallbacks
* 6 * 4, 0);
424 call
->service_id
= FS_SERVICE
;
425 call
->port
= htons(AFS_FS_PORT
);
427 /* marshall the parameters */
429 tp
= bp
+ 2 + ncallbacks
* 3;
430 *bp
++ = htonl(FSGIVEUPCALLBACKS
);
431 *bp
++ = htonl(ncallbacks
);
432 *tp
++ = htonl(ncallbacks
);
434 atomic_sub(ncallbacks
, &server
->cb_break_n
);
435 for (loop
= ncallbacks
; loop
> 0; loop
--) {
436 struct afs_callback
*cb
=
437 &server
->cb_break
[server
->cb_break_tail
];
439 *bp
++ = htonl(cb
->fid
.vid
);
440 *bp
++ = htonl(cb
->fid
.vnode
);
441 *bp
++ = htonl(cb
->fid
.unique
);
442 *tp
++ = htonl(cb
->version
);
443 *tp
++ = htonl(cb
->expiry
);
444 *tp
++ = htonl(cb
->type
);
446 server
->cb_break_tail
=
447 (server
->cb_break_tail
+ 1) &
448 (ARRAY_SIZE(server
->cb_break
) - 1);
451 ASSERT(ncallbacks
> 0);
452 wake_up_nr(&server
->cb_break_waitq
, ncallbacks
);
454 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
458 * deliver reply data to an FS.CreateFile or an FS.MakeDir
460 static int afs_deliver_fs_create_vnode(struct afs_call
*call
,
461 struct sk_buff
*skb
, bool last
)
463 struct afs_vnode
*vnode
= call
->reply
;
466 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
468 afs_transfer_reply(call
, skb
);
472 if (call
->reply_size
!= call
->reply_max
)
475 /* unmarshall the reply once we've received all of it */
477 xdr_decode_AFSFid(&bp
, call
->reply2
);
478 xdr_decode_AFSFetchStatus(&bp
, call
->reply3
, NULL
);
479 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
480 xdr_decode_AFSCallBack_raw(&bp
, call
->reply4
);
481 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
483 _leave(" = 0 [done]");
488 * FS.CreateFile and FS.MakeDir operation type
490 static const struct afs_call_type afs_RXFSCreateXXXX
= {
491 .name
= "FS.CreateXXXX",
492 .deliver
= afs_deliver_fs_create_vnode
,
493 .abort_to_error
= afs_abort_to_error
,
494 .destructor
= afs_flat_call_destructor
,
498 * create a file or make a directory
500 int afs_fs_create(struct afs_server
*server
,
502 struct afs_vnode
*vnode
,
505 struct afs_fid
*newfid
,
506 struct afs_file_status
*newstatus
,
507 struct afs_callback
*newcb
,
508 const struct afs_wait_mode
*wait_mode
)
510 struct afs_call
*call
;
511 size_t namesz
, reqsz
, padsz
;
516 namesz
= strlen(name
);
517 padsz
= (4 - (namesz
& 3)) & 3;
518 reqsz
= (5 * 4) + namesz
+ padsz
+ (6 * 4);
520 call
= afs_alloc_flat_call(&afs_RXFSCreateXXXX
, reqsz
,
521 (3 + 21 + 21 + 3 + 6) * 4);
527 call
->reply2
= newfid
;
528 call
->reply3
= newstatus
;
529 call
->reply4
= newcb
;
530 call
->service_id
= FS_SERVICE
;
531 call
->port
= htons(AFS_FS_PORT
);
533 /* marshall the parameters */
535 *bp
++ = htonl(S_ISDIR(mode
) ? FSMAKEDIR
: FSCREATEFILE
);
536 *bp
++ = htonl(vnode
->fid
.vid
);
537 *bp
++ = htonl(vnode
->fid
.vnode
);
538 *bp
++ = htonl(vnode
->fid
.unique
);
539 *bp
++ = htonl(namesz
);
540 memcpy(bp
, name
, namesz
);
541 bp
= (void *) bp
+ namesz
;
543 memset(bp
, 0, padsz
);
544 bp
= (void *) bp
+ padsz
;
546 *bp
++ = htonl(AFS_SET_MODE
);
547 *bp
++ = 0; /* mtime */
548 *bp
++ = 0; /* owner */
549 *bp
++ = 0; /* group */
550 *bp
++ = htonl(mode
& S_IALLUGO
); /* unix mode */
551 *bp
++ = 0; /* segment size */
553 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
557 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
559 static int afs_deliver_fs_remove(struct afs_call
*call
,
560 struct sk_buff
*skb
, bool last
)
562 struct afs_vnode
*vnode
= call
->reply
;
565 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
567 afs_transfer_reply(call
, skb
);
571 if (call
->reply_size
!= call
->reply_max
)
574 /* unmarshall the reply once we've received all of it */
576 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
577 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
579 _leave(" = 0 [done]");
584 * FS.RemoveDir/FS.RemoveFile operation type
586 static const struct afs_call_type afs_RXFSRemoveXXXX
= {
587 .name
= "FS.RemoveXXXX",
588 .deliver
= afs_deliver_fs_remove
,
589 .abort_to_error
= afs_abort_to_error
,
590 .destructor
= afs_flat_call_destructor
,
594 * remove a file or directory
596 int afs_fs_remove(struct afs_server
*server
,
598 struct afs_vnode
*vnode
,
601 const struct afs_wait_mode
*wait_mode
)
603 struct afs_call
*call
;
604 size_t namesz
, reqsz
, padsz
;
609 namesz
= strlen(name
);
610 padsz
= (4 - (namesz
& 3)) & 3;
611 reqsz
= (5 * 4) + namesz
+ padsz
;
613 call
= afs_alloc_flat_call(&afs_RXFSRemoveXXXX
, reqsz
, (21 + 6) * 4);
619 call
->service_id
= FS_SERVICE
;
620 call
->port
= htons(AFS_FS_PORT
);
622 /* marshall the parameters */
624 *bp
++ = htonl(isdir
? FSREMOVEDIR
: FSREMOVEFILE
);
625 *bp
++ = htonl(vnode
->fid
.vid
);
626 *bp
++ = htonl(vnode
->fid
.vnode
);
627 *bp
++ = htonl(vnode
->fid
.unique
);
628 *bp
++ = htonl(namesz
);
629 memcpy(bp
, name
, namesz
);
630 bp
= (void *) bp
+ namesz
;
632 memset(bp
, 0, padsz
);
633 bp
= (void *) bp
+ padsz
;
636 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
640 * deliver reply data to an FS.Link
642 static int afs_deliver_fs_link(struct afs_call
*call
,
643 struct sk_buff
*skb
, bool last
)
645 struct afs_vnode
*dvnode
= call
->reply
, *vnode
= call
->reply2
;
648 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
650 afs_transfer_reply(call
, skb
);
654 if (call
->reply_size
!= call
->reply_max
)
657 /* unmarshall the reply once we've received all of it */
659 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
660 xdr_decode_AFSFetchStatus(&bp
, &dvnode
->status
, dvnode
);
661 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
663 _leave(" = 0 [done]");
668 * FS.Link operation type
670 static const struct afs_call_type afs_RXFSLink
= {
672 .deliver
= afs_deliver_fs_link
,
673 .abort_to_error
= afs_abort_to_error
,
674 .destructor
= afs_flat_call_destructor
,
680 int afs_fs_link(struct afs_server
*server
,
682 struct afs_vnode
*dvnode
,
683 struct afs_vnode
*vnode
,
685 const struct afs_wait_mode
*wait_mode
)
687 struct afs_call
*call
;
688 size_t namesz
, reqsz
, padsz
;
693 namesz
= strlen(name
);
694 padsz
= (4 - (namesz
& 3)) & 3;
695 reqsz
= (5 * 4) + namesz
+ padsz
+ (3 * 4);
697 call
= afs_alloc_flat_call(&afs_RXFSLink
, reqsz
, (21 + 21 + 6) * 4);
702 call
->reply
= dvnode
;
703 call
->reply2
= vnode
;
704 call
->service_id
= FS_SERVICE
;
705 call
->port
= htons(AFS_FS_PORT
);
707 /* marshall the parameters */
709 *bp
++ = htonl(FSLINK
);
710 *bp
++ = htonl(dvnode
->fid
.vid
);
711 *bp
++ = htonl(dvnode
->fid
.vnode
);
712 *bp
++ = htonl(dvnode
->fid
.unique
);
713 *bp
++ = htonl(namesz
);
714 memcpy(bp
, name
, namesz
);
715 bp
= (void *) bp
+ namesz
;
717 memset(bp
, 0, padsz
);
718 bp
= (void *) bp
+ padsz
;
720 *bp
++ = htonl(vnode
->fid
.vid
);
721 *bp
++ = htonl(vnode
->fid
.vnode
);
722 *bp
++ = htonl(vnode
->fid
.unique
);
724 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
728 * deliver reply data to an FS.Symlink
730 static int afs_deliver_fs_symlink(struct afs_call
*call
,
731 struct sk_buff
*skb
, bool last
)
733 struct afs_vnode
*vnode
= call
->reply
;
736 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
738 afs_transfer_reply(call
, skb
);
742 if (call
->reply_size
!= call
->reply_max
)
745 /* unmarshall the reply once we've received all of it */
747 xdr_decode_AFSFid(&bp
, call
->reply2
);
748 xdr_decode_AFSFetchStatus(&bp
, call
->reply3
, NULL
);
749 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
750 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
752 _leave(" = 0 [done]");
757 * FS.Symlink operation type
759 static const struct afs_call_type afs_RXFSSymlink
= {
760 .name
= "FS.Symlink",
761 .deliver
= afs_deliver_fs_symlink
,
762 .abort_to_error
= afs_abort_to_error
,
763 .destructor
= afs_flat_call_destructor
,
767 * create a symbolic link
769 int afs_fs_symlink(struct afs_server
*server
,
771 struct afs_vnode
*vnode
,
773 const char *contents
,
774 struct afs_fid
*newfid
,
775 struct afs_file_status
*newstatus
,
776 const struct afs_wait_mode
*wait_mode
)
778 struct afs_call
*call
;
779 size_t namesz
, reqsz
, padsz
, c_namesz
, c_padsz
;
784 namesz
= strlen(name
);
785 padsz
= (4 - (namesz
& 3)) & 3;
787 c_namesz
= strlen(contents
);
788 c_padsz
= (4 - (c_namesz
& 3)) & 3;
790 reqsz
= (6 * 4) + namesz
+ padsz
+ c_namesz
+ c_padsz
+ (6 * 4);
792 call
= afs_alloc_flat_call(&afs_RXFSSymlink
, reqsz
,
793 (3 + 21 + 21 + 6) * 4);
799 call
->reply2
= newfid
;
800 call
->reply3
= newstatus
;
801 call
->service_id
= FS_SERVICE
;
802 call
->port
= htons(AFS_FS_PORT
);
804 /* marshall the parameters */
806 *bp
++ = htonl(FSSYMLINK
);
807 *bp
++ = htonl(vnode
->fid
.vid
);
808 *bp
++ = htonl(vnode
->fid
.vnode
);
809 *bp
++ = htonl(vnode
->fid
.unique
);
810 *bp
++ = htonl(namesz
);
811 memcpy(bp
, name
, namesz
);
812 bp
= (void *) bp
+ namesz
;
814 memset(bp
, 0, padsz
);
815 bp
= (void *) bp
+ padsz
;
817 *bp
++ = htonl(c_namesz
);
818 memcpy(bp
, contents
, c_namesz
);
819 bp
= (void *) bp
+ c_namesz
;
821 memset(bp
, 0, c_padsz
);
822 bp
= (void *) bp
+ c_padsz
;
824 *bp
++ = htonl(AFS_SET_MODE
);
825 *bp
++ = 0; /* mtime */
826 *bp
++ = 0; /* owner */
827 *bp
++ = 0; /* group */
828 *bp
++ = htonl(S_IRWXUGO
); /* unix mode */
829 *bp
++ = 0; /* segment size */
831 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
835 * deliver reply data to an FS.Rename
837 static int afs_deliver_fs_rename(struct afs_call
*call
,
838 struct sk_buff
*skb
, bool last
)
840 struct afs_vnode
*orig_dvnode
= call
->reply
, *new_dvnode
= call
->reply2
;
843 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
845 afs_transfer_reply(call
, skb
);
849 if (call
->reply_size
!= call
->reply_max
)
852 /* unmarshall the reply once we've received all of it */
854 xdr_decode_AFSFetchStatus(&bp
, &orig_dvnode
->status
, orig_dvnode
);
855 if (new_dvnode
!= orig_dvnode
)
856 xdr_decode_AFSFetchStatus(&bp
, &new_dvnode
->status
, new_dvnode
);
857 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
859 _leave(" = 0 [done]");
864 * FS.Rename operation type
866 static const struct afs_call_type afs_RXFSRename
= {
868 .deliver
= afs_deliver_fs_rename
,
869 .abort_to_error
= afs_abort_to_error
,
870 .destructor
= afs_flat_call_destructor
,
874 * create a symbolic link
876 int afs_fs_rename(struct afs_server
*server
,
878 struct afs_vnode
*orig_dvnode
,
879 const char *orig_name
,
880 struct afs_vnode
*new_dvnode
,
881 const char *new_name
,
882 const struct afs_wait_mode
*wait_mode
)
884 struct afs_call
*call
;
885 size_t reqsz
, o_namesz
, o_padsz
, n_namesz
, n_padsz
;
890 o_namesz
= strlen(orig_name
);
891 o_padsz
= (4 - (o_namesz
& 3)) & 3;
893 n_namesz
= strlen(new_name
);
894 n_padsz
= (4 - (n_namesz
& 3)) & 3;
897 4 + o_namesz
+ o_padsz
+
899 4 + n_namesz
+ n_padsz
;
901 call
= afs_alloc_flat_call(&afs_RXFSRename
, reqsz
, (21 + 21 + 6) * 4);
906 call
->reply
= orig_dvnode
;
907 call
->reply2
= new_dvnode
;
908 call
->service_id
= FS_SERVICE
;
909 call
->port
= htons(AFS_FS_PORT
);
911 /* marshall the parameters */
913 *bp
++ = htonl(FSRENAME
);
914 *bp
++ = htonl(orig_dvnode
->fid
.vid
);
915 *bp
++ = htonl(orig_dvnode
->fid
.vnode
);
916 *bp
++ = htonl(orig_dvnode
->fid
.unique
);
917 *bp
++ = htonl(o_namesz
);
918 memcpy(bp
, orig_name
, o_namesz
);
919 bp
= (void *) bp
+ o_namesz
;
921 memset(bp
, 0, o_padsz
);
922 bp
= (void *) bp
+ o_padsz
;
925 *bp
++ = htonl(new_dvnode
->fid
.vid
);
926 *bp
++ = htonl(new_dvnode
->fid
.vnode
);
927 *bp
++ = htonl(new_dvnode
->fid
.unique
);
928 *bp
++ = htonl(n_namesz
);
929 memcpy(bp
, new_name
, n_namesz
);
930 bp
= (void *) bp
+ n_namesz
;
932 memset(bp
, 0, n_padsz
);
933 bp
= (void *) bp
+ n_padsz
;
936 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);