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