Home | History | Annotate | Line # | Download | only in coda
coda_venus.c revision 1.19
      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