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
) {
270 buffer
= kmap_atomic(page
, KM_USER0
);
271 memset(buffer
+ PAGE_SIZE
- call
->count
, 0,
273 kunmap_atomic(buffer
, KM_USER0
);
276 /* extract the returned data */
278 _debug("extract data");
280 buffer
= kmap_atomic(page
, KM_USER0
);
281 ret
= afs_extract_data(call
, skb
, last
, buffer
, call
->count
);
282 kunmap_atomic(buffer
, KM_USER0
);
285 case -EAGAIN
: return 0;
292 /* extract the metadata */
294 ret
= afs_extract_data(call
, skb
, last
, call
->buffer
,
298 case -EAGAIN
: return 0;
303 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
304 xdr_decode_AFSCallBack(&bp
, vnode
);
306 xdr_decode_AFSVolSync(&bp
, call
->reply2
);
321 _leave(" = 0 [done]");
326 * FS.FetchData operation type
328 static const struct afs_call_type afs_RXFSFetchData
= {
329 .name
= "FS.FetchData",
330 .deliver
= afs_deliver_fs_fetch_data
,
331 .abort_to_error
= afs_abort_to_error
,
332 .destructor
= afs_flat_call_destructor
,
336 * fetch data from a file
338 int afs_fs_fetch_data(struct afs_server
*server
,
340 struct afs_vnode
*vnode
,
341 off_t offset
, size_t length
,
343 const struct afs_wait_mode
*wait_mode
)
345 struct afs_call
*call
;
350 call
= afs_alloc_flat_call(&afs_RXFSFetchData
, 24, (21 + 3 + 6) * 4);
356 call
->reply2
= NULL
; /* volsync */
357 call
->reply3
= buffer
;
358 call
->service_id
= FS_SERVICE
;
359 call
->port
= htons(AFS_FS_PORT
);
361 /* marshall the parameters */
363 bp
[0] = htonl(FSFETCHDATA
);
364 bp
[1] = htonl(vnode
->fid
.vid
);
365 bp
[2] = htonl(vnode
->fid
.vnode
);
366 bp
[3] = htonl(vnode
->fid
.unique
);
367 bp
[4] = htonl(offset
);
368 bp
[5] = htonl(length
);
370 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
374 * deliver reply data to an FS.GiveUpCallBacks
376 static int afs_deliver_fs_give_up_callbacks(struct afs_call
*call
,
377 struct sk_buff
*skb
, bool last
)
379 _enter(",{%u},%d", skb
->len
, last
);
382 return -EBADMSG
; /* shouldn't be any reply data */
387 * FS.GiveUpCallBacks operation type
389 static const struct afs_call_type afs_RXFSGiveUpCallBacks
= {
390 .name
= "FS.GiveUpCallBacks",
391 .deliver
= afs_deliver_fs_give_up_callbacks
,
392 .abort_to_error
= afs_abort_to_error
,
393 .destructor
= afs_flat_call_destructor
,
397 * give up a set of callbacks
398 * - the callbacks are held in the server->cb_break ring
400 int afs_fs_give_up_callbacks(struct afs_server
*server
,
401 const struct afs_wait_mode
*wait_mode
)
403 struct afs_call
*call
;
408 ncallbacks
= CIRC_CNT(server
->cb_break_head
, server
->cb_break_tail
,
409 ARRAY_SIZE(server
->cb_break
));
411 _enter("{%zu},", ncallbacks
);
415 if (ncallbacks
> AFSCBMAX
)
416 ncallbacks
= AFSCBMAX
;
418 _debug("break %zu callbacks", ncallbacks
);
420 call
= afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks
,
421 12 + ncallbacks
* 6 * 4, 0);
425 call
->service_id
= FS_SERVICE
;
426 call
->port
= htons(AFS_FS_PORT
);
428 /* marshall the parameters */
430 tp
= bp
+ 2 + ncallbacks
* 3;
431 *bp
++ = htonl(FSGIVEUPCALLBACKS
);
432 *bp
++ = htonl(ncallbacks
);
433 *tp
++ = htonl(ncallbacks
);
435 atomic_sub(ncallbacks
, &server
->cb_break_n
);
436 for (loop
= ncallbacks
; loop
> 0; loop
--) {
437 struct afs_callback
*cb
=
438 &server
->cb_break
[server
->cb_break_tail
];
440 *bp
++ = htonl(cb
->fid
.vid
);
441 *bp
++ = htonl(cb
->fid
.vnode
);
442 *bp
++ = htonl(cb
->fid
.unique
);
443 *tp
++ = htonl(cb
->version
);
444 *tp
++ = htonl(cb
->expiry
);
445 *tp
++ = htonl(cb
->type
);
447 server
->cb_break_tail
=
448 (server
->cb_break_tail
+ 1) &
449 (ARRAY_SIZE(server
->cb_break
) - 1);
452 ASSERT(ncallbacks
> 0);
453 wake_up_nr(&server
->cb_break_waitq
, ncallbacks
);
455 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
459 * deliver reply data to an FS.CreateFile or an FS.MakeDir
461 static int afs_deliver_fs_create_vnode(struct afs_call
*call
,
462 struct sk_buff
*skb
, bool last
)
464 struct afs_vnode
*vnode
= call
->reply
;
467 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
469 afs_transfer_reply(call
, skb
);
473 if (call
->reply_size
!= call
->reply_max
)
476 /* unmarshall the reply once we've received all of it */
478 xdr_decode_AFSFid(&bp
, call
->reply2
);
479 xdr_decode_AFSFetchStatus(&bp
, call
->reply3
, NULL
);
480 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
481 xdr_decode_AFSCallBack_raw(&bp
, call
->reply4
);
482 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
484 _leave(" = 0 [done]");
489 * FS.CreateFile and FS.MakeDir operation type
491 static const struct afs_call_type afs_RXFSCreateXXXX
= {
492 .name
= "FS.CreateXXXX",
493 .deliver
= afs_deliver_fs_create_vnode
,
494 .abort_to_error
= afs_abort_to_error
,
495 .destructor
= afs_flat_call_destructor
,
499 * create a file or make a directory
501 int afs_fs_create(struct afs_server
*server
,
503 struct afs_vnode
*vnode
,
506 struct afs_fid
*newfid
,
507 struct afs_file_status
*newstatus
,
508 struct afs_callback
*newcb
,
509 const struct afs_wait_mode
*wait_mode
)
511 struct afs_call
*call
;
512 size_t namesz
, reqsz
, padsz
;
517 namesz
= strlen(name
);
518 padsz
= (4 - (namesz
& 3)) & 3;
519 reqsz
= (5 * 4) + namesz
+ padsz
+ (6 * 4);
521 call
= afs_alloc_flat_call(&afs_RXFSCreateXXXX
, reqsz
,
522 (3 + 21 + 21 + 3 + 6) * 4);
528 call
->reply2
= newfid
;
529 call
->reply3
= newstatus
;
530 call
->reply4
= newcb
;
531 call
->service_id
= FS_SERVICE
;
532 call
->port
= htons(AFS_FS_PORT
);
534 /* marshall the parameters */
536 *bp
++ = htonl(S_ISDIR(mode
) ? FSMAKEDIR
: FSCREATEFILE
);
537 *bp
++ = htonl(vnode
->fid
.vid
);
538 *bp
++ = htonl(vnode
->fid
.vnode
);
539 *bp
++ = htonl(vnode
->fid
.unique
);
540 *bp
++ = htonl(namesz
);
541 memcpy(bp
, name
, namesz
);
542 bp
= (void *) bp
+ namesz
;
544 memset(bp
, 0, padsz
);
545 bp
= (void *) bp
+ padsz
;
547 *bp
++ = htonl(AFS_SET_MODE
);
548 *bp
++ = 0; /* mtime */
549 *bp
++ = 0; /* owner */
550 *bp
++ = 0; /* group */
551 *bp
++ = htonl(mode
& S_IALLUGO
); /* unix mode */
552 *bp
++ = 0; /* segment size */
554 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
558 * deliver reply data to an FS.RemoveFile or FS.RemoveDir
560 static int afs_deliver_fs_remove(struct afs_call
*call
,
561 struct sk_buff
*skb
, bool last
)
563 struct afs_vnode
*vnode
= call
->reply
;
566 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
568 afs_transfer_reply(call
, skb
);
572 if (call
->reply_size
!= call
->reply_max
)
575 /* unmarshall the reply once we've received all of it */
577 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
578 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
580 _leave(" = 0 [done]");
585 * FS.RemoveDir/FS.RemoveFile operation type
587 static const struct afs_call_type afs_RXFSRemoveXXXX
= {
588 .name
= "FS.RemoveXXXX",
589 .deliver
= afs_deliver_fs_remove
,
590 .abort_to_error
= afs_abort_to_error
,
591 .destructor
= afs_flat_call_destructor
,
595 * remove a file or directory
597 int afs_fs_remove(struct afs_server
*server
,
599 struct afs_vnode
*vnode
,
602 const struct afs_wait_mode
*wait_mode
)
604 struct afs_call
*call
;
605 size_t namesz
, reqsz
, padsz
;
610 namesz
= strlen(name
);
611 padsz
= (4 - (namesz
& 3)) & 3;
612 reqsz
= (5 * 4) + namesz
+ padsz
;
614 call
= afs_alloc_flat_call(&afs_RXFSRemoveXXXX
, reqsz
, (21 + 6) * 4);
620 call
->service_id
= FS_SERVICE
;
621 call
->port
= htons(AFS_FS_PORT
);
623 /* marshall the parameters */
625 *bp
++ = htonl(isdir
? FSREMOVEDIR
: FSREMOVEFILE
);
626 *bp
++ = htonl(vnode
->fid
.vid
);
627 *bp
++ = htonl(vnode
->fid
.vnode
);
628 *bp
++ = htonl(vnode
->fid
.unique
);
629 *bp
++ = htonl(namesz
);
630 memcpy(bp
, name
, namesz
);
631 bp
= (void *) bp
+ namesz
;
633 memset(bp
, 0, padsz
);
634 bp
= (void *) bp
+ padsz
;
637 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
641 * deliver reply data to an FS.Link
643 static int afs_deliver_fs_link(struct afs_call
*call
,
644 struct sk_buff
*skb
, bool last
)
646 struct afs_vnode
*dvnode
= call
->reply
, *vnode
= call
->reply2
;
649 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
651 afs_transfer_reply(call
, skb
);
655 if (call
->reply_size
!= call
->reply_max
)
658 /* unmarshall the reply once we've received all of it */
660 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
661 xdr_decode_AFSFetchStatus(&bp
, &dvnode
->status
, dvnode
);
662 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
664 _leave(" = 0 [done]");
669 * FS.Link operation type
671 static const struct afs_call_type afs_RXFSLink
= {
673 .deliver
= afs_deliver_fs_link
,
674 .abort_to_error
= afs_abort_to_error
,
675 .destructor
= afs_flat_call_destructor
,
681 int afs_fs_link(struct afs_server
*server
,
683 struct afs_vnode
*dvnode
,
684 struct afs_vnode
*vnode
,
686 const struct afs_wait_mode
*wait_mode
)
688 struct afs_call
*call
;
689 size_t namesz
, reqsz
, padsz
;
694 namesz
= strlen(name
);
695 padsz
= (4 - (namesz
& 3)) & 3;
696 reqsz
= (5 * 4) + namesz
+ padsz
+ (3 * 4);
698 call
= afs_alloc_flat_call(&afs_RXFSLink
, reqsz
, (21 + 21 + 6) * 4);
703 call
->reply
= dvnode
;
704 call
->reply2
= vnode
;
705 call
->service_id
= FS_SERVICE
;
706 call
->port
= htons(AFS_FS_PORT
);
708 /* marshall the parameters */
710 *bp
++ = htonl(FSLINK
);
711 *bp
++ = htonl(dvnode
->fid
.vid
);
712 *bp
++ = htonl(dvnode
->fid
.vnode
);
713 *bp
++ = htonl(dvnode
->fid
.unique
);
714 *bp
++ = htonl(namesz
);
715 memcpy(bp
, name
, namesz
);
716 bp
= (void *) bp
+ namesz
;
718 memset(bp
, 0, padsz
);
719 bp
= (void *) bp
+ padsz
;
721 *bp
++ = htonl(vnode
->fid
.vid
);
722 *bp
++ = htonl(vnode
->fid
.vnode
);
723 *bp
++ = htonl(vnode
->fid
.unique
);
725 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
729 * deliver reply data to an FS.Symlink
731 static int afs_deliver_fs_symlink(struct afs_call
*call
,
732 struct sk_buff
*skb
, bool last
)
734 struct afs_vnode
*vnode
= call
->reply
;
737 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
739 afs_transfer_reply(call
, skb
);
743 if (call
->reply_size
!= call
->reply_max
)
746 /* unmarshall the reply once we've received all of it */
748 xdr_decode_AFSFid(&bp
, call
->reply2
);
749 xdr_decode_AFSFetchStatus(&bp
, call
->reply3
, NULL
);
750 xdr_decode_AFSFetchStatus(&bp
, &vnode
->status
, vnode
);
751 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
753 _leave(" = 0 [done]");
758 * FS.Symlink operation type
760 static const struct afs_call_type afs_RXFSSymlink
= {
761 .name
= "FS.Symlink",
762 .deliver
= afs_deliver_fs_symlink
,
763 .abort_to_error
= afs_abort_to_error
,
764 .destructor
= afs_flat_call_destructor
,
768 * create a symbolic link
770 int afs_fs_symlink(struct afs_server
*server
,
772 struct afs_vnode
*vnode
,
774 const char *contents
,
775 struct afs_fid
*newfid
,
776 struct afs_file_status
*newstatus
,
777 const struct afs_wait_mode
*wait_mode
)
779 struct afs_call
*call
;
780 size_t namesz
, reqsz
, padsz
, c_namesz
, c_padsz
;
785 namesz
= strlen(name
);
786 padsz
= (4 - (namesz
& 3)) & 3;
788 c_namesz
= strlen(contents
);
789 c_padsz
= (4 - (c_namesz
& 3)) & 3;
791 reqsz
= (6 * 4) + namesz
+ padsz
+ c_namesz
+ c_padsz
+ (6 * 4);
793 call
= afs_alloc_flat_call(&afs_RXFSSymlink
, reqsz
,
794 (3 + 21 + 21 + 6) * 4);
800 call
->reply2
= newfid
;
801 call
->reply3
= newstatus
;
802 call
->service_id
= FS_SERVICE
;
803 call
->port
= htons(AFS_FS_PORT
);
805 /* marshall the parameters */
807 *bp
++ = htonl(FSSYMLINK
);
808 *bp
++ = htonl(vnode
->fid
.vid
);
809 *bp
++ = htonl(vnode
->fid
.vnode
);
810 *bp
++ = htonl(vnode
->fid
.unique
);
811 *bp
++ = htonl(namesz
);
812 memcpy(bp
, name
, namesz
);
813 bp
= (void *) bp
+ namesz
;
815 memset(bp
, 0, padsz
);
816 bp
= (void *) bp
+ padsz
;
818 *bp
++ = htonl(c_namesz
);
819 memcpy(bp
, contents
, c_namesz
);
820 bp
= (void *) bp
+ c_namesz
;
822 memset(bp
, 0, c_padsz
);
823 bp
= (void *) bp
+ c_padsz
;
825 *bp
++ = htonl(AFS_SET_MODE
);
826 *bp
++ = 0; /* mtime */
827 *bp
++ = 0; /* owner */
828 *bp
++ = 0; /* group */
829 *bp
++ = htonl(S_IRWXUGO
); /* unix mode */
830 *bp
++ = 0; /* segment size */
832 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);
836 * deliver reply data to an FS.Rename
838 static int afs_deliver_fs_rename(struct afs_call
*call
,
839 struct sk_buff
*skb
, bool last
)
841 struct afs_vnode
*orig_dvnode
= call
->reply
, *new_dvnode
= call
->reply2
;
844 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
846 afs_transfer_reply(call
, skb
);
850 if (call
->reply_size
!= call
->reply_max
)
853 /* unmarshall the reply once we've received all of it */
855 xdr_decode_AFSFetchStatus(&bp
, &orig_dvnode
->status
, orig_dvnode
);
856 if (new_dvnode
!= orig_dvnode
)
857 xdr_decode_AFSFetchStatus(&bp
, &new_dvnode
->status
, new_dvnode
);
858 /* xdr_decode_AFSVolSync(&bp, call->replyX); */
860 _leave(" = 0 [done]");
865 * FS.Rename operation type
867 static const struct afs_call_type afs_RXFSRename
= {
869 .deliver
= afs_deliver_fs_rename
,
870 .abort_to_error
= afs_abort_to_error
,
871 .destructor
= afs_flat_call_destructor
,
875 * create a symbolic link
877 int afs_fs_rename(struct afs_server
*server
,
879 struct afs_vnode
*orig_dvnode
,
880 const char *orig_name
,
881 struct afs_vnode
*new_dvnode
,
882 const char *new_name
,
883 const struct afs_wait_mode
*wait_mode
)
885 struct afs_call
*call
;
886 size_t reqsz
, o_namesz
, o_padsz
, n_namesz
, n_padsz
;
891 o_namesz
= strlen(orig_name
);
892 o_padsz
= (4 - (o_namesz
& 3)) & 3;
894 n_namesz
= strlen(new_name
);
895 n_padsz
= (4 - (n_namesz
& 3)) & 3;
898 4 + o_namesz
+ o_padsz
+
900 4 + n_namesz
+ n_padsz
;
902 call
= afs_alloc_flat_call(&afs_RXFSRename
, reqsz
, (21 + 21 + 6) * 4);
907 call
->reply
= orig_dvnode
;
908 call
->reply2
= new_dvnode
;
909 call
->service_id
= FS_SERVICE
;
910 call
->port
= htons(AFS_FS_PORT
);
912 /* marshall the parameters */
914 *bp
++ = htonl(FSRENAME
);
915 *bp
++ = htonl(orig_dvnode
->fid
.vid
);
916 *bp
++ = htonl(orig_dvnode
->fid
.vnode
);
917 *bp
++ = htonl(orig_dvnode
->fid
.unique
);
918 *bp
++ = htonl(o_namesz
);
919 memcpy(bp
, orig_name
, o_namesz
);
920 bp
= (void *) bp
+ o_namesz
;
922 memset(bp
, 0, o_padsz
);
923 bp
= (void *) bp
+ o_padsz
;
926 *bp
++ = htonl(new_dvnode
->fid
.vid
);
927 *bp
++ = htonl(new_dvnode
->fid
.vnode
);
928 *bp
++ = htonl(new_dvnode
->fid
.unique
);
929 *bp
++ = htonl(n_namesz
);
930 memcpy(bp
, new_name
, n_namesz
);
931 bp
= (void *) bp
+ n_namesz
;
933 memset(bp
, 0, n_padsz
);
934 bp
= (void *) bp
+ n_padsz
;
937 return afs_make_call(&server
->addr
, call
, GFP_NOFS
, wait_mode
);