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