Home | History | Annotate | Line # | Download | only in coda
coda_venus.c revision 1.1
      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 
     30 /* $Header: /tank/opengrok/rsync2/NetBSD/src/sys/coda/coda_venus.c,v 1.1 1998/08/29 21:26:45 rvb Exp $ */
     31 
     32 #include <sys/param.h>
     33 #include <sys/systm.h>
     34 #include <sys/malloc.h>
     35 #include <sys/proc.h>
     36 #include <sys/select.h>
     37 #ifdef	__FreeBSD_version
     38 #include <sys/ioccom.h>
     39 #else
     40 #include <sys/ioctl.h>
     41 #endif
     42 /* for CNV_OFLAGS below */
     43 #include <sys/fcntl.h>
     44 
     45 #include <cfs/coda.h>
     46 #include <cfs/cnode.h>
     47 #include <cfs/cfs_venus.h>
     48 #include <cfs/pioctl.h>
     49 
     50 #define DECL_NO_IN(name) 				\
     51     struct cfs_in_hdr *inp;				\
     52     struct name ## _out *outp;				\
     53     int name ## _size = sizeof (struct cfs_in_hdr);	\
     54     int Isize = sizeof (struct cfs_in_hdr);		\
     55     int Osize = sizeof (struct name ## _out);		\
     56     int error
     57 
     58 #define DECL(name)					\
     59     struct name ## _in *inp;				\
     60     struct name ## _out *outp;				\
     61     int name ## _size = sizeof (struct name ## _in);	\
     62     int Isize = sizeof (struct name ## _in);		\
     63     int Osize = sizeof (struct name ## _out);		\
     64     int error
     65 
     66 #define DECL_NO_OUT(name)				\
     67     struct name ## _in *inp;				\
     68     struct cfs_out_hdr *outp;				\
     69     int name ## _size = sizeof (struct name ## _in);	\
     70     int Isize = sizeof (struct name ## _in);		\
     71     int Osize = sizeof (struct cfs_out_hdr);		\
     72     int error
     73 
     74 #define ALLOC_NO_IN(name)				\
     75     if (Osize > name ## _size)				\
     76     	name ## _size = Osize;				\
     77     CFS_ALLOC(inp, struct cfs_in_hdr *, name ## _size);\
     78     outp = (struct name ## _out *) inp
     79 
     80 #define ALLOC(name)					\
     81     if (Osize > name ## _size)				\
     82     	name ## _size = Osize;				\
     83     CFS_ALLOC(inp, struct name ## _in *, name ## _size);\
     84     outp = (struct name ## _out *) inp
     85 
     86 #define ALLOC_NO_OUT(name)				\
     87     if (Osize > name ## _size)				\
     88     	name ## _size = Osize;				\
     89     CFS_ALLOC(inp, struct name ## _in *, name ## _size);\
     90     outp = (struct cfs_out_hdr *) inp
     91 
     92 #define STRCPY(struc, name, len) \
     93     bcopy(name, (char *)inp + (int)inp->struc, len); \
     94     ((char*)inp + (int)inp->struc)[len++] = 0; \
     95     Isize += len
     96 
     97 #define INIT_IN(in, op, ident, p) \
     98 	  (in)->opcode = (op); \
     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           if (ident != NOCRED) {                              \
    103 	      (in)->cred.cr_uid = ident->cr_uid;              \
    104 	      (in)->cred.cr_groupid = ident->cr_gid;          \
    105           } else {                                            \
    106 	      bzero(&((in)->cred),sizeof(struct coda_cred));  \
    107 	      (in)->cred.cr_uid = -1;                         \
    108 	      (in)->cred.cr_groupid = -1;                     \
    109           }                                                   \
    110 
    111 #define	CNV_OFLAG(to, from) 				\
    112     do { 						\
    113 	  to = 0;					\
    114 	  if (from & FREAD)   to |= C_O_READ; 		\
    115 	  if (from & FWRITE)  to |= C_O_WRITE; 		\
    116 	  if (from & O_TRUNC) to |= C_O_TRUNC; 		\
    117 	  if (from & O_EXCL)  to |= C_O_EXCL; 		\
    118     } while (0)
    119 
    120 #define CNV_VV2V_ATTR(top, fromp) \
    121 	do { \
    122 		(top)->va_type = (fromp)->va_type; \
    123 		(top)->va_mode = (fromp)->va_mode; \
    124 		(top)->va_nlink = (fromp)->va_nlink; \
    125 		(top)->va_uid = (fromp)->va_uid; \
    126 		(top)->va_gid = (fromp)->va_gid; \
    127 		(top)->va_fsid = VNOVAL; \
    128 		(top)->va_fileid = (fromp)->va_fileid; \
    129 		(top)->va_size = (fromp)->va_size; \
    130 		(top)->va_blocksize = (fromp)->va_blocksize; \
    131 		(top)->va_atime = (fromp)->va_atime; \
    132 		(top)->va_mtime = (fromp)->va_mtime; \
    133 		(top)->va_ctime = (fromp)->va_ctime; \
    134 		(top)->va_gen = (fromp)->va_gen; \
    135 		(top)->va_flags = (fromp)->va_flags; \
    136 		(top)->va_rdev = (fromp)->va_rdev; \
    137 		(top)->va_bytes = (fromp)->va_bytes; \
    138 		(top)->va_filerev = (fromp)->va_filerev; \
    139 		(top)->va_vaflags = VNOVAL; \
    140 		(top)->va_spare = VNOVAL; \
    141 	} while (0)
    142 
    143 #define CNV_V2VV_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_fileid = (fromp)->va_fileid; \
    151 		(top)->va_size = (fromp)->va_size; \
    152 		(top)->va_blocksize = (fromp)->va_blocksize; \
    153 		(top)->va_atime = (fromp)->va_atime; \
    154 		(top)->va_mtime = (fromp)->va_mtime; \
    155 		(top)->va_ctime = (fromp)->va_ctime; \
    156 		(top)->va_gen = (fromp)->va_gen; \
    157 		(top)->va_flags = (fromp)->va_flags; \
    158 		(top)->va_rdev = (fromp)->va_rdev; \
    159 		(top)->va_bytes = (fromp)->va_bytes; \
    160 		(top)->va_filerev = (fromp)->va_filerev; \
    161 	} while (0)
    162 
    163 
    164 int
    165 venus_root(void *mdp,
    166 	struct ucred *cred, struct proc *p,
    167 /*out*/	ViceFid *VFid)
    168 {
    169     DECL_NO_IN(cfs_root);		/* sets Isize & Osize */
    170     ALLOC_NO_IN(cfs_root);		/* sets inp & outp */
    171 
    172     /* send the open to venus. */
    173     INIT_IN(inp, CFS_ROOT, cred, p);
    174 
    175     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    176     if (!error)
    177 	*VFid = outp->VFid;
    178 
    179     CFS_FREE(inp, cfs_root_size);
    180     return error;
    181 }
    182 
    183 int
    184 venus_open(void *mdp, ViceFid *fid, int flag,
    185 	struct ucred *cred, struct proc *p,
    186 /*out*/	dev_t *dev, ino_t *inode)
    187 {
    188     int cflag;
    189     DECL(cfs_open);			/* sets Isize & Osize */
    190     ALLOC(cfs_open);			/* sets inp & outp */
    191 
    192     /* send the open to venus. */
    193     INIT_IN(&inp->ih, CFS_OPEN, cred, p);
    194     inp->VFid = *fid;
    195     CNV_OFLAG(cflag, flag);
    196     inp->flags = cflag;
    197 
    198     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    199     if (!error) {
    200 	*dev =  outp->dev;
    201 	*inode = outp->inode;
    202     }
    203 
    204     CFS_FREE(inp, cfs_open_size);
    205     return error;
    206 }
    207 
    208 int
    209 venus_close(void *mdp, ViceFid *fid, int flag,
    210 	struct ucred *cred, struct proc *p)
    211 {
    212     int cflag;
    213     DECL_NO_OUT(cfs_close);		/* sets Isize & Osize */
    214     ALLOC_NO_OUT(cfs_close);		/* sets inp & outp */
    215 
    216     INIT_IN(&inp->ih, CFS_CLOSE, cred, p);
    217     inp->VFid = *fid;
    218     CNV_OFLAG(cflag, flag);
    219     inp->flags = cflag;
    220 
    221     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    222 
    223     CFS_FREE(inp, cfs_close_size);
    224     return error;
    225 }
    226 
    227 /*
    228  * these two calls will not exist!!!  the container file is read/written
    229  * directly.
    230  */
    231 void
    232 venus_read(void)
    233 {
    234 }
    235 
    236 void
    237 venus_write(void)
    238 {
    239 }
    240 
    241 /*
    242  * this is a bit sad too.  the ioctl's are for the control file, not for
    243  * normal files.
    244  */
    245 int
    246 venus_ioctl(void *mdp, ViceFid *fid,
    247 	int com, int flag, caddr_t data,
    248 	struct ucred *cred, struct proc *p)
    249 {
    250     DECL(cfs_ioctl);			/* sets Isize & Osize */
    251     struct PioctlData *iap = (struct PioctlData *)data;
    252     int tmp;
    253 
    254     cfs_ioctl_size = VC_MAXMSGSIZE;
    255     ALLOC(cfs_ioctl);			/* sets inp & outp */
    256 
    257     INIT_IN(&inp->ih, CFS_IOCTL, cred, p);
    258     inp->VFid = *fid;
    259 
    260     /* command was mutated by increasing its size field to reflect the
    261      * path and follow args. we need to subtract that out before sending
    262      * the command to venus.
    263      */
    264     inp->cmd = (com & ~(IOCPARM_MASK << 16));
    265     tmp = ((com >> 16) & IOCPARM_MASK) - sizeof (char *) - sizeof (int);
    266     inp->cmd |= (tmp & IOCPARM_MASK) <<	16;
    267 
    268     inp->rwflag = flag;
    269     inp->len = iap->vi.in_size;
    270     inp->data = (char *)(sizeof (struct cfs_ioctl_in));
    271 
    272     error = copyin(iap->vi.in, (char*)inp + (int)inp->data,
    273 		   iap->vi.in_size);
    274     if (error) {
    275 	CFS_FREE(inp, cfs_ioctl_size);
    276 	return(error);
    277     }
    278 
    279     Osize = VC_MAXMSGSIZE;
    280     error = cfscall(mdp, Isize + iap->vi.in_size, &Osize, (char *)inp);
    281 
    282 	/* copy out the out buffer. */
    283     if (!error) {
    284 	if (outp->len > iap->vi.out_size) {
    285 	    error = EINVAL;
    286 	} else {
    287 	    error = copyout((char *)outp + (int)outp->data,
    288 			    iap->vi.out, iap->vi.out_size);
    289 	}
    290     }
    291 
    292     CFS_FREE(inp, cfs_ioctl_size);
    293     return error;
    294 }
    295 
    296 int
    297 venus_getattr(void *mdp, ViceFid *fid,
    298 	struct ucred *cred, struct proc *p,
    299 /*out*/	struct vattr *vap)
    300 {
    301     DECL(cfs_getattr);			/* sets Isize & Osize */
    302     ALLOC(cfs_getattr);			/* sets inp & outp */
    303 
    304     /* send the open to venus. */
    305     INIT_IN(&inp->ih, CFS_GETATTR, cred, p);
    306     inp->VFid = *fid;
    307 
    308     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    309     if (!error) {
    310 	CNV_VV2V_ATTR(vap, &outp->attr);
    311     }
    312 
    313     CFS_FREE(inp, cfs_getattr_size);
    314     return error;
    315 }
    316 
    317 int
    318 venus_setattr(void *mdp, ViceFid *fid, struct vattr *vap,
    319 	struct ucred *cred, struct proc *p)
    320 {
    321     DECL_NO_OUT(cfs_setattr);		/* sets Isize & Osize */
    322     ALLOC_NO_OUT(cfs_setattr);		/* sets inp & outp */
    323 
    324     /* send the open to venus. */
    325     INIT_IN(&inp->ih, CFS_SETATTR, cred, p);
    326     inp->VFid = *fid;
    327     CNV_V2VV_ATTR(&inp->attr, vap);
    328 
    329     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    330 
    331     CFS_FREE(inp, cfs_setattr_size);
    332     return error;
    333 }
    334 
    335 int
    336 venus_access(void *mdp, ViceFid *fid, int mode,
    337 	struct ucred *cred, struct proc *p)
    338 {
    339     DECL_NO_OUT(cfs_access);		/* sets Isize & Osize */
    340     ALLOC_NO_OUT(cfs_access);		/* sets inp & outp */
    341 
    342     /* send the open to venus. */
    343     INIT_IN(&inp->ih, CFS_ACCESS, cred, p);
    344     inp->VFid = *fid;
    345 #ifdef	NetBSD1_3
    346     inp->flags = mode;
    347 #else
    348     inp->flags = mode>>6;
    349 #endif
    350 
    351     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    352 
    353     CFS_FREE(inp, cfs_access_size);
    354     return error;
    355 }
    356 
    357 int
    358 venus_readlink(void *mdp, ViceFid *fid,
    359 	struct ucred *cred, struct proc *p,
    360 /*out*/	char **str, int *len)
    361 {
    362     DECL(cfs_readlink);			/* sets Isize & Osize */
    363     cfs_readlink_size += CFS_MAXPATHLEN;
    364     ALLOC(cfs_readlink);		/* sets inp & outp */
    365 
    366     /* send the open to venus. */
    367     INIT_IN(&inp->ih, CFS_READLINK, cred, p);
    368     inp->VFid = *fid;
    369 
    370     Osize += CFS_MAXPATHLEN;
    371     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    372     if (!error) {
    373 	    CFS_ALLOC(*str, char *, outp->count);
    374 	    *len = outp->count;
    375 	    bcopy((char *)outp + (int)outp->data, *str, *len);
    376     }
    377 
    378     CFS_FREE(inp, cfs_readlink_size);
    379     return error;
    380 }
    381 
    382 int
    383 venus_fsync(void *mdp, ViceFid *fid,
    384 	struct ucred *cred, struct proc *p)
    385 {
    386     DECL_NO_OUT(cfs_fsync);		/* sets Isize & Osize */
    387     ALLOC_NO_OUT(cfs_fsync);		/* sets inp & outp */
    388 
    389     /* send the open to venus. */
    390     INIT_IN(&inp->ih, CFS_FSYNC, cred, p);
    391     inp->VFid = *fid;
    392 
    393     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    394 
    395     CFS_FREE(inp, cfs_fsync_size);
    396     return error;
    397 }
    398 
    399 int
    400 venus_lookup(void *mdp, ViceFid *fid,
    401     	const char *nm, int len,
    402 	struct ucred *cred, struct proc *p,
    403 /*out*/	ViceFid *VFid, int *vtype)
    404 {
    405     DECL(cfs_lookup);			/* sets Isize & Osize */
    406     cfs_lookup_size += len + 1;
    407     ALLOC(cfs_lookup);			/* sets inp & outp */
    408 
    409     /* send the open to venus. */
    410     INIT_IN(&inp->ih, CFS_LOOKUP, cred, p);
    411     inp->VFid = *fid;
    412 
    413     inp->name = Isize;
    414     STRCPY(name, nm, len);		/* increments Isize */
    415 
    416     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    417     if (!error) {
    418 	*VFid = outp->VFid;
    419 	*vtype = outp->vtype;
    420     }
    421 
    422     CFS_FREE(inp, cfs_lookup_size);
    423     return error;
    424 }
    425 
    426 int
    427 venus_create(void *mdp, ViceFid *fid,
    428     	const char *nm, int len, int exclusive, int mode, struct vattr *va,
    429 	struct ucred *cred, struct proc *p,
    430 /*out*/	ViceFid *VFid, struct vattr *attr)
    431 {
    432     DECL(cfs_create);			/* sets Isize & Osize */
    433     cfs_create_size += len + 1;
    434     ALLOC(cfs_create);			/* sets inp & outp */
    435 
    436     /* send the open to venus. */
    437     INIT_IN(&inp->ih, CFS_CREATE, cred, p);
    438     inp->VFid = *fid;
    439     inp->excl = exclusive ? C_O_EXCL : 0;
    440 #ifdef	NetBSD1_3
    441     inp->mode = mode<<6;
    442 #else
    443     inp->mode = mode;
    444 #endif
    445     CNV_V2VV_ATTR(&inp->attr, va);
    446 
    447     inp->name = Isize;
    448     STRCPY(name, nm, len);		/* increments Isize */
    449 
    450     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    451     if (!error) {
    452 	*VFid = outp->VFid;
    453 	CNV_VV2V_ATTR(attr, &outp->attr);
    454     }
    455 
    456     CFS_FREE(inp, cfs_create_size);
    457     return error;
    458 }
    459 
    460 int
    461 venus_remove(void *mdp, ViceFid *fid,
    462         const char *nm, int len,
    463 	struct ucred *cred, struct proc *p)
    464 {
    465     DECL_NO_OUT(cfs_remove);		/* sets Isize & Osize */
    466     cfs_remove_size += len + 1;
    467     ALLOC_NO_OUT(cfs_remove);		/* sets inp & outp */
    468 
    469     /* send the open to venus. */
    470     INIT_IN(&inp->ih, CFS_REMOVE, cred, p);
    471     inp->VFid = *fid;
    472 
    473     inp->name = Isize;
    474     STRCPY(name, nm, len);		/* increments Isize */
    475 
    476     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    477 
    478     CFS_FREE(inp, cfs_remove_size);
    479     return error;
    480 }
    481 
    482 int
    483 venus_link(void *mdp, ViceFid *fid, ViceFid *tfid,
    484         const char *nm, int len,
    485 	struct ucred *cred, struct proc *p)
    486 {
    487     DECL_NO_OUT(cfs_link);		/* sets Isize & Osize */
    488     cfs_link_size += len + 1;
    489     ALLOC_NO_OUT(cfs_link);		/* sets inp & outp */
    490 
    491     /* send the open to venus. */
    492     INIT_IN(&inp->ih, CFS_LINK, cred, p);
    493     inp->sourceFid = *fid;
    494     inp->destFid = *tfid;
    495 
    496     inp->tname = Isize;
    497     STRCPY(tname, nm, len);		/* increments Isize */
    498 
    499     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    500 
    501     CFS_FREE(inp, cfs_link_size);
    502     return error;
    503 }
    504 
    505 int
    506 venus_rename(void *mdp, ViceFid *fid, ViceFid *tfid,
    507         const char *nm, int len, const char *tnm, int tlen,
    508 	struct ucred *cred, struct proc *p)
    509 {
    510     DECL_NO_OUT(cfs_rename);		/* sets Isize & Osize */
    511     cfs_rename_size += len + 1 + tlen + 1;
    512     ALLOC_NO_OUT(cfs_rename);		/* sets inp & outp */
    513 
    514     /* send the open to venus. */
    515     INIT_IN(&inp->ih, CFS_RENAME, cred, p);
    516     inp->sourceFid = *fid;
    517     inp->destFid = *tfid;
    518 
    519     inp->srcname = Isize;
    520     STRCPY(srcname, nm, len);		/* increments Isize */
    521 
    522     inp->destname = Isize;
    523     STRCPY(destname, tnm, tlen);	/* increments Isize */
    524 
    525     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    526 
    527     CFS_FREE(inp, cfs_rename_size);
    528     return error;
    529 }
    530 
    531 int
    532 venus_mkdir(void *mdp, ViceFid *fid,
    533     	const char *nm, int len, struct vattr *va,
    534 	struct ucred *cred, struct proc *p,
    535 /*out*/	ViceFid *VFid, struct vattr *ova)
    536 {
    537     DECL(cfs_mkdir);			/* sets Isize & Osize */
    538     cfs_mkdir_size += len + 1;
    539     ALLOC(cfs_mkdir);			/* sets inp & outp */
    540 
    541     /* send the open to venus. */
    542     INIT_IN(&inp->ih, CFS_MKDIR, cred, p);
    543     inp->VFid = *fid;
    544     CNV_V2VV_ATTR(&inp->attr, va);
    545 
    546     inp->name = Isize;
    547     STRCPY(name, nm, len);		/* increments Isize */
    548 
    549     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    550     if (!error) {
    551 	*VFid = outp->VFid;
    552 	CNV_VV2V_ATTR(ova, &outp->attr);
    553     }
    554 
    555     CFS_FREE(inp, cfs_mkdir_size);
    556     return error;
    557 }
    558 
    559 int
    560 venus_rmdir(void *mdp, ViceFid *fid,
    561     	const char *nm, int len,
    562 	struct ucred *cred, struct proc *p)
    563 {
    564     DECL_NO_OUT(cfs_rmdir);		/* sets Isize & Osize */
    565     cfs_rmdir_size += len + 1;
    566     ALLOC_NO_OUT(cfs_rmdir);		/* sets inp & outp */
    567 
    568     /* send the open to venus. */
    569     INIT_IN(&inp->ih, CFS_RMDIR, cred, p);
    570     inp->VFid = *fid;
    571 
    572     inp->name = Isize;
    573     STRCPY(name, nm, len);		/* increments Isize */
    574 
    575     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    576 
    577     CFS_FREE(inp, cfs_rmdir_size);
    578     return error;
    579 }
    580 
    581 int
    582 venus_symlink(void *mdp, ViceFid *fid,
    583         const char *lnm, int llen, const char *nm, int len, struct vattr *va,
    584 	struct ucred *cred, struct proc *p)
    585 {
    586     DECL_NO_OUT(cfs_symlink);		/* sets Isize & Osize */
    587     cfs_symlink_size += llen + 1 + len + 1;
    588     ALLOC_NO_OUT(cfs_symlink);		/* sets inp & outp */
    589 
    590     /* send the open to venus. */
    591     INIT_IN(&inp->ih, CFS_SYMLINK, cred, p);
    592     inp->VFid = *fid;
    593     CNV_V2VV_ATTR(&inp->attr, va);
    594 
    595     inp->srcname = Isize;
    596     STRCPY(srcname, lnm, llen);		/* increments Isize */
    597 
    598     inp->tname = Isize;
    599     STRCPY(tname, nm, len);		/* increments Isize */
    600 
    601     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    602 
    603     CFS_FREE(inp, cfs_symlink_size);
    604     return error;
    605 }
    606 
    607 int
    608 venus_readdir(void *mdp, ViceFid *fid,
    609     	int count, int offset,
    610 	struct ucred *cred, struct proc *p,
    611 /*out*/	char *buffer, int *len)
    612 {
    613     DECL(cfs_readdir);			/* sets Isize & Osize */
    614     cfs_readdir_size = VC_MAXMSGSIZE;
    615     ALLOC(cfs_readdir);			/* sets inp & outp */
    616 
    617     /* send the open to venus. */
    618     INIT_IN(&inp->ih, CFS_READDIR, cred, p);
    619     inp->VFid = *fid;
    620     inp->count = count;
    621     inp->offset = offset;
    622 
    623     Osize = VC_MAXMSGSIZE;
    624     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    625     if (!error) {
    626 	bcopy((char *)outp + (int)outp->data, buffer, outp->size);
    627 	*len = outp->size;
    628     }
    629 
    630     CFS_FREE(inp, cfs_readdir_size);
    631     return error;
    632 }
    633 
    634 int
    635 venus_fhtovp(void *mdp, ViceFid *fid,
    636 	struct ucred *cred, struct proc *p,
    637 /*out*/	ViceFid *VFid, int *vtype)
    638 {
    639     DECL(cfs_vget);			/* sets Isize & Osize */
    640     ALLOC(cfs_vget);			/* sets inp & outp */
    641 
    642     /* Send the open to Venus. */
    643     INIT_IN(&inp->ih, CFS_VGET, cred, p);
    644     inp->VFid = *fid;
    645 
    646     error = cfscall(mdp, Isize, &Osize, (char *)inp);
    647     if (!error) {
    648 	*VFid = outp->VFid;
    649 	*vtype = outp->vtype;
    650     }
    651 
    652     CFS_FREE(inp, cfs_vget_size);
    653     return error;
    654 }
    655