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