Home | History | Annotate | Line # | Download | only in coda
coda_venus.c revision 1.13
      1 /*	$NetBSD: coda_venus.c,v 1.13 2002/11/02 07:18:36 perry 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.13 2002/11/02 07:18:36 perry 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 #define DECL_NO_IN(name) 				\
     52     struct coda_in_hdr *inp;				\
     53     struct name ## _out *outp;				\
     54     int name ## _size = sizeof (struct coda_in_hdr);	\
     55     int Isize = sizeof (struct coda_in_hdr);		\
     56     int Osize = sizeof (struct name ## _out);		\
     57     int error
     58 
     59 #define DECL(name)					\
     60     struct name ## _in *inp;				\
     61     struct name ## _out *outp;				\
     62     int name ## _size = sizeof (struct name ## _in);	\
     63     int Isize = sizeof (struct name ## _in);		\
     64     int Osize = sizeof (struct name ## _out);		\
     65     int error
     66 
     67 #define DECL_NO_OUT(name)				\
     68     struct name ## _in *inp;				\
     69     struct coda_out_hdr *outp;				\
     70     int name ## _size = sizeof (struct name ## _in);	\
     71     int Isize = sizeof (struct name ## _in);		\
     72     int Osize = sizeof (struct coda_out_hdr);		\
     73     int error
     74 
     75 #define ALLOC_NO_IN(name)				\
     76     if (Osize > name ## _size)				\
     77     	name ## _size = Osize;				\
     78     CODA_ALLOC(inp, struct coda_in_hdr *, name ## _size);\
     79     outp = (struct name ## _out *) inp
     80 
     81 #define ALLOC(name)					\
     82     if (Osize > name ## _size)				\
     83     	name ## _size = Osize;				\
     84     CODA_ALLOC(inp, struct name ## _in *, name ## _size);\
     85     outp = (struct name ## _out *) inp
     86 
     87 #define ALLOC_NO_OUT(name)				\
     88     if (Osize > name ## _size)				\
     89     	name ## _size = Osize;				\
     90     CODA_ALLOC(inp, struct name ## _in *, name ## _size);\
     91     outp = (struct coda_out_hdr *) inp
     92 
     93 #define STRCPY(struc, name, len) \
     94     bcopy(name, (char *)inp + (int)inp->struc, len); \
     95     ((char*)inp + (int)inp->struc)[len++] = 0; \
     96     Isize += len
     97 
     98 #define INIT_IN(in, op, ident, p) \
     99 	  (in)->opcode = (op); \
    100 	  (in)->pid = p ? p->p_pid : -1; \
    101           (in)->pgid = p ? p->p_pgid : -1; \
    102           (in)->sid = (p && p->p_session && p->p_session->s_leader) ? (p->p_session->s_leader->p_pid) : -1; \
    103           if (ident != NOCRED) {                              \
    104 	      (in)->cred.cr_uid = ident->cr_uid;              \
    105 	      (in)->cred.cr_groupid = ident->cr_gid;          \
    106           } else {                                            \
    107 	      memset(&((in)->cred), 0, 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 (/*CONSTCOND*/ 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 (/*CONSTCOND*/ 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 (/*CONSTCOND*/ 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 	*dev =  outp->dev;
    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 proc *p)
    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, p);
    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 proc *p)
    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, p);
    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     if (iap->vi.in_size < 0 || iap->vi.in_size > VC_MAXMSGSIZE)
    273 	return (EINVAL);
    274 
    275     inp->rwflag = flag;
    276     inp->len = iap->vi.in_size;
    277     inp->data = (char *)(sizeof (struct coda_ioctl_in));
    278 
    279     error = copyin(iap->vi.in, (char*)inp + (int)(long)inp->data,
    280 		   iap->vi.in_size);
    281     if (error) {
    282 	CODA_FREE(inp, coda_ioctl_size);
    283 	return(error);
    284     }
    285 
    286     Osize = VC_MAXMSGSIZE;
    287     error = coda_call(mdp, Isize + iap->vi.in_size, &Osize, (char *)inp);
    288 
    289 	/* copy out the out buffer. */
    290     if (!error) {
    291 	if (outp->len > iap->vi.out_size) {
    292 	    error = EINVAL;
    293 	} else {
    294 	    error = copyout((char *)outp + (int)(long)outp->data,
    295 			    iap->vi.out, iap->vi.out_size);
    296 	}
    297     }
    298 
    299     CODA_FREE(inp, coda_ioctl_size);
    300     return error;
    301 }
    302 
    303 int
    304 venus_getattr(void *mdp, ViceFid *fid,
    305 	struct ucred *cred, struct proc *p,
    306 /*out*/	struct vattr *vap)
    307 {
    308     DECL(coda_getattr);			/* sets Isize & Osize */
    309     ALLOC(coda_getattr);			/* sets inp & outp */
    310 
    311     /* send the open to venus. */
    312     INIT_IN(&inp->ih, CODA_GETATTR, cred, p);
    313     inp->VFid = *fid;
    314 
    315     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    316     if (!error) {
    317 	CNV_VV2V_ATTR(vap, &outp->attr);
    318     }
    319 
    320     CODA_FREE(inp, coda_getattr_size);
    321     return error;
    322 }
    323 
    324 int
    325 venus_setattr(void *mdp, ViceFid *fid, struct vattr *vap,
    326 	struct ucred *cred, struct proc *p)
    327 {
    328     DECL_NO_OUT(coda_setattr);		/* sets Isize & Osize */
    329     ALLOC_NO_OUT(coda_setattr);		/* sets inp & outp */
    330 
    331     /* send the open to venus. */
    332     INIT_IN(&inp->ih, CODA_SETATTR, cred, p);
    333     inp->VFid = *fid;
    334     CNV_V2VV_ATTR(&inp->attr, vap);
    335 
    336     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    337 
    338     CODA_FREE(inp, coda_setattr_size);
    339     return error;
    340 }
    341 
    342 int
    343 venus_access(void *mdp, ViceFid *fid, int mode,
    344 	struct ucred *cred, struct proc *p)
    345 {
    346     DECL_NO_OUT(coda_access);		/* sets Isize & Osize */
    347     ALLOC_NO_OUT(coda_access);		/* sets inp & outp */
    348 
    349     /* send the open to venus. */
    350     INIT_IN(&inp->ih, CODA_ACCESS, cred, p);
    351     inp->VFid = *fid;
    352     inp->flags = mode;
    353 
    354     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    355 
    356     CODA_FREE(inp, coda_access_size);
    357     return error;
    358 }
    359 
    360 int
    361 venus_readlink(void *mdp, ViceFid *fid,
    362 	struct ucred *cred, struct proc *p,
    363 /*out*/	char **str, int *len)
    364 {
    365     DECL(coda_readlink);			/* sets Isize & Osize */
    366     coda_readlink_size += CODA_MAXPATHLEN;
    367     ALLOC(coda_readlink);		/* sets inp & outp */
    368 
    369     /* send the open to venus. */
    370     INIT_IN(&inp->ih, CODA_READLINK, cred, p);
    371     inp->VFid = *fid;
    372 
    373     Osize += CODA_MAXPATHLEN;
    374     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    375     if (!error) {
    376 	    CODA_ALLOC(*str, char *, outp->count);
    377 	    *len = outp->count;
    378 	    bcopy((char *)outp + (int)(long)outp->data, *str, *len);
    379     }
    380 
    381     CODA_FREE(inp, coda_readlink_size);
    382     return error;
    383 }
    384 
    385 int
    386 venus_fsync(void *mdp, ViceFid *fid,
    387 	struct ucred *cred, struct proc *p)
    388 {
    389     DECL_NO_OUT(coda_fsync);		/* sets Isize & Osize */
    390     ALLOC_NO_OUT(coda_fsync);		/* sets inp & outp */
    391 
    392     /* send the open to venus. */
    393     INIT_IN(&inp->ih, CODA_FSYNC, cred, p);
    394     inp->VFid = *fid;
    395 
    396     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    397 
    398     CODA_FREE(inp, coda_fsync_size);
    399     return error;
    400 }
    401 
    402 int
    403 venus_lookup(void *mdp, ViceFid *fid,
    404     	const char *nm, int len,
    405 	struct ucred *cred, struct proc *p,
    406 /*out*/	ViceFid *VFid, int *vtype)
    407 {
    408     DECL(coda_lookup);			/* sets Isize & Osize */
    409     coda_lookup_size += len + 1;
    410     ALLOC(coda_lookup);			/* sets inp & outp */
    411 
    412     /* send the open to venus. */
    413     INIT_IN(&inp->ih, CODA_LOOKUP, cred, p);
    414     inp->VFid = *fid;
    415 
    416     /* NOTE:
    417      * Between version 1 and version 2 we have added an extra flag field
    418      * to this structure.  But because the string was at the end and because
    419      * of the weird way we represent strings by having the slot point to
    420      * where the string characters are in the "heap", we can just slip the
    421      * flag parameter in after the string slot pointer and veni that don't
    422      * know better won't see this new flag field ...
    423      * Otherwise we'd need two different venus_lookup functions.
    424      */
    425     inp->name = Isize;
    426     inp->flags = CLU_CASE_SENSITIVE;	/* doesn't really matter for BSD */
    427     STRCPY(name, nm, len);		/* increments Isize */
    428 
    429     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    430     if (!error) {
    431 	*VFid = outp->VFid;
    432 	*vtype = outp->vtype;
    433     }
    434 
    435     CODA_FREE(inp, coda_lookup_size);
    436     return error;
    437 }
    438 
    439 int
    440 venus_create(void *mdp, ViceFid *fid,
    441     	const char *nm, int len, int exclusive, int mode, struct vattr *va,
    442 	struct ucred *cred, struct proc *p,
    443 /*out*/	ViceFid *VFid, struct vattr *attr)
    444 {
    445     DECL(coda_create);			/* sets Isize & Osize */
    446     coda_create_size += len + 1;
    447     ALLOC(coda_create);			/* sets inp & outp */
    448 
    449     /* send the open to venus. */
    450     INIT_IN(&inp->ih, CODA_CREATE, cred, p);
    451     inp->VFid = *fid;
    452     inp->excl = exclusive ? C_O_EXCL : 0;
    453     inp->mode = mode<<6;
    454     CNV_V2VV_ATTR(&inp->attr, va);
    455 
    456     inp->name = Isize;
    457     STRCPY(name, nm, len);		/* increments Isize */
    458 
    459     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    460     if (!error) {
    461 	*VFid = outp->VFid;
    462 	CNV_VV2V_ATTR(attr, &outp->attr);
    463     }
    464 
    465     CODA_FREE(inp, coda_create_size);
    466     return error;
    467 }
    468 
    469 int
    470 venus_remove(void *mdp, ViceFid *fid,
    471         const char *nm, int len,
    472 	struct ucred *cred, struct proc *p)
    473 {
    474     DECL_NO_OUT(coda_remove);		/* sets Isize & Osize */
    475     coda_remove_size += len + 1;
    476     ALLOC_NO_OUT(coda_remove);		/* sets inp & outp */
    477 
    478     /* send the open to venus. */
    479     INIT_IN(&inp->ih, CODA_REMOVE, cred, p);
    480     inp->VFid = *fid;
    481 
    482     inp->name = Isize;
    483     STRCPY(name, nm, len);		/* increments Isize */
    484 
    485     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    486 
    487     CODA_FREE(inp, coda_remove_size);
    488     return error;
    489 }
    490 
    491 int
    492 venus_link(void *mdp, ViceFid *fid, ViceFid *tfid,
    493         const char *nm, int len,
    494 	struct ucred *cred, struct proc *p)
    495 {
    496     DECL_NO_OUT(coda_link);		/* sets Isize & Osize */
    497     coda_link_size += len + 1;
    498     ALLOC_NO_OUT(coda_link);		/* sets inp & outp */
    499 
    500     /* send the open to venus. */
    501     INIT_IN(&inp->ih, CODA_LINK, cred, p);
    502     inp->sourceFid = *fid;
    503     inp->destFid = *tfid;
    504 
    505     inp->tname = Isize;
    506     STRCPY(tname, nm, len);		/* increments Isize */
    507 
    508     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    509 
    510     CODA_FREE(inp, coda_link_size);
    511     return error;
    512 }
    513 
    514 int
    515 venus_rename(void *mdp, ViceFid *fid, ViceFid *tfid,
    516         const char *nm, int len, const char *tnm, int tlen,
    517 	struct ucred *cred, struct proc *p)
    518 {
    519     DECL_NO_OUT(coda_rename);		/* sets Isize & Osize */
    520     coda_rename_size += len + 1 + tlen + 1;
    521     ALLOC_NO_OUT(coda_rename);		/* sets inp & outp */
    522 
    523     /* send the open to venus. */
    524     INIT_IN(&inp->ih, CODA_RENAME, cred, p);
    525     inp->sourceFid = *fid;
    526     inp->destFid = *tfid;
    527 
    528     inp->srcname = Isize;
    529     STRCPY(srcname, nm, len);		/* increments Isize */
    530 
    531     inp->destname = Isize;
    532     STRCPY(destname, tnm, tlen);	/* increments Isize */
    533 
    534     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    535 
    536     CODA_FREE(inp, coda_rename_size);
    537     return error;
    538 }
    539 
    540 int
    541 venus_mkdir(void *mdp, ViceFid *fid,
    542     	const char *nm, int len, struct vattr *va,
    543 	struct ucred *cred, struct proc *p,
    544 /*out*/	ViceFid *VFid, struct vattr *ova)
    545 {
    546     DECL(coda_mkdir);			/* sets Isize & Osize */
    547     coda_mkdir_size += len + 1;
    548     ALLOC(coda_mkdir);			/* sets inp & outp */
    549 
    550     /* send the open to venus. */
    551     INIT_IN(&inp->ih, CODA_MKDIR, cred, p);
    552     inp->VFid = *fid;
    553     CNV_V2VV_ATTR(&inp->attr, va);
    554 
    555     inp->name = Isize;
    556     STRCPY(name, nm, len);		/* increments Isize */
    557 
    558     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    559     if (!error) {
    560 	*VFid = outp->VFid;
    561 	CNV_VV2V_ATTR(ova, &outp->attr);
    562     }
    563 
    564     CODA_FREE(inp, coda_mkdir_size);
    565     return error;
    566 }
    567 
    568 int
    569 venus_rmdir(void *mdp, ViceFid *fid,
    570     	const char *nm, int len,
    571 	struct ucred *cred, struct proc *p)
    572 {
    573     DECL_NO_OUT(coda_rmdir);		/* sets Isize & Osize */
    574     coda_rmdir_size += len + 1;
    575     ALLOC_NO_OUT(coda_rmdir);		/* sets inp & outp */
    576 
    577     /* send the open to venus. */
    578     INIT_IN(&inp->ih, CODA_RMDIR, cred, p);
    579     inp->VFid = *fid;
    580 
    581     inp->name = Isize;
    582     STRCPY(name, nm, len);		/* increments Isize */
    583 
    584     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    585 
    586     CODA_FREE(inp, coda_rmdir_size);
    587     return error;
    588 }
    589 
    590 int
    591 venus_symlink(void *mdp, ViceFid *fid,
    592         const char *lnm, int llen, const char *nm, int len, struct vattr *va,
    593 	struct ucred *cred, struct proc *p)
    594 {
    595     DECL_NO_OUT(coda_symlink);		/* sets Isize & Osize */
    596     coda_symlink_size += llen + 1 + len + 1;
    597     ALLOC_NO_OUT(coda_symlink);		/* sets inp & outp */
    598 
    599     /* send the open to venus. */
    600     INIT_IN(&inp->ih, CODA_SYMLINK, cred, p);
    601     inp->VFid = *fid;
    602     CNV_V2VV_ATTR(&inp->attr, va);
    603 
    604     inp->srcname = Isize;
    605     STRCPY(srcname, lnm, llen);		/* increments Isize */
    606 
    607     inp->tname = Isize;
    608     STRCPY(tname, nm, len);		/* increments Isize */
    609 
    610     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    611 
    612     CODA_FREE(inp, coda_symlink_size);
    613     return error;
    614 }
    615 
    616 int
    617 venus_readdir(void *mdp, ViceFid *fid,
    618     	int count, int offset,
    619 	struct ucred *cred, struct proc *p,
    620 /*out*/	char *buffer, int *len)
    621 {
    622     DECL(coda_readdir);			/* sets Isize & Osize */
    623     coda_readdir_size = VC_MAXMSGSIZE;
    624     ALLOC(coda_readdir);			/* sets inp & outp */
    625 
    626     /* send the open to venus. */
    627     INIT_IN(&inp->ih, CODA_READDIR, cred, p);
    628     inp->VFid = *fid;
    629     inp->count = count;
    630     inp->offset = offset;
    631 
    632     Osize = VC_MAXMSGSIZE;
    633     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    634     if (!error) {
    635 	bcopy((char *)outp + (int)(long)outp->data, buffer, outp->size);
    636 	*len = outp->size;
    637     }
    638 
    639     CODA_FREE(inp, coda_readdir_size);
    640     return error;
    641 }
    642 
    643 int
    644 venus_statfs(void *mdp, struct ucred *cred, struct proc *p,
    645    /*out*/   struct coda_statfs *fsp)
    646 {
    647     DECL(coda_statfs);			/* sets Isize & Osize */
    648     ALLOC(coda_statfs);			/* sets inp & outp */
    649 
    650     /* send the open to venus. */
    651     INIT_IN(&inp->ih, CODA_STATFS, cred, p);
    652 
    653     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    654     if (!error) {
    655         *fsp = outp->stat;
    656     }
    657 
    658     CODA_FREE(inp, coda_statfs_size);
    659     return error;
    660 }
    661 
    662 int
    663 venus_fhtovp(void *mdp, ViceFid *fid,
    664 	struct ucred *cred, struct proc *p,
    665 /*out*/	ViceFid *VFid, int *vtype)
    666 {
    667     DECL(coda_vget);			/* sets Isize & Osize */
    668     ALLOC(coda_vget);			/* sets inp & outp */
    669 
    670     /* Send the open to Venus. */
    671     INIT_IN(&inp->ih, CODA_VGET, cred, p);
    672     inp->VFid = *fid;
    673 
    674     error = coda_call(mdp, Isize, &Osize, (char *)inp);
    675     if (!error) {
    676 	*VFid = outp->VFid;
    677 	*vtype = outp->vtype;
    678     }
    679 
    680     CODA_FREE(inp, coda_vget_size);
    681     return error;
    682 }
    683