proc->thread stage 4: rework the VFS and DEVICE subsystems to take thread
[dragonfly.git] / sys / vfs / coda / coda_venus.c
1 /*
2  * 
3  *             Coda: an Experimental Distributed File System
4  *                              Release 3.1
5  * 
6  *           Copyright (c) 1987-1998 Carnegie Mellon University
7  *                          All Rights Reserved
8  * 
9  * Permission  to  use, copy, modify and distribute this software and its
10  * documentation is hereby granted,  provided  that  both  the  copyright
11  * notice  and  this  permission  notice  appear  in  all  copies  of the
12  * software, derivative works or  modified  versions,  and  any  portions
13  * thereof, and that both notices appear in supporting documentation, and
14  * that credit is given to Carnegie Mellon University  in  all  documents
15  * and publicity pertaining to direct or indirect use of this code or its
16  * derivatives.
17  * 
18  * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS  KNOWN  TO  HAVE  BUGS,
19  * SOME  OF  WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON ALLOWS
20  * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.   CARNEGIE  MELLON
21  * DISCLAIMS  ANY  LIABILITY  OF  ANY  KIND  FOR  ANY  DAMAGES WHATSOEVER
22  * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE  OR  OF
23  * ANY DERIVATIVE WORK.
24  * 
25  * Carnegie  Mellon  encourages  users  of  this  software  to return any
26  * improvements or extensions that  they  make,  and  to  grant  Carnegie
27  * Mellon the rights to redistribute these changes without encumbrance.
28  * 
29  *      @(#) src/sys/cfs/coda_venus.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
30  * $FreeBSD: src/sys/coda/coda_venus.c,v 1.9 1999/08/28 00:40:56 peter Exp $
31  * $DragonFly: src/sys/vfs/coda/Attic/coda_venus.c,v 1.3 2003/06/25 03:55:44 dillon Exp $
32  * 
33  */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/proc.h>
39 #include <sys/select.h>
40 #include <sys/ioccom.h>
41 #include <sys/fcntl.h>
42
43 #include <coda/coda.h>
44 #include <coda/cnode.h>
45 #include <coda/coda_venus.h>
46 #include <coda/coda_pioctl.h>
47
48 #define DECL_NO_IN(name)                                \
49     struct coda_in_hdr *inp;                            \
50     struct name ## _out *outp;                          \
51     int name ## _size = sizeof (struct coda_in_hdr);    \
52     int Isize = sizeof (struct coda_in_hdr);            \
53     int Osize = sizeof (struct name ## _out);           \
54     int error
55
56 #define DECL(name)                                      \
57     struct name ## _in *inp;                            \
58     struct name ## _out *outp;                          \
59     int name ## _size = sizeof (struct name ## _in);    \
60     int Isize = sizeof (struct name ## _in);            \
61     int Osize = sizeof (struct name ## _out);           \
62     int error
63
64 #define DECL_NO_OUT(name)                               \
65     struct name ## _in *inp;                            \
66     struct coda_out_hdr *outp;                          \
67     int name ## _size = sizeof (struct name ## _in);    \
68     int Isize = sizeof (struct name ## _in);            \
69     int Osize = sizeof (struct coda_out_hdr);           \
70     int error
71
72 #define ALLOC_NO_IN(name)                               \
73     if (Osize > name ## _size)                          \
74         name ## _size = Osize;                          \
75     CODA_ALLOC(inp, struct coda_in_hdr *, name ## _size);\
76     outp = (struct name ## _out *) inp
77
78 #define ALLOC(name)                                     \
79     if (Osize > name ## _size)                          \
80         name ## _size = Osize;                          \
81     CODA_ALLOC(inp, struct name ## _in *, name ## _size);\
82     outp = (struct name ## _out *) inp
83
84 #define ALLOC_NO_OUT(name)                              \
85     if (Osize > name ## _size)                          \
86         name ## _size = Osize;                          \
87     CODA_ALLOC(inp, struct name ## _in *, name ## _size);\
88     outp = (struct coda_out_hdr *) inp
89
90 #define STRCPY(struc, name, len) \
91     bcopy(name, (char *)inp + (int)inp->struc, len); \
92     ((char*)inp + (int)inp->struc)[len++] = 0; \
93     Isize += len
94
95 #define INIT_IN(in, op, ident, td) \
96         do { struct proc *p = (td)->td_proc; \
97           (in)->opcode = (op); \
98           (in)->pid = p ? p->p_pid : -1; \
99           (in)->pgid = p ? p->p_pgid : -1; \
100           (in)->sid = (p && p->p_session && p->p_session->s_leader) ? (p->p_session->s_leader->p_pid) : -1; \
101           if (ident != NOCRED) {                              \
102               (in)->cred.cr_uid = ident->cr_uid;              \
103               (in)->cred.cr_groupid = ident->cr_gid;          \
104           } else {                                            \
105               bzero(&((in)->cred),sizeof(struct coda_cred));  \
106               (in)->cred.cr_uid = -1;                         \
107               (in)->cred.cr_groupid = -1;                     \
108           }                                                   \
109        } while(0)
110
111 #define CNV_OFLAG(to, from)                             \
112     do {                                                \
113           to = 0;                                       \
114           if (from & FREAD)   to |= C_O_READ;           \
115           if (from & FWRITE)  to |= C_O_WRITE;          \
116           if (from & O_TRUNC) to |= C_O_TRUNC;          \
117           if (from & O_EXCL)  to |= C_O_EXCL;           \
118           if (from & O_CREAT) to |= C_O_CREAT;          \
119     } while (0)
120
121 #define CNV_VV2V_ATTR(top, fromp) \
122         do { \
123                 (top)->va_type = (fromp)->va_type; \
124                 (top)->va_mode = (fromp)->va_mode; \
125                 (top)->va_nlink = (fromp)->va_nlink; \
126                 (top)->va_uid = (fromp)->va_uid; \
127                 (top)->va_gid = (fromp)->va_gid; \
128                 (top)->va_fsid = VNOVAL; \
129                 (top)->va_fileid = (fromp)->va_fileid; \
130                 (top)->va_size = (fromp)->va_size; \
131                 (top)->va_blocksize = (fromp)->va_blocksize; \
132                 (top)->va_atime = (fromp)->va_atime; \
133                 (top)->va_mtime = (fromp)->va_mtime; \
134                 (top)->va_ctime = (fromp)->va_ctime; \
135                 (top)->va_gen = (fromp)->va_gen; \
136                 (top)->va_flags = (fromp)->va_flags; \
137                 (top)->va_rdev = (fromp)->va_rdev; \
138                 (top)->va_bytes = (fromp)->va_bytes; \
139                 (top)->va_filerev = (fromp)->va_filerev; \
140                 (top)->va_vaflags = VNOVAL; \
141                 (top)->va_spare = VNOVAL; \
142         } while (0)
143
144 #define CNV_V2VV_ATTR(top, fromp) \
145         do { \
146                 (top)->va_type = (fromp)->va_type; \
147                 (top)->va_mode = (fromp)->va_mode; \
148                 (top)->va_nlink = (fromp)->va_nlink; \
149                 (top)->va_uid = (fromp)->va_uid; \
150                 (top)->va_gid = (fromp)->va_gid; \
151                 (top)->va_fileid = (fromp)->va_fileid; \
152                 (top)->va_size = (fromp)->va_size; \
153                 (top)->va_blocksize = (fromp)->va_blocksize; \
154                 (top)->va_atime = (fromp)->va_atime; \
155                 (top)->va_mtime = (fromp)->va_mtime; \
156                 (top)->va_ctime = (fromp)->va_ctime; \
157                 (top)->va_gen = (fromp)->va_gen; \
158                 (top)->va_flags = (fromp)->va_flags; \
159                 (top)->va_rdev = (fromp)->va_rdev; \
160                 (top)->va_bytes = (fromp)->va_bytes; \
161                 (top)->va_filerev = (fromp)->va_filerev; \
162         } while (0)
163
164
165 int coda_kernel_version = CODA_KERNEL_VERSION;
166
167 int
168 venus_root(void *mdp,
169         struct ucred *cred, struct thread *td,
170 /*out*/ ViceFid *VFid)
171 {
172     DECL_NO_IN(coda_root);              /* sets Isize & Osize */
173     ALLOC_NO_IN(coda_root);             /* sets inp & outp */
174
175     /* send the open to venus. */
176     INIT_IN(inp, CODA_ROOT, cred, td);  
177
178     error = coda_call(mdp, Isize, &Osize, (char *)inp);
179     if (!error)
180         *VFid = outp->VFid;
181
182     CODA_FREE(inp, coda_root_size);
183     return error;
184 }
185
186 int
187 venus_open(void *mdp, ViceFid *fid, int flag,
188         struct ucred *cred, struct thread *td,
189 /*out*/ dev_t *dev, ino_t *inode)
190 {
191     int cflag;
192     DECL(coda_open);                    /* sets Isize & Osize */
193     ALLOC(coda_open);                   /* sets inp & outp */
194
195     /* send the open to venus. */
196     INIT_IN(&inp->ih, CODA_OPEN, cred, td);
197     inp->VFid = *fid;
198     CNV_OFLAG(cflag, flag);
199     inp->flags = cflag;
200
201     error = coda_call(mdp, Isize, &Osize, (char *)inp);
202     if (!error) {
203 /* 5/11 *dev =  udev2dev(outp->dev, 2); */
204         *dev =  udev2dev(outp->dev, 0);
205         *inode = outp->inode;
206     }
207
208     CODA_FREE(inp, coda_open_size);
209     return error;
210 }
211
212 int
213 venus_close(void *mdp, ViceFid *fid, int flag,
214         struct ucred *cred, struct thread *td)
215 {
216     int cflag;
217     DECL_NO_OUT(coda_close);            /* sets Isize & Osize */
218     ALLOC_NO_OUT(coda_close);           /* sets inp & outp */
219
220     INIT_IN(&inp->ih, CODA_CLOSE, cred, td);
221     inp->VFid = *fid;
222     CNV_OFLAG(cflag, flag);
223     inp->flags = cflag;
224
225     error = coda_call(mdp, Isize, &Osize, (char *)inp);
226
227     CODA_FREE(inp, coda_close_size);
228     return error;
229 }
230
231 /*
232  * these two calls will not exist!!!  the container file is read/written
233  * directly.
234  */
235 void
236 venus_read(void)
237 {
238 }
239
240 void
241 venus_write(void)
242 {
243 }
244
245 /*
246  * this is a bit sad too.  the ioctl's are for the control file, not for
247  * normal files.
248  */
249 int
250 venus_ioctl(void *mdp, ViceFid *fid,
251         int com, int flag, caddr_t data,
252         struct ucred *cred, struct thread *td)
253 {
254     DECL(coda_ioctl);                   /* sets Isize & Osize */
255     struct PioctlData *iap = (struct PioctlData *)data;
256     int tmp;
257
258     coda_ioctl_size = VC_MAXMSGSIZE;
259     ALLOC(coda_ioctl);                  /* sets inp & outp */
260
261     INIT_IN(&inp->ih, CODA_IOCTL, cred, td);
262     inp->VFid = *fid;
263
264     /* command was mutated by increasing its size field to reflect the  
265      * path and follow args. we need to subtract that out before sending
266      * the command to venus.
267      */
268     inp->cmd = (com & ~(IOCPARM_MASK << 16));
269     tmp = ((com >> 16) & IOCPARM_MASK) - sizeof (char *) - sizeof (int);
270     inp->cmd |= (tmp & IOCPARM_MASK) << 16;
271
272     inp->rwflag = flag;
273     inp->len = iap->vi.in_size;
274     inp->data = (char *)(sizeof (struct coda_ioctl_in));
275
276     error = copyin(iap->vi.in, (char*)inp + (int)inp->data, 
277                    iap->vi.in_size);
278     if (error) {
279         CODA_FREE(inp, coda_ioctl_size);
280         return(error);
281     }
282
283     Osize = VC_MAXMSGSIZE;
284     error = coda_call(mdp, Isize + iap->vi.in_size, &Osize, (char *)inp);
285
286         /* copy out the out buffer. */
287     if (!error) {
288         if (outp->len > iap->vi.out_size) {
289             error = EINVAL;
290         } else {
291             error = copyout((char *)outp + (int)outp->data, 
292                             iap->vi.out, iap->vi.out_size);
293         }
294     }
295
296     CODA_FREE(inp, coda_ioctl_size);
297     return error;
298 }
299
300 int
301 venus_getattr(void *mdp, ViceFid *fid,
302         struct ucred *cred, struct thread *td,
303 /*out*/ struct vattr *vap)
304 {
305     DECL(coda_getattr);                 /* sets Isize & Osize */
306     ALLOC(coda_getattr);                        /* sets inp & outp */
307
308     /* send the open to venus. */
309     INIT_IN(&inp->ih, CODA_GETATTR, cred, td);
310     inp->VFid = *fid;
311
312     error = coda_call(mdp, Isize, &Osize, (char *)inp);
313     if (!error) {
314         CNV_VV2V_ATTR(vap, &outp->attr);
315     }
316
317     CODA_FREE(inp, coda_getattr_size);
318     return error;
319 }
320
321 int
322 venus_setattr(void *mdp, ViceFid *fid, struct vattr *vap,
323         struct ucred *cred, struct thread *td)
324 {
325     DECL_NO_OUT(coda_setattr);          /* sets Isize & Osize */
326     ALLOC_NO_OUT(coda_setattr);         /* sets inp & outp */
327
328     /* send the open to venus. */
329     INIT_IN(&inp->ih, CODA_SETATTR, cred, td);
330     inp->VFid = *fid;
331     CNV_V2VV_ATTR(&inp->attr, vap);
332
333     error = coda_call(mdp, Isize, &Osize, (char *)inp);
334
335     CODA_FREE(inp, coda_setattr_size);
336     return error;
337 }
338
339 int
340 venus_access(void *mdp, ViceFid *fid, int mode,
341         struct ucred *cred, struct thread *td)
342 {
343     DECL_NO_OUT(coda_access);           /* sets Isize & Osize */
344     ALLOC_NO_OUT(coda_access);          /* sets inp & outp */
345
346     /* send the open to venus. */
347     INIT_IN(&inp->ih, CODA_ACCESS, cred, td);
348     inp->VFid = *fid;
349     /* NOTE:
350      * NetBSD and Venus internals use the "data" in the low 3 bits.
351      * Hence, the conversion.
352      */
353     inp->flags = mode>>6;
354
355     error = coda_call(mdp, Isize, &Osize, (char *)inp);
356
357     CODA_FREE(inp, coda_access_size);
358     return error;
359 }
360
361 int
362 venus_readlink(void *mdp, ViceFid *fid,
363         struct ucred *cred, struct thread *td,
364 /*out*/ char **str, int *len)
365 {
366     DECL(coda_readlink);                        /* sets Isize & Osize */
367     coda_readlink_size += CODA_MAXPATHLEN;
368     ALLOC(coda_readlink);               /* sets inp & outp */
369
370     /* send the open to venus. */
371     INIT_IN(&inp->ih, CODA_READLINK, cred, td);
372     inp->VFid = *fid;
373
374     Osize += CODA_MAXPATHLEN;
375     error = coda_call(mdp, Isize, &Osize, (char *)inp);
376     if (!error) {
377             CODA_ALLOC(*str, char *, outp->count);
378             *len = outp->count;
379             bcopy((char *)outp + (int)outp->data, *str, *len);
380     }
381
382     CODA_FREE(inp, coda_readlink_size);
383     return error;
384 }
385
386 int
387 venus_fsync(void *mdp, ViceFid *fid,
388         struct ucred *cred, struct thread *td)
389 {
390     DECL_NO_OUT(coda_fsync);            /* sets Isize & Osize */
391     ALLOC_NO_OUT(coda_fsync);           /* sets inp & outp */
392
393     /* send the open to venus. */
394     INIT_IN(&inp->ih, CODA_FSYNC, cred, td);
395     inp->VFid = *fid;
396
397     error = coda_call(mdp, Isize, &Osize, (char *)inp);
398
399     CODA_FREE(inp, coda_fsync_size);
400     return error;
401 }
402
403 int
404 venus_lookup(void *mdp, ViceFid *fid,
405         const char *nm, int len,
406         struct ucred *cred, struct thread *td,
407 /*out*/ ViceFid *VFid, int *vtype)
408 {
409     DECL(coda_lookup);                  /* sets Isize & Osize */
410     coda_lookup_size += len + 1;
411     ALLOC(coda_lookup);                 /* sets inp & outp */
412
413     /* send the open to venus. */
414     INIT_IN(&inp->ih, CODA_LOOKUP, cred, td);
415     inp->VFid = *fid;
416
417     /* NOTE:
418      * Between version 1 and version 2 we have added an extra flag field
419      * to this structure.  But because the string was at the end and because
420      * of the wierd way we represent strings by having the slot point to
421      * where the string characters are in the "heap", we can just slip the
422      * flag parameter in after the string slot pointer and veni that don't
423      * know better won't see this new flag field ...
424      * Otherwise we'd need two different venus_lookup functions.
425      */
426     inp->name = Isize;
427     inp->flags = CLU_CASE_SENSITIVE;    /* doesn't really matter for BSD */
428     STRCPY(name, nm, len);              /* increments Isize */
429
430     error = coda_call(mdp, Isize, &Osize, (char *)inp);
431     if (!error) {
432         *VFid = outp->VFid;
433         *vtype = outp->vtype;
434     }
435
436     CODA_FREE(inp, coda_lookup_size);
437     return error;
438 }
439
440 int
441 venus_create(void *mdp, ViceFid *fid,
442         const char *nm, int len, int exclusive, int mode, struct vattr *va,
443         struct ucred *cred, struct thread *td,
444 /*out*/ ViceFid *VFid, struct vattr *attr)
445 {
446     DECL(coda_create);                  /* sets Isize & Osize */
447     coda_create_size += len + 1;
448     ALLOC(coda_create);                 /* sets inp & outp */
449
450     /* send the open to venus. */
451     INIT_IN(&inp->ih, CODA_CREATE, cred, td);
452     inp->VFid = *fid;
453     inp->excl = exclusive ? C_O_EXCL : 0;
454     inp->mode = mode;
455     CNV_V2VV_ATTR(&inp->attr, va);
456
457     inp->name = Isize;
458     STRCPY(name, nm, len);              /* increments Isize */
459
460     error = coda_call(mdp, Isize, &Osize, (char *)inp);
461     if (!error) {
462         *VFid = outp->VFid;
463         CNV_VV2V_ATTR(attr, &outp->attr);
464     }
465
466     CODA_FREE(inp, coda_create_size);
467     return error;
468 }
469
470 int
471 venus_remove(void *mdp, ViceFid *fid,
472         const char *nm, int len,
473         struct ucred *cred, struct thread *td)
474 {
475     DECL_NO_OUT(coda_remove);           /* sets Isize & Osize */
476     coda_remove_size += len + 1;
477     ALLOC_NO_OUT(coda_remove);          /* sets inp & outp */
478
479     /* send the open to venus. */
480     INIT_IN(&inp->ih, CODA_REMOVE, cred, td);
481     inp->VFid = *fid;
482
483     inp->name = Isize;
484     STRCPY(name, nm, len);              /* increments Isize */
485
486     error = coda_call(mdp, Isize, &Osize, (char *)inp);
487
488     CODA_FREE(inp, coda_remove_size);
489     return error;
490 }
491
492 int
493 venus_link(void *mdp, ViceFid *fid, ViceFid *tfid,
494         const char *nm, int len,
495         struct ucred *cred, struct thread *td)
496 {
497     DECL_NO_OUT(coda_link);             /* sets Isize & Osize */
498     coda_link_size += len + 1;
499     ALLOC_NO_OUT(coda_link);            /* sets inp & outp */
500
501     /* send the open to venus. */
502     INIT_IN(&inp->ih, CODA_LINK, cred, td);
503     inp->sourceFid = *fid;
504     inp->destFid = *tfid;
505
506     inp->tname = Isize;
507     STRCPY(tname, nm, len);             /* increments Isize */
508
509     error = coda_call(mdp, Isize, &Osize, (char *)inp);
510
511     CODA_FREE(inp, coda_link_size);
512     return error;
513 }
514
515 int
516 venus_rename(void *mdp, ViceFid *fid, ViceFid *tfid,
517         const char *nm, int len, const char *tnm, int tlen,
518         struct ucred *cred, struct thread *td)
519 {
520     DECL_NO_OUT(coda_rename);           /* sets Isize & Osize */
521     coda_rename_size += len + 1 + tlen + 1;
522     ALLOC_NO_OUT(coda_rename);          /* sets inp & outp */
523
524     /* send the open to venus. */
525     INIT_IN(&inp->ih, CODA_RENAME, cred, td);
526     inp->sourceFid = *fid;
527     inp->destFid = *tfid;
528
529     inp->srcname = Isize;
530     STRCPY(srcname, nm, len);           /* increments Isize */
531
532     inp->destname = Isize;
533     STRCPY(destname, tnm, tlen);        /* increments Isize */
534
535     error = coda_call(mdp, Isize, &Osize, (char *)inp);
536
537     CODA_FREE(inp, coda_rename_size);
538     return error;
539 }
540
541 int
542 venus_mkdir(void *mdp, ViceFid *fid,
543         const char *nm, int len, struct vattr *va,
544         struct ucred *cred, struct thread *td,
545 /*out*/ ViceFid *VFid, struct vattr *ova)
546 {
547     DECL(coda_mkdir);                   /* sets Isize & Osize */
548     coda_mkdir_size += len + 1;
549     ALLOC(coda_mkdir);                  /* sets inp & outp */
550
551     /* send the open to venus. */
552     INIT_IN(&inp->ih, CODA_MKDIR, cred, td);
553     inp->VFid = *fid;
554     CNV_V2VV_ATTR(&inp->attr, va);
555
556     inp->name = Isize;
557     STRCPY(name, nm, len);              /* increments Isize */
558
559     error = coda_call(mdp, Isize, &Osize, (char *)inp);
560     if (!error) {
561         *VFid = outp->VFid;
562         CNV_VV2V_ATTR(ova, &outp->attr);
563     }
564
565     CODA_FREE(inp, coda_mkdir_size);
566     return error;
567 }
568
569 int
570 venus_rmdir(void *mdp, ViceFid *fid,
571         const char *nm, int len,
572         struct ucred *cred, struct thread *td)
573 {
574     DECL_NO_OUT(coda_rmdir);            /* sets Isize & Osize */
575     coda_rmdir_size += len + 1;
576     ALLOC_NO_OUT(coda_rmdir);           /* sets inp & outp */
577
578     /* send the open to venus. */
579     INIT_IN(&inp->ih, CODA_RMDIR, cred, td);
580     inp->VFid = *fid;
581
582     inp->name = Isize;
583     STRCPY(name, nm, len);              /* increments Isize */
584
585     error = coda_call(mdp, Isize, &Osize, (char *)inp);
586
587     CODA_FREE(inp, coda_rmdir_size);
588     return error;
589 }
590
591 int
592 venus_symlink(void *mdp, ViceFid *fid,
593         const char *lnm, int llen, const char *nm, int len, struct vattr *va,
594         struct ucred *cred, struct thread *td)
595 {
596     DECL_NO_OUT(coda_symlink);          /* sets Isize & Osize */
597     coda_symlink_size += llen + 1 + len + 1;
598     ALLOC_NO_OUT(coda_symlink);         /* sets inp & outp */
599
600     /* send the open to venus. */
601     INIT_IN(&inp->ih, CODA_SYMLINK, cred, td);
602     inp->VFid = *fid;
603     CNV_V2VV_ATTR(&inp->attr, va);
604
605     inp->srcname = Isize;
606     STRCPY(srcname, lnm, llen);         /* increments Isize */
607
608     inp->tname = Isize;
609     STRCPY(tname, nm, len);             /* increments Isize */
610
611     error = coda_call(mdp, Isize, &Osize, (char *)inp);
612
613     CODA_FREE(inp, coda_symlink_size);
614     return error;
615 }
616
617 int
618 venus_readdir(void *mdp, ViceFid *fid,
619         int count, int offset,
620         struct ucred *cred, struct thread *td,
621 /*out*/ char *buffer, int *len)
622 {
623     DECL(coda_readdir);                 /* sets Isize & Osize */
624     coda_readdir_size = VC_MAXMSGSIZE;
625     ALLOC(coda_readdir);                        /* sets inp & outp */
626
627     /* send the open to venus. */
628     INIT_IN(&inp->ih, CODA_READDIR, cred, td);
629     inp->VFid = *fid;
630     inp->count = count;
631     inp->offset = offset;
632
633     Osize = VC_MAXMSGSIZE;
634     error = coda_call(mdp, Isize, &Osize, (char *)inp);
635     if (!error) {
636         bcopy((char *)outp + (int)outp->data, buffer, outp->size);
637         *len = outp->size;
638     }
639
640     CODA_FREE(inp, coda_readdir_size);
641     return error;
642 }
643
644 int
645 venus_fhtovp(void *mdp, ViceFid *fid,
646         struct ucred *cred, struct thread *td,
647 /*out*/ ViceFid *VFid, int *vtype)
648 {
649     DECL(coda_vget);                    /* sets Isize & Osize */
650     ALLOC(coda_vget);                   /* sets inp & outp */
651
652     /* Send the open to Venus. */
653     INIT_IN(&inp->ih, CODA_VGET, cred, td);
654     inp->VFid = *fid;
655
656     error = coda_call(mdp, Isize, &Osize, (char *)inp);
657     if (!error) {
658         *VFid = outp->VFid;
659         *vtype = outp->vtype;
660     }
661
662     CODA_FREE(inp, coda_vget_size);
663     return error;
664 }