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