[AFS/AF_RXRPC]: Miscellaneous fixes.
[safe/jmp/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:%d},,",
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                 if (call->count < PAGE_SIZE) {
269                         page = call->reply3;
270                         buffer = kmap_atomic(page, KM_USER0);
271                         memset(buffer + PAGE_SIZE - call->count, 0,
272                                call->count);
273                         kunmap_atomic(buffer, KM_USER0);
274                 }
275
276                 /* extract the returned data */
277         case 2:
278                 _debug("extract data");
279                 page = call->reply3;
280                 buffer = kmap_atomic(page, KM_USER0);
281                 ret = afs_extract_data(call, skb, last, buffer, call->count);
282                 kunmap_atomic(buffer, KM_USER0);
283                 switch (ret) {
284                 case 0:         break;
285                 case -EAGAIN:   return 0;
286                 default:        return ret;
287                 }
288
289                 call->offset = 0;
290                 call->unmarshall++;
291
292                 /* extract the metadata */
293         case 3:
294                 ret = afs_extract_data(call, skb, last, call->buffer,
295                                        (21 + 3 + 6) * 4);
296                 switch (ret) {
297                 case 0:         break;
298                 case -EAGAIN:   return 0;
299                 default:        return ret;
300                 }
301
302                 bp = call->buffer;
303                 xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode);
304                 xdr_decode_AFSCallBack(&bp, vnode);
305                 if (call->reply2)
306                         xdr_decode_AFSVolSync(&bp, call->reply2);
307
308                 call->offset = 0;
309                 call->unmarshall++;
310
311         case 4:
312                 _debug("trailer");
313                 if (skb->len != 0)
314                         return -EBADMSG;
315                 break;
316         }
317
318         if (!last)
319                 return 0;
320
321         _leave(" = 0 [done]");
322         return 0;
323 }
324
325 /*
326  * FS.FetchData operation type
327  */
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,
333 };
334
335 /*
336  * fetch data from a file
337  */
338 int afs_fs_fetch_data(struct afs_server *server,
339                       struct key *key,
340                       struct afs_vnode *vnode,
341                       off_t offset, size_t length,
342                       struct page *buffer,
343                       const struct afs_wait_mode *wait_mode)
344 {
345         struct afs_call *call;
346         __be32 *bp;
347
348         _enter("");
349
350         call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
351         if (!call)
352                 return -ENOMEM;
353
354         call->key = key;
355         call->reply = vnode;
356         call->reply2 = NULL; /* volsync */
357         call->reply3 = buffer;
358         call->service_id = FS_SERVICE;
359         call->port = htons(AFS_FS_PORT);
360
361         /* marshall the parameters */
362         bp = call->request;
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);
369
370         return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
371 }
372
373 /*
374  * deliver reply data to an FS.GiveUpCallBacks
375  */
376 static int afs_deliver_fs_give_up_callbacks(struct afs_call *call,
377                                             struct sk_buff *skb, bool last)
378 {
379         _enter(",{%u},%d", skb->len, last);
380
381         if (skb->len > 0)
382                 return -EBADMSG; /* shouldn't be any reply data */
383         return 0;
384 }
385
386 /*
387  * FS.GiveUpCallBacks operation type
388  */
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,
394 };
395
396 /*
397  * give up a set of callbacks
398  * - the callbacks are held in the server->cb_break ring
399  */
400 int afs_fs_give_up_callbacks(struct afs_server *server,
401                              const struct afs_wait_mode *wait_mode)
402 {
403         struct afs_call *call;
404         size_t ncallbacks;
405         __be32 *bp, *tp;
406         int loop;
407
408         ncallbacks = CIRC_CNT(server->cb_break_head, server->cb_break_tail,
409                               ARRAY_SIZE(server->cb_break));
410
411         _enter("{%zu},", ncallbacks);
412
413         if (ncallbacks == 0)
414                 return 0;
415         if (ncallbacks > AFSCBMAX)
416                 ncallbacks = AFSCBMAX;
417
418         _debug("break %zu callbacks", ncallbacks);
419
420         call = afs_alloc_flat_call(&afs_RXFSGiveUpCallBacks,
421                                    12 + ncallbacks * 6 * 4, 0);
422         if (!call)
423                 return -ENOMEM;
424
425         call->service_id = FS_SERVICE;
426         call->port = htons(AFS_FS_PORT);
427
428         /* marshall the parameters */
429         bp = call->request;
430         tp = bp + 2 + ncallbacks * 3;
431         *bp++ = htonl(FSGIVEUPCALLBACKS);
432         *bp++ = htonl(ncallbacks);
433         *tp++ = htonl(ncallbacks);
434
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];
439
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);
446                 smp_mb();
447                 server->cb_break_tail =
448                         (server->cb_break_tail + 1) &
449                         (ARRAY_SIZE(server->cb_break) - 1);
450         }
451
452         ASSERT(ncallbacks > 0);
453         wake_up_nr(&server->cb_break_waitq, ncallbacks);
454
455         return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
456 }
457
458 /*
459  * deliver reply data to an FS.CreateFile or an FS.MakeDir
460  */
461 static int afs_deliver_fs_create_vnode(struct afs_call *call,
462                                        struct sk_buff *skb, bool last)
463 {
464         struct afs_vnode *vnode = call->reply;
465         const __be32 *bp;
466
467         _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
468
469         afs_transfer_reply(call, skb);
470         if (!last)
471                 return 0;
472
473         if (call->reply_size != call->reply_max)
474                 return -EBADMSG;
475
476         /* unmarshall the reply once we've received all of it */
477         bp = call->buffer;
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); */
483
484         _leave(" = 0 [done]");
485         return 0;
486 }
487
488 /*
489  * FS.CreateFile and FS.MakeDir operation type
490  */
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,
496 };
497
498 /*
499  * create a file or make a directory
500  */
501 int afs_fs_create(struct afs_server *server,
502                   struct key *key,
503                   struct afs_vnode *vnode,
504                   const char *name,
505                   umode_t mode,
506                   struct afs_fid *newfid,
507                   struct afs_file_status *newstatus,
508                   struct afs_callback *newcb,
509                   const struct afs_wait_mode *wait_mode)
510 {
511         struct afs_call *call;
512         size_t namesz, reqsz, padsz;
513         __be32 *bp;
514
515         _enter("");
516
517         namesz = strlen(name);
518         padsz = (4 - (namesz & 3)) & 3;
519         reqsz = (5 * 4) + namesz + padsz + (6 * 4);
520
521         call = afs_alloc_flat_call(&afs_RXFSCreateXXXX, reqsz,
522                                    (3 + 21 + 21 + 3 + 6) * 4);
523         if (!call)
524                 return -ENOMEM;
525
526         call->key = key;
527         call->reply = vnode;
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);
533
534         /* marshall the parameters */
535         bp = call->request;
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;
543         if (padsz > 0) {
544                 memset(bp, 0, padsz);
545                 bp = (void *) bp + padsz;
546         }
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 */
553
554         return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
555 }
556
557 /*
558  * deliver reply data to an FS.RemoveFile or FS.RemoveDir
559  */
560 static int afs_deliver_fs_remove(struct afs_call *call,
561                                  struct sk_buff *skb, bool last)
562 {
563         struct afs_vnode *vnode = call->reply;
564         const __be32 *bp;
565
566         _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
567
568         afs_transfer_reply(call, skb);
569         if (!last)
570                 return 0;
571
572         if (call->reply_size != call->reply_max)
573                 return -EBADMSG;
574
575         /* unmarshall the reply once we've received all of it */
576         bp = call->buffer;
577         xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode);
578         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
579
580         _leave(" = 0 [done]");
581         return 0;
582 }
583
584 /*
585  * FS.RemoveDir/FS.RemoveFile operation type
586  */
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,
592 };
593
594 /*
595  * remove a file or directory
596  */
597 int afs_fs_remove(struct afs_server *server,
598                   struct key *key,
599                   struct afs_vnode *vnode,
600                   const char *name,
601                   bool isdir,
602                   const struct afs_wait_mode *wait_mode)
603 {
604         struct afs_call *call;
605         size_t namesz, reqsz, padsz;
606         __be32 *bp;
607
608         _enter("");
609
610         namesz = strlen(name);
611         padsz = (4 - (namesz & 3)) & 3;
612         reqsz = (5 * 4) + namesz + padsz;
613
614         call = afs_alloc_flat_call(&afs_RXFSRemoveXXXX, reqsz, (21 + 6) * 4);
615         if (!call)
616                 return -ENOMEM;
617
618         call->key = key;
619         call->reply = vnode;
620         call->service_id = FS_SERVICE;
621         call->port = htons(AFS_FS_PORT);
622
623         /* marshall the parameters */
624         bp = call->request;
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;
632         if (padsz > 0) {
633                 memset(bp, 0, padsz);
634                 bp = (void *) bp + padsz;
635         }
636
637         return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
638 }
639
640 /*
641  * deliver reply data to an FS.Link
642  */
643 static int afs_deliver_fs_link(struct afs_call *call,
644                                struct sk_buff *skb, bool last)
645 {
646         struct afs_vnode *dvnode = call->reply, *vnode = call->reply2;
647         const __be32 *bp;
648
649         _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
650
651         afs_transfer_reply(call, skb);
652         if (!last)
653                 return 0;
654
655         if (call->reply_size != call->reply_max)
656                 return -EBADMSG;
657
658         /* unmarshall the reply once we've received all of it */
659         bp = call->buffer;
660         xdr_decode_AFSFetchStatus(&bp, &vnode->status, vnode);
661         xdr_decode_AFSFetchStatus(&bp, &dvnode->status, dvnode);
662         /* xdr_decode_AFSVolSync(&bp, call->replyX); */
663
664         _leave(" = 0 [done]");
665         return 0;
666 }
667
668 /*
669  * FS.Link operation type
670  */
671 static const struct afs_call_type afs_RXFSLink = {
672         .name           = "FS.Link",
673         .deliver        = afs_deliver_fs_link,
674         .abort_to_error = afs_abort_to_error,
675         .destructor     = afs_flat_call_destructor,
676 };
677
678 /*
679  * make a hard link
680  */
681 int afs_fs_link(struct afs_server *server,
682                 struct key *key,
683                 struct afs_vnode *dvnode,
684                 struct afs_vnode *vnode,
685                 const char *name,
686                 const struct afs_wait_mode *wait_mode)
687 {
688         struct afs_call *call;
689         size_t namesz, reqsz, padsz;
690         __be32 *bp;
691
692         _enter("");
693
694         namesz = strlen(name);
695         padsz = (4 - (namesz & 3)) & 3;
696         reqsz = (5 * 4) + namesz + padsz + (3 * 4);
697
698         call = afs_alloc_flat_call(&afs_RXFSLink, reqsz, (21 + 21 + 6) * 4);
699         if (!call)
700                 return -ENOMEM;
701
702         call->key = key;
703         call->reply = dvnode;
704         call->reply2 = vnode;
705         call->service_id = FS_SERVICE;
706         call->port = htons(AFS_FS_PORT);
707
708         /* marshall the parameters */
709         bp = call->request;
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;
717         if (padsz > 0) {
718                 memset(bp, 0, padsz);
719                 bp = (void *) bp + padsz;
720         }
721         *bp++ = htonl(vnode->fid.vid);
722         *bp++ = htonl(vnode->fid.vnode);
723         *bp++ = htonl(vnode->fid.unique);
724
725         return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
726 }
727
728 /*
729  * deliver reply data to an FS.Symlink
730  */
731 static int afs_deliver_fs_symlink(struct afs_call *call,
732                                   struct sk_buff *skb, bool last)
733 {
734         struct afs_vnode *vnode = call->reply;
735         const __be32 *bp;
736
737         _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
738
739         afs_transfer_reply(call, skb);
740         if (!last)
741                 return 0;
742
743         if (call->reply_size != call->reply_max)
744                 return -EBADMSG;
745
746         /* unmarshall the reply once we've received all of it */
747         bp = call->buffer;
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); */
752
753         _leave(" = 0 [done]");
754         return 0;
755 }
756
757 /*
758  * FS.Symlink operation type
759  */
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,
765 };
766
767 /*
768  * create a symbolic link
769  */
770 int afs_fs_symlink(struct afs_server *server,
771                    struct key *key,
772                    struct afs_vnode *vnode,
773                    const char *name,
774                    const char *contents,
775                    struct afs_fid *newfid,
776                    struct afs_file_status *newstatus,
777                    const struct afs_wait_mode *wait_mode)
778 {
779         struct afs_call *call;
780         size_t namesz, reqsz, padsz, c_namesz, c_padsz;
781         __be32 *bp;
782
783         _enter("");
784
785         namesz = strlen(name);
786         padsz = (4 - (namesz & 3)) & 3;
787
788         c_namesz = strlen(contents);
789         c_padsz = (4 - (c_namesz & 3)) & 3;
790
791         reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
792
793         call = afs_alloc_flat_call(&afs_RXFSSymlink, reqsz,
794                                    (3 + 21 + 21 + 6) * 4);
795         if (!call)
796                 return -ENOMEM;
797
798         call->key = key;
799         call->reply = vnode;
800         call->reply2 = newfid;
801         call->reply3 = newstatus;
802         call->service_id = FS_SERVICE;
803         call->port = htons(AFS_FS_PORT);
804
805         /* marshall the parameters */
806         bp = call->request;
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;
814         if (padsz > 0) {
815                 memset(bp, 0, padsz);
816                 bp = (void *) bp + padsz;
817         }
818         *bp++ = htonl(c_namesz);
819         memcpy(bp, contents, c_namesz);
820         bp = (void *) bp + c_namesz;
821         if (c_padsz > 0) {
822                 memset(bp, 0, c_padsz);
823                 bp = (void *) bp + c_padsz;
824         }
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 */
831
832         return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
833 }
834
835 /*
836  * deliver reply data to an FS.Rename
837  */
838 static int afs_deliver_fs_rename(struct afs_call *call,
839                                   struct sk_buff *skb, bool last)
840 {
841         struct afs_vnode *orig_dvnode = call->reply, *new_dvnode = call->reply2;
842         const __be32 *bp;
843
844         _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
845
846         afs_transfer_reply(call, skb);
847         if (!last)
848                 return 0;
849
850         if (call->reply_size != call->reply_max)
851                 return -EBADMSG;
852
853         /* unmarshall the reply once we've received all of it */
854         bp = call->buffer;
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); */
859
860         _leave(" = 0 [done]");
861         return 0;
862 }
863
864 /*
865  * FS.Rename operation type
866  */
867 static const struct afs_call_type afs_RXFSRename = {
868         .name           = "FS.Rename",
869         .deliver        = afs_deliver_fs_rename,
870         .abort_to_error = afs_abort_to_error,
871         .destructor     = afs_flat_call_destructor,
872 };
873
874 /*
875  * create a symbolic link
876  */
877 int afs_fs_rename(struct afs_server *server,
878                   struct key *key,
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)
884 {
885         struct afs_call *call;
886         size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
887         __be32 *bp;
888
889         _enter("");
890
891         o_namesz = strlen(orig_name);
892         o_padsz = (4 - (o_namesz & 3)) & 3;
893
894         n_namesz = strlen(new_name);
895         n_padsz = (4 - (n_namesz & 3)) & 3;
896
897         reqsz = (4 * 4) +
898                 4 + o_namesz + o_padsz +
899                 (3 * 4) +
900                 4 + n_namesz + n_padsz;
901
902         call = afs_alloc_flat_call(&afs_RXFSRename, reqsz, (21 + 21 + 6) * 4);
903         if (!call)
904                 return -ENOMEM;
905
906         call->key = key;
907         call->reply = orig_dvnode;
908         call->reply2 = new_dvnode;
909         call->service_id = FS_SERVICE;
910         call->port = htons(AFS_FS_PORT);
911
912         /* marshall the parameters */
913         bp = call->request;
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;
921         if (o_padsz > 0) {
922                 memset(bp, 0, o_padsz);
923                 bp = (void *) bp + o_padsz;
924         }
925
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;
932         if (n_padsz > 0) {
933                 memset(bp, 0, n_padsz);
934                 bp = (void *) bp + n_padsz;
935         }
936
937         return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
938 }