Fix pioctl input and output handling
[openafs.git] / src / afs / afs_pioctl.c
index 597dd61..26f45c6 100644 (file)
@@ -10,8 +10,6 @@
 #include <afsconfig.h>
 #include "afs/param.h"
 
-RCSID
-    ("$Header$");
 
 #include "afs/sysincludes.h"   /* Standard vendor system headers */
 #ifdef AFS_OBSD_ENV
@@ -33,7 +31,6 @@ afs_int32 afs_showflags = GAGUSER | GAGCONSOLE;       /* show all messages */
 
 #ifdef AFS_DISCON_ENV
 afs_int32 afs_is_disconnected;
-afs_int32 afs_is_logging;
 afs_int32 afs_is_discon_rw;
 /* On reconnection, turn this knob on until it finishes,
  * then turn it off.
@@ -41,24 +38,185 @@ afs_int32 afs_is_discon_rw;
 afs_int32 afs_in_sync = 0;
 #endif
 
+struct afs_pdata {
+    char *ptr;
+    size_t remaining;
+};
+
+/*
+ * A set of handy little functions for encoding and decoding
+ * pioctls without losing your marbles, or memory integrity
+ */
+
+static_inline int
+afs_pd_alloc(struct afs_pdata *apd, size_t size) {
+
+    if (size > AFS_LRALLOCSIZ)
+       apd->ptr = osi_Alloc(size + 1);
+    else
+       apd->ptr = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+
+    if (apd->ptr == NULL)
+       return ENOMEM;
+
+    apd->remaining = size;
+
+    return 0;
+}
+
+static_inline void
+afs_pd_free(struct afs_pdata *apd) {
+    if (apd->ptr == NULL)
+       return;
+
+    if (apd->remaining > AFS_LRALLOCSIZ)
+       osi_Free(apd->ptr, apd->remaining + 1);
+    else
+       osi_FreeLargeSpace(apd->ptr);
+
+    apd->ptr = NULL;
+    apd->remaining = 0;
+}
+
+static_inline char *
+afs_pd_where(struct afs_pdata *apd) {
+    return apd ? apd->ptr : NULL;
+}
+
+static_inline size_t
+afs_pd_remaining(struct afs_pdata *apd) {
+    return apd ? apd->remaining : 0;
+}
+
+static_inline int
+afs_pd_skip(struct afs_pdata *apd, size_t skip) {
+    if (apd == NULL || apd->remaining < skip)
+       return EINVAL;
+    apd->remaining -= skip;
+    apd->ptr += skip;
+
+    return 0;
+}
+
+static_inline int
+afs_pd_getInt(struct afs_pdata *apd, afs_int32 *val) {
+    if (apd == NULL || apd->remaining < sizeof(afs_int32))
+       return EINVAL;
+    apd->remaining -= sizeof(afs_int32);
+    *val = *(afs_int32 *)apd->ptr;
+    apd->ptr += sizeof(afs_int32);
+    return 0;
+}
+
+static_inline int
+afs_pd_getUint(struct afs_pdata *apd, afs_uint32 *val) {
+    return afs_pd_getInt(apd, (afs_int32 *)val);
+}
+
+static_inline int
+afs_pd_getBytes(struct afs_pdata *apd, void *dest, size_t bytes) {
+    if (apd == NULL || apd->remaining < bytes)
+       return EINVAL;
+    apd->remaining -= bytes;
+    memcpy(dest, apd->ptr, bytes);
+    apd->ptr += bytes;
+    return 0;
+}
+
+static_inline void *
+afs_pd_inline(struct afs_pdata *apd, size_t bytes) {
+    void *ret;
+
+    if (apd == NULL || apd->remaining < bytes)
+       return NULL;
+
+    ret = apd->ptr;
+
+    apd->remaining -= bytes;
+    apd->ptr += bytes;
+
+    return ret;
+}
+
+static_inline int
+afs_pd_getString(struct afs_pdata *apd, char *str, size_t maxLen) {
+    size_t len;
+
+    if (apd == NULL || apd->remaining <= 0)
+       return EINVAL;
+    len = strlen(apd->ptr) + 1;
+    if (len > maxLen)
+       return E2BIG;
+    memcpy(str, apd->ptr, len);
+    apd->ptr += len;
+    apd->remaining -= len;
+    return 0;
+}
+
+static_inline int
+afs_pd_getStringPtr(struct afs_pdata *apd, char **str) {
+    size_t len;
+
+    if (apd == NULL || apd->remaining <= 0)
+       return EINVAL;
+    len = strlen(apd->ptr) + 1;
+    *str = apd->ptr;
+    apd->ptr += len;
+    apd->remaining -= len;
+    return 0;
+}
+
+static_inline int
+afs_pd_putInt(struct afs_pdata *apd, afs_int32 val) {
+    if (apd == NULL || apd->remaining < sizeof(afs_int32))
+       return E2BIG;
+    *(afs_int32 *)apd->ptr = val;
+    apd->ptr += sizeof(afs_int32);
+    apd->remaining -= sizeof(afs_int32);
+
+    return 0;
+}
+
+static_inline int
+afs_pd_putBytes(struct afs_pdata *apd, const void *bytes, size_t len) {
+    if (apd == NULL || apd->remaining < len)
+       return E2BIG;
+    memcpy(apd->ptr, bytes, len);
+    apd->ptr += len;
+    apd->remaining -= len;
+    return 0;
+}
+
+static_inline int
+afs_pd_putString(struct afs_pdata *apd, char *str) {
+
+    /* Add 1 so we copy the NULL too */
+    return afs_pd_putBytes(apd, str, strlen(str) +1);
+}
+
 /*!
  * \defgroup pioctl Path IOCTL functions
  *
  * DECL_PIOCTL is a macro defined to contain the following parameters for functions:
  *
- * \param[in] avc      the AFS vcache structure in use by pioctl
- * \param[in] afun     not in use
- * \param[in] areq     the AFS vrequest structure
- * \param[in] ain      as defined by the function
- * \param[in] aout     as defined by the function
- * \param[in] ainSize  size of ain
- * \param[in] aoutSize size of aout
- * \param[in] acred    UNIX credentials structure underlying the operation
+ * \param[in] avc
+ *     the AFS vcache structure in use by pioctl
+ * \param[in] afun
+ *     not in use
+ * \param[in] areq
+ *     the AFS vrequest structure
+ * \param[in] ain
+ *     an afs_pdata block describing the data received from the caller
+ * \param[in] aout
+ *     an afs_pdata block describing a pre-allocated block for output
+ * \param[in] acred
+ *     UNIX credentials structure underlying the operation
  */
 
-#define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
-       char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
-       struct AFS_UCRED **acred)
+#define DECL_PIOCTL(x) \
+       static int x(struct vcache *avc, int afun, struct vrequest *areq, \
+                    struct afs_pdata *ain, struct afs_pdata *aout, \
+                    afs_ucred_t **acred)
 
 /* Prototypes for pioctl routines */
 DECL_PIOCTL(PGetFID);
@@ -114,12 +272,13 @@ DECL_PIOCTL(PFlushMount);
 DECL_PIOCTL(PRxStatProc);
 DECL_PIOCTL(PRxStatPeer);
 DECL_PIOCTL(PPrefetchFromTape);
-DECL_PIOCTL(PResidencyCmd);
+DECL_PIOCTL(PFsCmd);
 DECL_PIOCTL(PCallBackAddr);
 DECL_PIOCTL(PDiscon);
 DECL_PIOCTL(PNFSNukeCreds);
 DECL_PIOCTL(PNewUuid);
 DECL_PIOCTL(PPrecache); 
+DECL_PIOCTL(PGetPAG);
 #if defined(AFS_CACHE_BYPASS)
 DECL_PIOCTL(PSetCachingThreshold);
 DECL_PIOCTL(PSetCachingBlkSize);
@@ -136,20 +295,20 @@ DECL_PIOCTL(PSetCachingBlkSize);
 /* Prototypes for private routines */
 #ifdef AFS_NEED_CLIENTCONTEXT
 static int HandleClientContext(struct afs_ioctl *ablob, int *com,
-                              struct AFS_UCRED **acred,
-                              struct AFS_UCRED *credp);
+                              afs_ucred_t **acred,
+                              afs_ucred_t *credp);
 #endif
 int HandleIoctl(register struct vcache *avc, register afs_int32 acom,
                struct afs_ioctl *adata);
 int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
                     register struct afs_ioctl *ablob, int afollow,
-                    struct AFS_UCRED **acred);
-static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
-                   struct AFS_UCRED *acred);
+                    afs_ucred_t **acred);
+static int Prefetch(uparmtype apath, struct afs_ioctl *adata, int afollow,
+                   afs_ucred_t *acred);
 
 typedef int (*pioctlFunction) (struct vcache *, int, struct vrequest *,
-                              char *, char *, afs_int32, afs_int32 *,
-                              struct AFS_UCRED **);
+                              struct afs_pdata *, struct afs_pdata *,
+                              afs_ucred_t **);
 
 static pioctlFunction VpioctlSw[] = {
     PBogus,                    /* 0 */
@@ -219,7 +378,7 @@ static pioctlFunction VpioctlSw[] = {
        PBogus,                 /* 64 -- arla: force cache check */
        PBogus,                 /* 65 -- arla: break callback */
        PPrefetchFromTape,      /* 66 -- MR-AFS: prefetch file from tape */
-       PResidencyCmd,          /* 67 -- MR-AFS: generic commnd interface */
+       PFsCmd,                 /* 67 -- RXOSD: generic commnd interface */
        PBogus,                 /* 68 -- arla: fetch stats */
        PGetVnodeXStatus2,      /* 69 - get caller access and some vcache status */
 };
@@ -238,9 +397,10 @@ static pioctlFunction CpioctlSw[] = {
     PBogus,                     /* 0 */
     PBogus,                     /* 0 */
     PPrecache,                  /* 12 */
+    PGetPAG,                    /* 13 */
 };
 
-static int (*(OpioctlSw[])) () = {
+static pioctlFunction OpioctlSw[]  = {
     PBogus,                    /* 0 */
     PNFSNukeCreds,             /* 1 -- nuke all creds for NFS client */
 #if defined(AFS_CACHE_BYPASS)
@@ -264,8 +424,9 @@ HandleIoctl(register struct vcache *avc, register afs_int32 acom,
 
     switch (acom & 0xff) {
     case 1:
-       avc->states |= CSafeStore;
+       avc->f.states |= CSafeStore;
        avc->asynchrony = 0;
+       /* SXW - Should we force a MetaData flush for this flag setting */
        break;
 
        /* case 2 used to be abort store, but this is no longer provided,
@@ -277,7 +438,7 @@ HandleIoctl(register struct vcache *avc, register afs_int32 acom,
            register struct cell *tcell;
            register afs_int32 i;
 
-           tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
+           tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
            if (tcell) {
                i = strlen(tcell->cellName) + 1;        /* bytes to copy out */
 
@@ -315,7 +476,6 @@ HandleIoctl(register struct vcache *avc, register afs_int32 acom,
     return code;               /* so far, none implemented */
 }
 
-
 #ifdef AFS_AIX_ENV
 /* For aix we don't temporarily bypass ioctl(2) but rather do our
  * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
@@ -382,32 +542,32 @@ afs_ioctl(OSI_VN_DECL(tvc), int cmd, void *arg, int flag, cred_t * cr,
    */
 /* AFS_HPUX102 and up uses VNODE ioctl instead */
 #if !defined(AFS_HPUX102_ENV) && !defined(AFS_DARWIN80_ENV)
-#if !defined(AFS_SGI_ENV)
-#ifdef AFS_AIX32_ENV
-#ifdef AFS_AIX51_ENV
-#ifdef __64BIT__
+# if !defined(AFS_SGI_ENV)
+#  ifdef       AFS_AIX32_ENV
+#   ifdef AFS_AIX51_ENV
+#    ifdef __64BIT__
 int
 kioctl(int fdes, int com, caddr_t arg, caddr_t ext, caddr_t arg2, 
           caddr_t arg3)
-#else /* __64BIT__ */
+#    else /* __64BIT__ */
 int
 kioctl32(int fdes, int com, caddr_t arg, caddr_t ext, caddr_t arg2, 
             caddr_t arg3)
-#endif /* __64BIT__ */
-#else
+#    endif /* __64BIT__ */
+#   else
 int
 kioctl(int fdes, int com, caddr_t arg, caddr_t ext)
-#endif
+#   endif
 {
     struct a {
        int fd, com;
        caddr_t arg, ext;
-#ifdef AFS_AIX51_ENV
+#   ifdef AFS_AIX51_ENV
        caddr_t arg2, arg3;
-#endif
+#   endif
     } u_uap, *uap = &u_uap;
-#else
-#if defined(AFS_SUN5_ENV)
+#  else
+#   if defined(AFS_SUN5_ENV)
 
 struct afs_ioctl_sys {
     int fd;
@@ -418,23 +578,14 @@ struct afs_ioctl_sys {
 int 
 afs_xioctl(struct afs_ioctl_sys *uap, rval_t *rvp)
 {
-#elif defined(AFS_OSF_ENV)
-int 
-afs_xioctl(struct proc *p, void *args, long *retval)
-{
-    struct a {
-       long fd;
-       u_long com;
-       caddr_t arg;
-    } *uap = (struct a *)args;
-#elif defined(AFS_FBSD50_ENV)
-#define arg data
+#   elif defined(AFS_FBSD50_ENV)
+#    define arg data
 int
 afs_xioctl(struct thread *td, register struct ioctl_args *uap, 
           register_t *retval)
 {
-    struct proc *p = td->td_proc;
-#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+    afs_proc_t *p = td->td_proc;
+#   elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 struct ioctl_args {
     int fd;
     u_long com;
@@ -442,9 +593,9 @@ struct ioctl_args {
 };
 
 int
-afs_xioctl(struct proc *p, register struct ioctl_args *uap, register_t *retval)
+afs_xioctl(afs_proc_t *p, register struct ioctl_args *uap, register_t *retval)
 {
-#elif defined(AFS_LINUX22_ENV)
+#   elif defined(AFS_LINUX22_ENV)
 struct afs_ioctl_sys {
     unsigned int com;
     unsigned long arg;
@@ -454,7 +605,7 @@ afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
           unsigned long arg)
 {
     struct afs_ioctl_sys ua, *uap = &ua;
-#else
+#   else
 int
 afs_xioctl(void)
 {
@@ -463,88 +614,84 @@ afs_xioctl(void)
        int com;
        caddr_t arg;
     } *uap = (struct a *)u.u_ap;
-#endif /* AFS_SUN5_ENV */
-#endif
-#if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
+#   endif /* AFS_SUN5_ENV */
+#  endif
+#  if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV)
     struct file *fd;
-#elif !defined(AFS_LINUX22_ENV)
+#  elif !defined(AFS_LINUX22_ENV)
     register struct file *fd;
-#endif
-#if defined(AFS_XBSD_ENV)
+#  endif
+#  if defined(AFS_XBSD_ENV)
     register struct filedesc *fdp;
-#endif
+#  endif
     register struct vcache *tvc;
     register int ioctlDone = 0, code = 0;
 
     AFS_STATCNT(afs_xioctl);
-#if defined(AFS_DARWIN_ENV)
+#  if defined(AFS_DARWIN_ENV)
     if ((code = fdgetf(p, uap->fd, &fd)))
        return code;
-#elif defined(AFS_XBSD_ENV)
+#  elif defined(AFS_XBSD_ENV)
     fdp = p->p_fd;
     if ((u_int) uap->fd >= fdp->fd_nfiles
        || (fd = fdp->fd_ofiles[uap->fd]) == NULL)
        return EBADF;
     if ((fd->f_flag & (FREAD | FWRITE)) == 0)
        return EBADF;
-#elif defined(AFS_LINUX22_ENV)
+#  elif defined(AFS_LINUX22_ENV)
     ua.com = com;
     ua.arg = arg;
-#elif defined(AFS_AIX32_ENV)
+#  elif defined(AFS_AIX32_ENV)
     uap->fd = fdes;
     uap->com = com;
     uap->arg = arg;
-#ifdef AFS_AIX51_ENV
+#   ifdef AFS_AIX51_ENV
     uap->arg2 = arg2;
     uap->arg3 = arg3;
-#endif
+#   endif
     if (setuerror(getf(uap->fd, &fd))) {
        return -1;
     }
-#elif defined(AFS_OSF_ENV)
-    fd = NULL;
-    if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
-       return code;
-#elif defined(AFS_SUN5_ENV)
-# if defined(AFS_SUN57_ENV)
+#  elif defined(AFS_SUN5_ENV)
+#   if defined(AFS_SUN57_ENV)
     fd = getf(uap->fd);
     if (!fd)
        return (EBADF);
-# elif defined(AFS_SUN54_ENV)
+#   elif defined(AFS_SUN54_ENV)
     fd = GETF(uap->fd);
     if (!fd)
        return (EBADF);
-# else
+#   else
     if (code = getf(uap->fd, &fd)) {
        return (code);
     }
-# endif        /* AFS_SUN57_ENV */
-#else
+#   endif      /* AFS_SUN57_ENV */
+#  else
     fd = getf(uap->fd);
     if (!fd)
        return (EBADF);
-#endif
+#  endif
     /* first determine whether this is any sort of vnode */
-#if defined(AFS_LINUX22_ENV)
+#  if defined(AFS_LINUX22_ENV)
     tvc = VTOAFS(ip);
     {
-#else
-#ifdef AFS_SUN5_ENV
+#  else
+#   ifdef AFS_SUN5_ENV
     if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
-#else
+#   else
     if (fd->f_type == DTYPE_VNODE) {
-#endif
+#   endif
        /* good, this is a vnode; next see if it is an AFS vnode */
-#if    defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
+#   if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
        tvc = VTOAFS(fd->f_vnode);      /* valid, given a vnode */
-#elif defined(AFS_OBSD_ENV)
+#   elif defined(AFS_OBSD_ENV)
        tvc =
            IsAfsVnode((struct vnode *)fd->
                       f_data) ? VTOAFS((struct vnode *)fd->f_data) : NULL;
-#else
+#   else
        tvc = VTOAFS((struct vnode *)fd->f_data);       /* valid, given a vnode */
-#endif
-#endif /* AFS_LINUX22_ENV */
+#   endif
+#  endif /* AFS_LINUX22_ENV */
        if (tvc && IsAfsVnode(AFSTOV(tvc))) {
            /* This is an AFS vnode */
            if (((uap->com >> 8) & 0xff) == 'V') {
@@ -556,134 +703,102 @@ afs_xioctl(void)
                if (code) {
                    osi_FreeSmallSpace(datap);
                    AFS_GUNLOCK();
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-                   return code;
-#else
-#if    defined(AFS_SUN5_ENV)
-#ifdef AFS_SUN54_ENV
+#  if defined(AFS_AIX41_ENV)
+                   ufdrele(uap->fd);
+#  elif defined(AFS_SUN54_ENV)
                    releasef(uap->fd);
-#else
+#  elif defined(AFS_SUN5_ENV)
                    releasef(fd);
-#endif
-                   return (EFAULT);
-#else
-#ifdef AFS_OSF_ENV
-#ifdef AFS_OSF30_ENV
-                   FP_UNREF_ALWAYS(fd);
-#else
-                   FP_UNREF(fd);
-#endif
+#  endif
+
+#  if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
                    return code;
-#else /* AFS_OSF_ENV */
-#ifdef AFS_AIX41_ENV
-                   ufdrele(uap->fd);
-#endif
-#ifdef AFS_LINUX22_ENV
+#  elif defined(AFS_SUN5_ENV)
+                   return (EFAULT);
+#  elif defined(AFS_LINUX22_ENV)
                    return -code;
-#else
-                   setuerror(code);
-                   return;
-#endif
-#endif
-#endif
-#endif
+#  else
+                   return (setuerror(code), code);
+#  endif
                }
                code = HandleIoctl(tvc, uap->com, datap);
                osi_FreeSmallSpace(datap);
                AFS_GUNLOCK();
                ioctlDone = 1;
-#ifdef AFS_AIX41_ENV
+#  if defined(AFS_AIX41_ENV)
                ufdrele(uap->fd);
-#endif
-#ifdef AFS_OSF_ENV
-#ifdef AFS_OSF30_ENV
-               FP_UNREF_ALWAYS(fd);
-#else
-               FP_UNREF(fd);
-#endif
-#endif
+#  endif
            }
-#if defined(AFS_LINUX22_ENV)
+#  if defined(AFS_LINUX22_ENV)
            else
                code = EINVAL;
-#endif
+#  endif
        }
     }
 
     if (!ioctlDone) {
-#ifdef AFS_AIX41_ENV
+#  if defined(AFS_AIX41_ENV)
        ufdrele(uap->fd);
-#ifdef AFS_AIX51_ENV
-#ifdef __64BIT__
+#   ifdef AFS_AIX51_ENV
+#    ifdef __64BIT__
        code = okioctl(fdes, com, arg, ext, arg2, arg3);
-#else /* __64BIT__ */
+#    else /* __64BIT__ */
        code = okioctl32(fdes, com, arg, ext, arg2, arg3);
-#endif /* __64BIT__ */
-#else /* !AFS_AIX51_ENV */
+#    endif /* __64BIT__ */
+#   else /* !AFS_AIX51_ENV */
        code = okioctl(fdes, com, arg, ext);
-#endif /* AFS_AIX51_ENV */
+#   endif /* AFS_AIX51_ENV */
        return code;
-#else /* !AFS_AIX41_ENV */
-#ifdef AFS_AIX32_ENV
+#  elif defined(AFS_AIX32_ENV)
        okioctl(fdes, com, arg, ext);
-#elif defined(AFS_SUN5_ENV)
-#if defined(AFS_SUN57_ENV)
+#  elif defined(AFS_SUN5_ENV)
+#   if defined(AFS_SUN57_ENV)
        releasef(uap->fd);
-#elif defined(AFS_SUN54_ENV)
+#   elif defined(AFS_SUN54_ENV)
        RELEASEF(uap->fd);
-#else
+#   else
        releasef(fd);
-#endif
+#   endif
        code = ioctl(uap, rvp);
-#elif defined(AFS_FBSD50_ENV)
+#  elif defined(AFS_FBSD50_ENV)
        return ioctl(td, uap);
-#elif defined(AFS_FBSD_ENV)
+#  elif defined(AFS_FBSD_ENV)
        return ioctl(p, uap);
-#elif defined(AFS_OBSD_ENV)
+#  elif defined(AFS_OBSD_ENV)
        code = sys_ioctl(p, uap, retval);
-#elif defined(AFS_DARWIN_ENV)
+#  elif defined(AFS_DARWIN_ENV)
        return ioctl(p, uap, retval);
-#elif defined(AFS_OSF_ENV)
-       code = ioctl(p, args, retval);
-#ifdef AFS_OSF30_ENV
-       FP_UNREF_ALWAYS(fd);
-#else
-       FP_UNREF(fd);
-#endif
-       return code;
-#elif !defined(AFS_LINUX22_ENV)
+#  elif !defined(AFS_LINUX22_ENV)
        ioctl();
-#endif
-#endif
+#  endif
     }
-#ifdef AFS_SUN5_ENV
+#  ifdef       AFS_SUN5_ENV
     if (ioctlDone)
-#ifdef AFS_SUN54_ENV
+#   ifdef      AFS_SUN54_ENV
        releasef(uap->fd);
-#else
+#   else
        releasef(fd);
-#endif
+#   endif
     return (code);
-#else
-#ifdef AFS_LINUX22_ENV
+#  elif defined(AFS_LINUX22_ENV)
     return -code;
-#else
-#if defined(KERNEL_HAVE_UERROR)
+#  elif defined(KERNEL_HAVE_UERROR)
     if (!getuerror())
        setuerror(code);
-#if    defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
+#   if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
     return (getuerror()? -1 : u.u_ioctlrv);
-#else
+#   else
     return getuerror()? -1 : 0;
-#endif
-#endif
-#endif /* AFS_LINUX22_ENV */
-#endif /* AFS_SUN5_ENV */
-#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#   endif
+#  endif
+
+#  if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
     return (code);
-#endif
+#  else
+    return 0;
+#  endif
 }
-#endif /* AFS_SGI_ENV */
+# endif /* AFS_SGI_ENV */
 #endif /* AFS_HPUX102_ENV */
 
 #if defined(AFS_SGI_ENV)
@@ -704,25 +819,11 @@ afs_pioctl(struct pioctlargs *uap, rval_t * rvp)
     AFS_GLOCK();
     code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
     AFS_GUNLOCK();
-#ifdef AFS_SGI64_ENV
+# ifdef AFS_SGI64_ENV
     return code;
-#else
+# else
     return u.u_error;
-#endif
-}
-
-#elif defined(AFS_OSF_ENV)
-afs_pioctl(struct proc *p, void *args, int *retval)
-{
-    struct a {
-       char *path;
-       int cmd;
-       caddr_t cmarg;
-       int follow;
-    } *uap = (struct a *)args;
-
-    AFS_STATCNT(afs_pioctl);
-    return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
+# endif
 }
 
 #elif defined(AFS_FBSD50_ENV)
@@ -743,7 +844,7 @@ afs_pioctl(struct thread *td, void *args, int *retval)
 
 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 int
-afs_pioctl(struct proc *p, void *args, int *retval)
+afs_pioctl(afs_proc_t *p, void *args, int *retval)
 {
     struct a {
        char *path;
@@ -753,15 +854,15 @@ afs_pioctl(struct proc *p, void *args, int *retval)
     } *uap = (struct a *)args;
 
     AFS_STATCNT(afs_pioctl);
-#ifdef AFS_DARWIN80_ENV
+# ifdef AFS_DARWIN80_ENV
     return (afs_syscall_pioctl
            (uap->path, uap->cmd, uap->cmarg, uap->follow,
             kauth_cred_get()));
-#else
+# else
     return (afs_syscall_pioctl
            (uap->path, uap->cmd, uap->cmarg, uap->follow,
             p->p_cred->pc_ucred));
-#endif
+# endif
 }
 
 #endif
@@ -776,11 +877,14 @@ afs_pioctl(struct proc *p, void *args, int *retval)
 int
 #ifdef AFS_SUN5_ENV
 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow, 
-                  rval_t *vvp, struct AFS_UCRED *credp)
+                  rval_t *vvp, afs_ucred_t *credp)
 #else
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#ifdef AFS_DARWIN100_ENV
+afs_syscall64_pioctl(user_addr_t path, unsigned int com, user_addr_t cmarg,
+                  int follow, afs_ucred_t *credp)
+#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow, 
-                  struct AFS_UCRED *credp)
+                  afs_ucred_t *credp)
 #else
 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
 #endif
@@ -788,9 +892,11 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
 {
     struct afs_ioctl data;
 #ifdef AFS_NEED_CLIENTCONTEXT
-    struct AFS_UCRED *tmpcred = NULL;
+    afs_ucred_t *tmpcred = NULL;
+#endif
+#if defined(AFS_NEED_CLIENTCONTEXT) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+    afs_ucred_t *foreigncreds = NULL;
 #endif
-    struct AFS_UCRED *foreigncreds = NULL;
     register afs_int32 code = 0;
     struct vnode *vp = NULL;
 #ifdef AFS_AIX41_ENV
@@ -886,11 +992,14 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
                       foreigncreds ? foreigncreds : credp);
 #else
 #ifdef AFS_LINUX22_ENV
-       code = gop_lookupname(path, AFS_UIOUSER, follow, &dp);
+       code = gop_lookupname_user(path, AFS_UIOUSER, follow, &dp);
        if (!code)
            vp = (struct vnode *)dp->d_inode;
 #else
-       code = gop_lookupname(path, AFS_UIOUSER, follow, &vp);
+       code = gop_lookupname_user(path, AFS_UIOUSER, follow, &vp);
+#if defined(AFS_FBSD80_ENV) /* XXX check on 7x */
+       VN_HOLD(vp);
+#endif /* AFS_FBSD80_ENV */
 #endif /* AFS_LINUX22_ENV */
 #endif /* AFS_AIX41_ENV */
        AFS_GLOCK();
@@ -988,6 +1097,10 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
 #ifdef AFS_LINUX22_ENV
        dput(dp);
 #else
+#if defined(AFS_FBSD80_ENV)
+    if (VOP_ISLOCKED(vp))
+       VOP_UNLOCK(vp, 0);
+#endif /* AFS_FBSD80_ENV */
        AFS_RELE(vp);           /* put vnode back */
 #endif
     }
@@ -1001,37 +1114,53 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
 #endif
 }
 
+#ifdef AFS_DARWIN100_ENV
+int
+afs_syscall_pioctl(char * path, unsigned int com, caddr_t cmarg,
+                  int follow, afs_ucred_t *credp)
+{
+    return afs_syscall64_pioctl(CAST_USER_ADDR_T(path), com,
+                               CAST_USER_ADDR_T((unsigned int)cmarg), follow,
+                               credp);
+}
+#endif
+
 #define MAXPIOCTLTOKENLEN \
 (3*sizeof(afs_int32)+MAXKTCTICKETLEN+sizeof(struct ClearToken)+MAXKTCREALMLEN)
 
 int
 afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
                 register struct afs_ioctl *ablob, int afollow,
-                struct AFS_UCRED **acred)
+                afs_ucred_t **acred)
 {
     struct vcache *avc;
     struct vrequest treq;
     register afs_int32 code;
     register afs_int32 function, device;
-    afs_int32 inSize, outSize, outSizeMax;
-    char *inData, *outData;
+    struct afs_pdata input, output;
+    struct afs_pdata copyInput, copyOutput;
+    size_t outSize;
     pioctlFunction *pioctlSw;
     int pioctlSwSize;
     struct afs_fakestat_state fakestate;
 
+    memset(&input, 0, sizeof(input));
+    memset(&output, 0, sizeof(output));
+
     avc = avp ? VTOAFS(avp) : NULL;
     afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
               ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
     AFS_STATCNT(HandlePioctl);
-    if ((code = afs_InitReq(&treq, *acred)))
+
+    code = afs_InitReq(&treq, *acred);
+    if (code)
        return code;
+
     afs_InitFakeStat(&fakestate);
     if (avc) {
        code = afs_EvalFakeStat(&avc, &fakestate, &treq);
-       if (code) {
-           afs_PutFakeStat(&fakestate);
-           return code;
-       }
+       if (code)
+           goto out;
     }
     device = (acom & 0xff00) >> 8;
     switch (device) {
@@ -1048,79 +1177,62 @@ afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
        pioctlSwSize = sizeof(OpioctlSw);
        break;
     default:
-       afs_PutFakeStat(&fakestate);
-       return EINVAL;
+       code = EINVAL;
+       goto out;
     }
     function = acom & 0xff;
     if (function >= (pioctlSwSize / sizeof(char *))) {
-       afs_PutFakeStat(&fakestate);
-       return EINVAL;          /* out of range */
+       code = EINVAL;
+       goto out;
     }
-    inSize = ablob->in_size;
 
     /* Do all range checking before continuing */
-    if (inSize > MAXPIOCTLTOKENLEN || inSize < 0 || ablob->out_size < 0)
-       return E2BIG;
-
-    /* Note that we use osi_Alloc for large allocs and osi_AllocLargeSpace for small ones */
-    if (inSize > AFS_LRALLOCSIZ) {
-       inData = osi_Alloc(inSize + 1);
-    } else {
-       inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+    if (ablob->in_size > MAXPIOCTLTOKENLEN ||
+        ablob->in_size < 0 || ablob->out_size < 0) {
+       code = EINVAL;
+       goto out;
     }
-    if (!inData)
-       return ENOMEM;
-    if (inSize > 0) {
-       AFS_COPYIN(ablob->in, inData, inSize, code);
-       inData[inSize] = '\0';
-    } else
-       code = 0;
-    if (code) {
-       if (inSize > AFS_LRALLOCSIZ) {
-           osi_Free(inData, inSize + 1);
-       } else {
-           osi_FreeLargeSpace(inData);
-       }
-       afs_PutFakeStat(&fakestate);
-       return code;
+
+    code = afs_pd_alloc(&input, ablob->in_size);
+    if (code)
+       goto out;
+
+    if (ablob->in_size > 0) {
+       AFS_COPYIN(ablob->in, input.ptr, ablob->in_size, code);
+       input.ptr[input.remaining] = '\0';
     }
+    if (code)
+       goto out;
+
     if (function == 8 && device == 'V') {      /* PGetTokens */
-       outSizeMax = MAXPIOCTLTOKENLEN;
-       outData = osi_Alloc(outSizeMax);
+       code = afs_pd_alloc(&output, MAXPIOCTLTOKENLEN);
     } else {
-       outSizeMax = AFS_LRALLOCSIZ;
-       outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
-    }
-    if (!outData) {
-       if (inSize > AFS_LRALLOCSIZ) {
-           osi_Free(inData, inSize + 1);
-       } else {
-           osi_FreeLargeSpace(inData);
-       }
-       afs_PutFakeStat(&fakestate);
-       return ENOMEM;
+       code = afs_pd_alloc(&output, AFS_LRALLOCSIZ);
     }
-    outSize = 0;
+    if (code)
+       goto out;
+
+    copyInput = input;
+    copyOutput = output;
+
     code =
-       (*pioctlSw[function]) (avc, function, &treq, inData, outData, inSize,
-                              &outSize, acred);
-    if (inSize > AFS_LRALLOCSIZ) {
-       osi_Free(inData, inSize + 1);
-    } else {
-       osi_FreeLargeSpace(inData);
-    }
+       (*pioctlSw[function]) (avc, function, &treq, &copyInput,
+                              &copyOutput, acred);
+
+    outSize = copyOutput.ptr - output.ptr;
+
     if (code == 0 && ablob->out_size > 0) {
        if (outSize > ablob->out_size) {
            code = E2BIG;       /* data wont fit in user buffer */
        } else if (outSize) {
-           AFS_COPYOUT(outData, ablob->out, outSize, code);
+           AFS_COPYOUT(output.ptr, ablob->out, outSize, code);
        }
     }
-    if (outSizeMax > AFS_LRALLOCSIZ) {
-       osi_Free(outData, outSizeMax);
-    } else {
-       osi_FreeLargeSpace(outData);
-    }
+
+out:
+    afs_pd_free(&input);
+    afs_pd_free(&output);
+
     afs_PutFakeStat(&fakestate);
     return afs_CheckCode(code, &treq, 41);
 }
@@ -1142,8 +1254,8 @@ DECL_PIOCTL(PGetFID)
     AFS_STATCNT(PGetFID);
     if (!avc)
        return EINVAL;
-    memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
-    *aoutSize = sizeof(struct VenusFid);
+    if (afs_pd_putBytes(aout, &avc->f.fid, sizeof(struct VenusFid)) != 0)
+       return EINVAL;
     return 0;
 }
 
@@ -1167,7 +1279,7 @@ int dummy_PSetAcl(char *ain, char *aout)
 DECL_PIOCTL(PSetAcl)
 {
     register afs_int32 code;
-    struct conn *tconn;
+    struct afs_conn *tconn;
     struct AFSOpaque acl;
     struct AFSVolSync tsync;
     struct AFSFetchStatus OutStatus;
@@ -1176,34 +1288,39 @@ DECL_PIOCTL(PSetAcl)
     AFS_STATCNT(PSetAcl);
     if (!avc)
        return EINVAL;
-    if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1024 /* AFSOPAQUEMAX */)
+
+    if (afs_pd_getStringPtr(ain, &acl.AFSOpaque_val) != 0)
+       return EINVAL;
+    acl.AFSOpaque_len = strlen(acl.AFSOpaque_val) + 1;
+    if (acl.AFSOpaque_len > 1024)
        return EINVAL;
 
-    acl.AFSOpaque_val = ain;
     do {
-       tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+       tconn = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
        if (tconn) {
            XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
            RX_AFS_GUNLOCK();
            code =
-               RXAFS_StoreACL(tconn->id, (struct AFSFid *)&avc->fid.Fid,
+               RXAFS_StoreACL(tconn->id, (struct AFSFid *)&avc->f.fid.Fid,
                               &acl, &OutStatus, &tsync);
            RX_AFS_GLOCK();
            XSTATS_END_TIME;
        } else
            code = -1;
     } while (afs_Analyze
-            (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STOREACL,
+            (tconn, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_STOREACL,
              SHARED_LOCK, NULL));
 
     /* now we've forgotten all of the access info */
     ObtainWriteLock(&afs_xcbhash, 455);
     avc->callback = 0;
     afs_DequeueCallback(avc);
-    avc->states &= ~(CStatd | CUnique);
+    avc->f.states &= ~(CStatd | CUnique);
     ReleaseWriteLock(&afs_xcbhash);
-    if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
+    if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
        osi_dnlc_purgedp(avc);
+
+    /* SXW - Should we flush metadata here? */
     return code;
 }
 
@@ -1224,33 +1341,33 @@ int afs_defaultAsynchrony = 0;
  */
 DECL_PIOCTL(PStoreBehind)
 {
-    afs_int32 code = 0;
-    struct sbstruct *sbr;
+    struct sbstruct sbr;
 
-    sbr = (struct sbstruct *)ain;
-    if (sbr->sb_default != -1) {
+    if (afs_pd_getBytes(ain, &sbr, sizeof(struct sbstruct)) != 0)
+       return EINVAL;
+
+    if (sbr.sb_default != -1) {
        if (afs_osi_suser(*acred))
-           afs_defaultAsynchrony = sbr->sb_default;
+           afs_defaultAsynchrony = sbr.sb_default;
        else
-           code = EPERM;
+           return EPERM;
     }
 
-    if (avc && (sbr->sb_thisfile != -1)) {
+    if (avc && (sbr.sb_thisfile != -1)) {
        if (afs_AccessOK
            (avc, PRSFS_WRITE | PRSFS_ADMINISTER, areq, DONT_CHECK_MODE_BITS))
-           avc->asynchrony = sbr->sb_thisfile;
+           avc->asynchrony = sbr.sb_thisfile;
        else
-           code = EACCES;
+           return EACCES;
     }
 
-    *aoutSize = sizeof(struct sbstruct);
-    sbr = (struct sbstruct *)aout;
-    sbr->sb_default = afs_defaultAsynchrony;
+    memset(&sbr, 0, sizeof(sbr));
+    sbr.sb_default = afs_defaultAsynchrony;
     if (avc) {
-       sbr->sb_thisfile = avc->asynchrony;
+       sbr.sb_thisfile = avc->asynchrony;
     }
 
-    return code;
+    return afs_pd_putBytes(aout, &sbr, sizeof(sbr));
 }
 
 /*!
@@ -1296,17 +1413,17 @@ DECL_PIOCTL(PGetAcl)
     struct AFSVolSync tsync;
     struct AFSFetchStatus OutStatus;
     afs_int32 code;
-    struct conn *tconn;
+    struct afs_conn *tconn;
     struct AFSFid Fid;
     XSTATS_DECLS;
 
     AFS_STATCNT(PGetAcl);
     if (!avc)
        return EINVAL;
-    Fid.Volume = avc->fid.Fid.Volume;
-    Fid.Vnode = avc->fid.Fid.Vnode;
-    Fid.Unique = avc->fid.Fid.Unique;
-    if (avc->states & CForeign) {
+    Fid.Volume = avc->f.fid.Fid.Volume;
+    Fid.Vnode = avc->f.fid.Fid.Vnode;
+    Fid.Unique = avc->f.fid.Fid.Unique;
+    if (avc->f.states & CForeign) {
        /*
         * For a dfs xlator acl we have a special hack so that the
         * xlator will distinguish which type of acl will return. So
@@ -1316,13 +1433,13 @@ DECL_PIOCTL(PGetAcl)
         */
        if (Fid.Vnode & 0xc0000000)
            return ERANGE;
-       Fid.Vnode |= (ainSize << 30);
+       Fid.Vnode |= (ain->remaining << 30);
     }
-    acl.AFSOpaque_val = aout;
+    acl.AFSOpaque_val = aout->ptr;
     do {
-       tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+       tconn = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
        if (tconn) {
-           *aout = 0;
+           acl.AFSOpaque_val[0] = '\0';
            XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
            RX_AFS_GUNLOCK();
            code = RXAFS_FetchACL(tconn->id, &Fid, &acl, &OutStatus, &tsync);
@@ -1331,11 +1448,14 @@ DECL_PIOCTL(PGetAcl)
        } else
            code = -1;
     } while (afs_Analyze
-            (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_FETCHACL,
+            (tconn, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_FETCHACL,
              SHARED_LOCK, NULL));
 
     if (code == 0) {
-       *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
+       if (acl.AFSOpaque_len == 0)
+           afs_pd_skip(aout, 1); /* leave the NULL */
+       else
+           afs_pd_skip(aout, acl.AFSOpaque_len); /* Length of the ACL */
     }
     return code;
 }
@@ -1388,12 +1508,14 @@ DECL_PIOCTL(PGetFileCell)
     AFS_STATCNT(PGetFileCell);
     if (!avc)
        return EINVAL;
-    tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
+    tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
     if (!tcell)
        return ESRCH;
-    strcpy(aout, tcell->cellName);
+
+    if (afs_pd_putString(aout, tcell->cellName) != 0)
+       return EINVAL;
+
     afs_PutCell(tcell, READ_LOCK);
-    *aoutSize = strlen(aout) + 1;
     return 0;
 }
 
@@ -1421,8 +1543,9 @@ DECL_PIOCTL(PGetWSCell)
     tcell = afs_GetPrimaryCell(READ_LOCK);
     if (!tcell)                        /* no primary cell? */
        return ESRCH;
-    strcpy(aout, tcell->cellName);
-    *aoutSize = strlen(aout) + 1;
+
+    if (afs_pd_putString(aout, tcell->cellName) != 0)
+       return EINVAL;
     afs_PutCell(tcell, READ_LOCK);
     return 0;
 }
@@ -1465,14 +1588,12 @@ DECL_PIOCTL(PGetUserCell)
        if (!tcell)
            return ESRCH;
        else {
-           strcpy(aout, tcell->cellName);
+           if (afs_pd_putString(aout, tcell->cellName) != 0)
+               return E2BIG;
            afs_PutCell(tcell, READ_LOCK);
-           *aoutSize = strlen(aout) + 1;       /* 1 for the null */
        }
     } else {
        ReleaseWriteLock(&afs_xuser);
-       *aout = 0;
-       *aoutSize = 1;
     }
     return 0;
 }
@@ -1499,6 +1620,7 @@ DECL_PIOCTL(PSetTokens)
     struct ClearToken clear;
     register struct cell *tcell;
     char *stp;
+    char *cellName;
     int stLen;
     struct vrequest treq;
     afs_int32 flag, set_parent_pag = 0;
@@ -1507,33 +1629,44 @@ DECL_PIOCTL(PSetTokens)
     if (!afs_resourceinit_flag) {
        return EIO;
     }
-    memcpy((char *)&i, ain, sizeof(afs_int32));
-    ain += sizeof(afs_int32);
-    stp = ain;                 /* remember where the ticket is */
-    if (i < 0 || i > MAXKTCTICKETLEN)
+
+    if (afs_pd_getInt(ain, &stLen) != 0)
+       return EINVAL;
+
+    stp = afs_pd_where(ain);   /* remember where the ticket is */
+    if (stLen < 0 || stLen > MAXKTCTICKETLEN)
        return EINVAL;          /* malloc may fail */
-    stLen = i;
-    ain += i;                  /* skip over ticket */
-    memcpy((char *)&i, ain, sizeof(afs_int32));
-    ain += sizeof(afs_int32);
-    if (i != sizeof(struct ClearToken)) {
+    if (afs_pd_skip(ain, stLen) != 0)
        return EINVAL;
-    }
-    memcpy((char *)&clear, ain, sizeof(struct ClearToken));
+
+    if (afs_pd_getInt(ain, &i) != 0)
+       return EINVAL;
+    if (i != sizeof(struct ClearToken))
+       return EINVAL;
+
+    if (afs_pd_getBytes(ain, &clear, sizeof(struct ClearToken)) !=0)
+       return EINVAL;
+
     if (clear.AuthHandle == -1)
        clear.AuthHandle = 999; /* more rxvab compat stuff */
-    ain += sizeof(struct ClearToken);
-    if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
+
+    if (afs_pd_remaining(ain) != 0) {
        /* still stuff left?  we've got primary flag and cell name.  Set these */
-       memcpy((char *)&flag, ain, sizeof(afs_int32));  /* primary id flag */
-       ain += sizeof(afs_int32);       /* skip id field */
-       /* rest is cell name, look it up */
+
+       if (afs_pd_getInt(ain, &flag) != 0)
+           return EINVAL;
+
        /* some versions of gcc appear to need != 0 in order to get this right */
        if ((flag & 0x8000) != 0) {     /* XXX Use Constant XXX */
            flag &= ~0x8000;
            set_parent_pag = 1;
        }
-       tcell = afs_GetCellByName(ain, READ_LOCK);
+
+       if (afs_pd_getStringPtr(ain, &cellName) != 0)
+           return EINVAL;
+
+       /* rest is cell name, look it up */
+       tcell = afs_GetCellByName(cellName, READ_LOCK);
        if (!tcell)
            goto nocell;
     } else {
@@ -1546,25 +1679,21 @@ DECL_PIOCTL(PSetTokens)
     i = tcell->cellNum;
     afs_PutCell(tcell, READ_LOCK);
     if (set_parent_pag) {
-       afs_int32 pag;
+       afs_uint32 pag;
 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-#if defined(AFS_DARWIN_ENV)
-       struct proc *p = current_proc();        /* XXX */
-#else
-       struct proc *p = curproc;       /* XXX */
-#endif
-#ifndef AFS_DARWIN80_ENV
+# if defined(AFS_DARWIN_ENV)
+       afs_proc_t *p = current_proc(); /* XXX */
+# else
+       afs_proc_t *p = curproc;        /* XXX */
+# endif
+# ifndef AFS_DARWIN80_ENV
        uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
                p->p_pid, p->p_comm);
-#endif
+# endif
        if (!setpag(p, acred, -1, &pag, 1)) {
 #else
-#ifdef AFS_OSF_ENV
-       if (!setpag(u.u_procp, acred, -1, &pag, 1)) {   /* XXX u.u_procp is a no-op XXX */
-#else
        if (!setpag(acred, -1, &pag, 1)) {
 #endif
-#endif
            afs_InitReq(&treq, *acred);
            areq = &treq;
        }
@@ -1623,11 +1752,10 @@ DECL_PIOCTL(PGetVolumeStatus)
     char volName[32];
     char *offLineMsg = afs_osi_Alloc(256);
     char *motd = afs_osi_Alloc(256);
-    register struct conn *tc;
+    register struct afs_conn *tc;
     register afs_int32 code = 0;
     struct AFSFetchVolumeStatus volstat;
-    register char *cp;
-    char *Name, *OfflineMsg, *MOTD;
+    char *Name;
     XSTATS_DECLS;
 
     AFS_STATCNT(PGetVolumeStatus);
@@ -1636,37 +1764,33 @@ DECL_PIOCTL(PGetVolumeStatus)
        goto out;
     }
     Name = volName;
-    OfflineMsg = offLineMsg;
-    MOTD = motd;
     do {
-       tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+       tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
        if (tc) {
            XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
            RX_AFS_GUNLOCK();
            code =
-               RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
-                                     &Name, &OfflineMsg, &MOTD);
+               RXAFS_GetVolumeStatus(tc->id, avc->f.fid.Fid.Volume, &volstat,
+                                     &Name, &offLineMsg, &motd);
            RX_AFS_GLOCK();
            XSTATS_END_TIME;
        } else
            code = -1;
     } while (afs_Analyze
-            (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
+            (tc, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
              SHARED_LOCK, NULL));
 
     if (code)
        goto out;
     /* Copy all this junk into msg->im_data, keeping track of the lengths. */
-    cp = aout;
-    memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
-    cp += sizeof(VolumeStatus);
-    strcpy(cp, volName);
-    cp += strlen(volName) + 1;
-    strcpy(cp, offLineMsg);
-    cp += strlen(offLineMsg) + 1;
-    strcpy(cp, motd);
-    cp += strlen(motd) + 1;
-    *aoutSize = (cp - aout);
+    if (afs_pd_putBytes(aout, &volstat, sizeof(VolumeStatus)) != 0)
+       return E2BIG;
+    if (afs_pd_putString(aout, volName) != 0)
+       return E2BIG;
+    if (afs_pd_putString(aout, offLineMsg) != 0)
+       return E2BIG;
+    if (afs_pd_putString(aout, motd) != 0)
+       return E2BIG;
   out:
     afs_osi_Free(offLineMsg, 256);
     afs_osi_Free(motd, 256);
@@ -1690,56 +1814,51 @@ DECL_PIOCTL(PGetVolumeStatus)
  */
 DECL_PIOCTL(PSetVolumeStatus)
 {
-    char volName[32];
-    char *offLineMsg = afs_osi_Alloc(256);
-    char *motd = afs_osi_Alloc(256);
-    register struct conn *tc;
+    char *volName;
+    char *offLineMsg;
+    char *motd;
+    register struct afs_conn *tc;
     register afs_int32 code = 0;
     struct AFSFetchVolumeStatus volstat;
     struct AFSStoreVolumeStatus storeStat;
     register struct volume *tvp;
-    register char *cp;
     XSTATS_DECLS;
 
     AFS_STATCNT(PSetVolumeStatus);
-    if (!avc) {
-       code = EINVAL;
-       goto out;
-    }
+    if (!avc)
+       return EINVAL;
 
-    tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
+    tvp = afs_GetVolume(&avc->f.fid, areq, READ_LOCK);
     if (tvp) {
        if (tvp->states & (VRO | VBackup)) {
            afs_PutVolume(tvp, READ_LOCK);
-           code = EROFS;
-           goto out;
+           return EROFS;
        }
        afs_PutVolume(tvp, READ_LOCK);
-    } else {
-       code = ENODEV;
-       goto out;
-    }
-    /* Copy the junk out, using cp as a roving pointer. */
-    cp = ain;
-    memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
-    cp += sizeof(AFSFetchVolumeStatus);
-    if (strlen(cp) >= sizeof(volName)) {
-       code = E2BIG;
-       goto out;
-    }
-    strcpy(volName, cp);
-    cp += strlen(volName) + 1;
-    if (strlen(cp) >= sizeof(offLineMsg)) {
-       code = E2BIG;
-       goto out;
-    }
-    strcpy(offLineMsg, cp);
-    cp += strlen(offLineMsg) + 1;
-    if (strlen(cp) >= sizeof(motd)) {
-       code = E2BIG;
-       goto out;
-    }
-    strcpy(motd, cp);
+    } else
+       return ENODEV;
+
+
+    if (afs_pd_getBytes(ain, &volstat, sizeof(AFSFetchVolumeStatus)) != 0)
+       return EINVAL;
+
+    if (afs_pd_getStringPtr(ain, &volName) != 0)
+       return EINVAL;
+    if (strlen(volName) > 32)
+        return E2BIG;
+
+    if (afs_pd_getStringPtr(ain, &offLineMsg) != 0)
+       return EINVAL;
+    if (strlen(offLineMsg) > 256)
+       return E2BIG;
+
+    if (afs_pd_getStringPtr(ain, &motd) != 0)
+       return EINVAL;
+    if (strlen(motd) > 256)
+       return E2BIG;
+
+    /* Done reading ... */
+
     storeStat.Mask = 0;
     if (volstat.MinQuota != -1) {
        storeStat.MinQuota = volstat.MinQuota;
@@ -1750,38 +1869,37 @@ DECL_PIOCTL(PSetVolumeStatus)
        storeStat.Mask |= AFS_SETMAXQUOTA;
     }
     do {
-       tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+       tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
        if (tc) {
            XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
            RX_AFS_GUNLOCK();
            code =
-               RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume, &storeStat,
+               RXAFS_SetVolumeStatus(tc->id, avc->f.fid.Fid.Volume, &storeStat,
                                      volName, offLineMsg, motd);
            RX_AFS_GLOCK();
            XSTATS_END_TIME;
        } else
            code = -1;
     } while (afs_Analyze
-            (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
+            (tc, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
              SHARED_LOCK, NULL));
 
     if (code)
-       goto out;
+       return code;
     /* we are sending parms back to make compat. with prev system.  should
      * change interface later to not ask for current status, just set new status */
-    cp = aout;
-    memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
-    cp += sizeof(VolumeStatus);
-    strcpy(cp, volName);
-    cp += strlen(volName) + 1;
-    strcpy(cp, offLineMsg);
-    cp += strlen(offLineMsg) + 1;
-    strcpy(cp, motd);
-    cp += strlen(motd) + 1;
-    *aoutSize = cp - aout;
-  out:
-    afs_osi_Free(offLineMsg, 256);
-    afs_osi_Free(motd, 256);
+
+    /* XXX - We really need to check that this doesn't overflow, too, otherwise
+     * bad fileserver status could be _really_ bad */
+    if (afs_pd_putBytes(aout, &volstat, sizeof(VolumeStatus)) != 0)
+       return EINVAL;
+    if (afs_pd_putString(aout, volName) != 0)
+       return EINVAL;
+    if (afs_pd_putString(aout, offLineMsg) != 0)
+       return EINVAL;
+    if (afs_pd_putString(aout, motd) != 0)
+       return EINVAL;
+
     return code;
 }
 
@@ -1803,20 +1921,10 @@ DECL_PIOCTL(PFlush)
     if (!avc)
        return EINVAL;
 #ifdef AFS_BOZONLOCK_ENV
-    afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
-#endif
-    ObtainWriteLock(&avc->lock, 225);
-    ObtainWriteLock(&afs_xcbhash, 456);
-    afs_DequeueCallback(avc);
-    avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
-    ReleaseWriteLock(&afs_xcbhash);
-    /* now find the disk cache entries */
-    afs_TryToSmush(avc, *acred, 1);
-    osi_dnlc_purgedp(avc);
-    if (avc->linkData && !(avc->states & CCore)) {
-       afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
-       avc->linkData = NULL;
-    }
+    afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
+#endif
+    ObtainWriteLock(&avc->lock, 225);
+    afs_ResetVCache(avc, *acred);
     ReleaseWriteLock(&avc->lock);
 #ifdef AFS_BOZONLOCK_ENV
     afs_BozonUnlock(&avc->pvnLock, avc);
@@ -1845,12 +1953,17 @@ DECL_PIOCTL(PNewStatMount)
     register struct dcache *tdc;
     struct VenusFid tfid;
     char *bufp;
+    char *name;
     struct sysname_info sysState;
     afs_size_t offset, len;
 
     AFS_STATCNT(PNewStatMount);
     if (!avc)
        return EINVAL;
+
+    if (afs_pd_getStringPtr(ain, &name) != 0)
+       return EINVAL;
+
     code = afs_VerifyVCache(avc, areq);
     if (code)
        return code;
@@ -1860,7 +1973,7 @@ DECL_PIOCTL(PNewStatMount)
     tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
     if (!tdc)
        return ENOENT;
-    Check_AtSys(avc, ain, &sysState, areq);
+    Check_AtSys(avc, name, &sysState, areq);
     ObtainReadLock(&tdc->lock);
     do {
        code = afs_dir_Lookup(tdc, sysState.name, &tfid.Fid);
@@ -1871,9 +1984,9 @@ DECL_PIOCTL(PNewStatMount)
     if (code) {
        goto out;
     }
-    tfid.Cell = avc->fid.Cell;
-    tfid.Fid.Volume = avc->fid.Fid.Volume;
-    if (!tfid.Fid.Unique && (avc->states & CForeign)) {
+    tfid.Cell = avc->f.fid.Cell;
+    tfid.Fid.Volume = avc->f.fid.Fid.Volume;
+    if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
        tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
     } else {
        tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
@@ -1895,8 +2008,8 @@ DECL_PIOCTL(PNewStatMount)
                code = EINVAL;
            else {
                /* we have the data */
-               strcpy(aout, tvc->linkData);
-               *aoutSize = strlen(tvc->linkData) + 1;
+               if (afs_pd_putString(aout, tvc->linkData) != 0)
+                   code = EINVAL;
            }
        } else
            code = EIO;
@@ -1931,9 +2044,9 @@ DECL_PIOCTL(PGetTokens)
     register struct cell *tcell;
     register afs_int32 i;
     register struct unixuser *tu;
-    register char *cp;
-    afs_int32 iterator;
+    afs_int32 iterator = 0;
     int newStyle;
+    int code = E2BIG;
 
     AFS_STATCNT(PGetTokens);
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
@@ -1948,8 +2061,10 @@ DECL_PIOCTL(PGetTokens)
      * tokens, the primary cell indicator (an afs_int32 0) and the cell name
      * at the end, in that order.
      */
-    if ((newStyle = (ainSize > 0))) {
-       memcpy((char *)&iterator, ain, sizeof(afs_int32));
+    newStyle = (afs_pd_remaining(ain) > 0);
+    if (newStyle) {
+       if (afs_pd_getInt(ain, &iterator) != 0)
+           return EINVAL;
     }
     i = UHash(areq->uid);
     ObtainReadLock(&afs_xuser);
@@ -1981,36 +2096,45 @@ DECL_PIOCTL(PGetTokens)
        afs_PutUser(tu, READ_LOCK);
        return ENOTCONN;
     }
-    /* use iterator for temp */
-    cp = aout;
     iterator = tu->stLen;      /* for compat, we try to return 56 byte tix if they fit */
     if (iterator < 56)
        iterator = 56;          /* # of bytes we're returning */
-    memcpy(cp, (char *)&iterator, sizeof(afs_int32));
-    cp += sizeof(afs_int32);
-    memcpy(cp, tu->stp, tu->stLen);    /* copy out st */
-    cp += iterator;
-    iterator = sizeof(struct ClearToken);
-    memcpy(cp, (char *)&iterator, sizeof(afs_int32));
-    cp += sizeof(afs_int32);
-    memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
-    cp += sizeof(struct ClearToken);
+
+    if (afs_pd_putInt(aout, iterator) != 0)
+       goto out;
+    if (afs_pd_putBytes(aout, tu->stp, tu->stLen) != 0)
+       goto out;
+    if (tu->stLen < 56) {
+       /* Tokens are always 56 bytes or larger */
+       if (afs_pd_skip(aout, iterator - tu->stLen) != 0) {
+           goto out;
+       }
+    }
+
+    if (afs_pd_putInt(aout, sizeof(struct ClearToken)) != 0)
+       goto out;
+    if (afs_pd_putBytes(aout, &tu->ct, sizeof(struct ClearToken)) != 0)
+       goto out;
+
     if (newStyle) {
        /* put out primary id and cell name, too */
        iterator = (tu->states & UPrimary ? 1 : 0);
-       memcpy(cp, (char *)&iterator, sizeof(afs_int32));
-       cp += sizeof(afs_int32);
+       if (afs_pd_putInt(aout, iterator) != 0)
+           goto out;
        tcell = afs_GetCell(tu->cell, READ_LOCK);
        if (tcell) {
-           strcpy(cp, tcell->cellName);
-           cp += strlen(tcell->cellName) + 1;
+           if (afs_pd_putString(aout, tcell->cellName) != 0)
+               goto out;
            afs_PutCell(tcell, READ_LOCK);
        } else
-           *cp++ = 0;
+           if (afs_pd_putString(aout, "") != 0)
+               goto out;
     }
-    *aoutSize = cp - aout;
+    /* Got here, all is good */
+    code = 0;
+out:
     afs_PutUser(tu, READ_LOCK);
-    return 0;
+    return code;
 }
 
 /*!
@@ -2044,7 +2168,7 @@ DECL_PIOCTL(PUnlog)
            tu->vid = UNDEFVID;
            tu->states &= ~UHasTokens;
            /* security is not having to say you're sorry */
-           memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
+           memset(&tu->ct, 0, sizeof(struct ClearToken));
            tu->refCount++;
            ReleaseWriteLock(&afs_xuser);
            /* We have to drop the lock over the call to afs_ResetUserConns, since
@@ -2095,7 +2219,9 @@ DECL_PIOCTL(PMariner)
     else
        oldHostAddr = 0xffffffff;       /* disabled */
 
-    memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
+    if (afs_pd_getInt(ain, &newHostAddr) != 0)
+       return EINVAL;
+
     if (newHostAddr == 0xffffffff) {
        /* disable mariner operations */
        afs_mariner = 0;
@@ -2103,8 +2229,10 @@ DECL_PIOCTL(PMariner)
        afs_mariner = 1;
        afs_marinerHost = newHostAddr;
     }
-    memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
-    *aoutSize = sizeof(afs_int32);
+
+    if (afs_pd_putInt(aout, oldHostAddr) != 0)
+       return E2BIG;
+
     return 0;
 }
 
@@ -2124,10 +2252,10 @@ DECL_PIOCTL(PMariner)
  */
 DECL_PIOCTL(PCheckServers)
 {
-    register char *cp = 0;
     register int i;
     register struct server *ts;
-    afs_int32 temp, *lp = (afs_int32 *) ain, havecell = 0;
+    afs_int32 temp;
+    char *cellName = NULL;
     struct cell *cellp;
     struct chservinfo *pcheck;
 
@@ -2136,12 +2264,21 @@ DECL_PIOCTL(PCheckServers)
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    if (*lp == 0x12345678) {   /* For afs3.3 version */
-       pcheck = (struct chservinfo *)ain;
+    /* This is tricky, because we need to peak at the datastream to see
+     * what we're getting. For now, let's cheat. */
+
+    /* ain contains either an int32 or a string */
+    if (ain->remaining == 0)
+       return EINVAL;
+
+    if (*(afs_int32 *)ain->ptr == 0x12345678) {        /* For afs3.3 version */
+       pcheck = afs_pd_inline(ain, sizeof(*pcheck));
+        if (pcheck == NULL)
+           return EINVAL;
+
        if (pcheck->tinterval >= 0) {
-           cp = aout;
-           memcpy(cp, (char *)&afs_probe_interval, sizeof(afs_int32));
-           *aoutSize = sizeof(afs_int32);
+           if (afs_pd_putInt(aout, afs_probe_interval) != 0)
+               return E2BIG;
            if (pcheck->tinterval > 0) {
                if (!afs_osi_suser(*acred))
                    return EACCES;
@@ -2149,24 +2286,25 @@ DECL_PIOCTL(PCheckServers)
            }
            return 0;
        }
-       if (pcheck->tsize)
-           havecell = 1;
        temp = pcheck->tflags;
-       cp = pcheck->tbuffer;
+       if (pcheck->tsize)
+           cellName = pcheck->tbuffer;
     } else {                   /* For pre afs3.3 versions */
-       memcpy((char *)&temp, ain, sizeof(afs_int32));
-       cp = ain + sizeof(afs_int32);
-       if (ainSize > sizeof(afs_int32))
-           havecell = 1;
+       if (afs_pd_getInt(ain, &temp) != 0)
+           return EINVAL;
+       if (afs_pd_remaining(ain) > 0) {
+           if (afs_pd_getStringPtr(ain, &cellName) != 0)
+               return EINVAL;
+       }
     }
 
     /*
      * 1: fast check, don't contact servers.
      * 2: local cell only.
      */
-    if (havecell) {
+    if (cellName) {
        /* have cell name, too */
-       cellp = afs_GetCellByName(cp, READ_LOCK);
+       cellp = afs_GetCellByName(cellName, READ_LOCK);
        if (!cellp)
            return ENOENT;
     } else
@@ -2180,7 +2318,6 @@ DECL_PIOCTL(PCheckServers)
        afs_CheckServers(0, cellp);     /* check up servers */
     }
     /* now return the current down server list */
-    cp = aout;
     ObtainReadLock(&afs_xserver);
     for (i = 0; i < NSERVERS; i++) {
        for (ts = afs_servers[i]; ts; ts = ts->next) {
@@ -2188,15 +2325,13 @@ DECL_PIOCTL(PCheckServers)
                continue;       /* cell spec'd and wrong */
            if ((ts->flags & SRVR_ISDOWN)
                && ts->addr->sa_portal != ts->cell->vlport) {
-               memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
-               cp += sizeof(afs_int32);
+               afs_pd_putInt(aout, ts->addr->sa_ip);
            }
        }
     }
     ReleaseReadLock(&afs_xserver);
     if (cellp)
        afs_PutCell(cellp, READ_LOCK);
-    *aoutSize = cp - aout;
     return 0;
 }
 
@@ -2242,7 +2377,7 @@ DECL_PIOCTL(PCheckAuth)
 {
     int i;
     struct srvAddr *sa;
-    struct conn *tc;
+    struct afs_conn *tc;
     struct unixuser *tu;
     afs_int32 retValue;
 
@@ -2275,14 +2410,14 @@ DECL_PIOCTL(PCheckAuth)
        ReleaseReadLock(&afs_xconn);
        afs_PutUser(tu, READ_LOCK);
     }
-    memcpy(aout, (char *)&retValue, sizeof(afs_int32));
-    *aoutSize = sizeof(afs_int32);
+    if (afs_pd_putInt(aout, retValue) != 0)
+       return E2BIG;
     return 0;
 }
 
 static int
-Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
-        struct AFS_UCRED *acred)
+Prefetch(uparmtype apath, struct afs_ioctl *adata, int afollow,
+        afs_ucred_t *acred)
 {
     register char *tp;
     register afs_int32 code;
@@ -2330,32 +2465,34 @@ DECL_PIOCTL(PFindVolume)
     register struct volume *tvp;
     register struct server *ts;
     register afs_int32 i;
-    register char *cp;
+    int code = 0;
 
     AFS_STATCNT(PFindVolume);
     if (!avc)
        return EINVAL;
-    tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
-    if (tvp) {
-       cp = aout;
-       for (i = 0; i < MAXHOSTS; i++) {
-           ts = tvp->serverHost[i];
-           if (!ts)
-               break;
-           memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
-           cp += sizeof(afs_int32);
+    tvp = afs_GetVolume(&avc->f.fid, areq, READ_LOCK);
+    if (!tvp)
+       return ENODEV;
+
+    for (i = 0; i < AFS_MAXHOSTS; i++) {
+       ts = tvp->serverHost[i];
+       if (!ts)
+           break;
+       if (afs_pd_putInt(aout, ts->addr->sa_ip) != 0) {
+           code = E2BIG;
+           goto out;
        }
-       if (i < MAXHOSTS) {
-           /* still room for terminating NULL, add it on */
-           ainSize = 0;        /* reuse vbl */
-           memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
-           cp += sizeof(afs_int32);
+    }
+    if (i < AFS_MAXHOSTS) {
+       /* still room for terminating NULL, add it on */
+       if (afs_pd_putInt(aout, 0) != 0) {
+           code = E2BIG;
+           goto out;
        }
-       *aoutSize = cp - aout;
-       afs_PutVolume(tvp, READ_LOCK);
-       return 0;
     }
-    return ENODEV;
+out:
+    afs_PutVolume(tvp, READ_LOCK);
+    return code;
 }
 
 /*!
@@ -2379,10 +2516,14 @@ DECL_PIOCTL(PViceAccess)
     AFS_STATCNT(PViceAccess);
     if (!avc)
        return EINVAL;
+
     code = afs_VerifyVCache(avc, areq);
     if (code)
        return code;
-    memcpy((char *)&temp, ain, sizeof(afs_int32));
+
+    if (afs_pd_getInt(ain, &temp) != 0)
+       return EINVAL;
+
     code = afs_AccessOK(avc, temp, areq, CHECK_MODE_BITS);
     if (code)
        return 0;
@@ -2390,6 +2531,25 @@ DECL_PIOCTL(PViceAccess)
        return EACCES;
 }
 
+/*!
+ * VIOC_GETPAG (13) - Get PAG value
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    PAG value or NOPAG
+ *
+ * \post get PAG value for the caller's cred
+ */
+DECL_PIOCTL(PGetPAG)
+{
+    afs_int32 pag;
+
+    pag = PagInCred(*acred);
+
+    return afs_pd_putInt(aout, pag);
+}
+
 DECL_PIOCTL(PPrecache)
 {
     afs_int32 newValue;
@@ -2397,7 +2557,10 @@ DECL_PIOCTL(PPrecache)
     /*AFS_STATCNT(PPrecache);*/
     if (!afs_osi_suser(*acred))
        return EACCES;
-    memcpy((char *)&newValue, ain, sizeof(afs_int32));
+
+    if (afs_pd_getInt(ain, &newValue) != 0)
+       return EINVAL;
+
     afs_preCache = newValue*1024;
     return 0;
 }
@@ -2423,12 +2586,14 @@ DECL_PIOCTL(PSetCacheSize)
     int waitcnt = 0;
 
     AFS_STATCNT(PSetCacheSize);
+
     if (!afs_osi_suser(*acred))
        return EACCES;
     /* too many things are setup initially in mem cache version */
     if (cacheDiskType == AFS_FCACHE_TYPE_MEM)
        return EROFS;
-    memcpy((char *)&newValue, ain, sizeof(afs_int32));
+    if (afs_pd_getInt(ain, &newValue) != 0)
+       return EINVAL;
     if (newValue == 0)
        afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
     else {
@@ -2467,15 +2632,15 @@ DECL_PIOCTL(PGetCacheSize)
     
     AFS_STATCNT(PGetCacheSize);
 
-    if (sizeof(afs_int32) == ainSize){
-       memcpy((char *)&flags, ain, sizeof(afs_int32));
-    } else if (0 == ainSize){ 
+    if (afs_pd_remaining(ain) == sizeof(afs_int32)) {
+       afs_pd_getInt(ain, &flags); /* can't error, we just checked size */
+    } else if (afs_pd_remaining(ain) == 0) {
        flags = 0;
     } else {
        return EINVAL;
     }
     
-    memset((char *)results, 0, sizeof(results));
+    memset(results, 0, sizeof(results));
     results[0] = afs_cacheBlocks;
     results[1] = afs_blocksUsed;
     results[2] = afs_cacheFiles;
@@ -2506,9 +2671,7 @@ DECL_PIOCTL(PGetCacheSize)
            }
         }
     }
-    memcpy(aout, (char *)results, sizeof(results));
-    *aoutSize = sizeof(results);
-    return 0;
+    return afs_pd_putBytes(aout, results, sizeof(results));
 }
 
 /*!
@@ -2526,7 +2689,7 @@ DECL_PIOCTL(PGetCacheSize)
  */
 DECL_PIOCTL(PRemoveCallBack)
 {
-    register struct conn *tc;
+    register struct afs_conn *tc;
     register afs_int32 code = 0;
     struct AFSCallBack CallBacks_Array[1];
     struct AFSCBFids theFids;
@@ -2536,17 +2699,17 @@ DECL_PIOCTL(PRemoveCallBack)
     AFS_STATCNT(PRemoveCallBack);
     if (!avc)
        return EINVAL;
-    if (avc->states & CRO)
+    if (avc->f.states & CRO)
        return 0;               /* read-only-ness can't change */
     ObtainWriteLock(&avc->lock, 229);
     theFids.AFSCBFids_len = 1;
     theCBs.AFSCBs_len = 1;
-    theFids.AFSCBFids_val = (struct AFSFid *)&avc->fid.Fid;
+    theFids.AFSCBFids_val = (struct AFSFid *)&avc->f.fid.Fid;
     theCBs.AFSCBs_val = CallBacks_Array;
     CallBacks_Array[0].CallBackType = CB_DROPPED;
     if (avc->callback) {
        do {
-           tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+           tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
            if (tc) {
                XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
                RX_AFS_GUNLOCK();
@@ -2556,15 +2719,15 @@ DECL_PIOCTL(PRemoveCallBack)
            }
            /* don't set code on failure since we wouldn't use it */
        } while (afs_Analyze
-                (tc, code, &avc->fid, areq,
+                (tc, code, &avc->f.fid, areq,
                  AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS, SHARED_LOCK, NULL));
 
        ObtainWriteLock(&afs_xcbhash, 457);
        afs_DequeueCallback(avc);
        avc->callback = 0;
-       avc->states &= ~(CStatd | CUnique);
+       avc->f.states &= ~(CStatd | CUnique);
        ReleaseWriteLock(&afs_xcbhash);
-       if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
+       if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
            osi_dnlc_purgedp(avc);
     }
     ReleaseWriteLock(&avc->lock);
@@ -2587,12 +2750,13 @@ DECL_PIOCTL(PRemoveCallBack)
  */
 DECL_PIOCTL(PNewCell)
 {
-    /* create a new cell */
-    afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic = 0;
-    char *newcell = 0, *linkedcell = 0, *tp = ain;
-    register afs_int32 code, linkedstate = 0, ls;
-    u_short fsport = 0, vlport = 0;
-    afs_int32 scount;
+    afs_int32 cellHosts[AFS_MAXCELLHOSTS], magic = 0;
+    char *newcell = NULL;
+    char *linkedcell = NULL;
+    afs_int32 code, ls;
+    afs_int32 linkedstate = 0;
+    afs_int32 fsport = 0, vlport = 0;
+    int skip;
 
     AFS_STATCNT(PNewCell);
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
@@ -2601,34 +2765,55 @@ DECL_PIOCTL(PNewCell)
     if (!afs_osi_suser(*acred))
        return EACCES;
 
-    memcpy((char *)&magic, tp, sizeof(afs_int32));
-    tp += sizeof(afs_int32);
+    if (afs_pd_getInt(ain, &magic) != 0)
+       return EINVAL;
     if (magic != 0x12345678)
        return EINVAL;
 
-    /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
+    /* A 3.4 fs newcell command will pass an array of AFS_MAXCELLHOSTS
      * server addresses while the 3.5 fs newcell command passes
-     * MAXHOSTS. To figure out which is which, check if the cellname
+     * AFS_MAXHOSTS. To figure out which is which, check if the cellname
      * is good.
+     *
+     * This whole logic is bogus, because it relies on the newer command
+     * sending its 12th address as 0.
      */
-    newcell = tp + (MAXCELLHOSTS + 3) * sizeof(afs_int32);
-    scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
+    if ((afs_pd_remaining(ain) < AFS_MAXCELLHOSTS +3) * sizeof(afs_int32))
+       return EINVAL;
 
-    /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
-    memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
-    tp += (scount * sizeof(afs_int32));
+    newcell = afs_pd_where(ain) + (AFS_MAXCELLHOSTS + 3) * sizeof(afs_int32);
+    if (newcell[0] != '\0') {
+       skip = 0;
+    } else {
+       skip = AFS_MAXHOSTS - AFS_MAXCELLHOSTS;
+    }
+
+    /* AFS_MAXCELLHOSTS (=8) is less than AFS_MAXHOSTS (=13) */
+    if (afs_pd_getBytes(ain, &cellHosts,
+                       AFS_MAXCELLHOSTS * sizeof(afs_int32)) != 0)
+       return EINVAL;
+    if (afs_pd_skip(ain, skip * sizeof(afs_int32)) !=0)
+       return EINVAL;
 
-    lp = (afs_int32 *) tp;
-    fsport = *lp++;
-    vlport = *lp++;
+    if (afs_pd_getInt(ain, &fsport) != 0)
+       return EINVAL;
     if (fsport < 1024)
        fsport = 0;             /* Privileged ports not allowed */
+
+    if (afs_pd_getInt(ain, &vlport) != 0)
+       return EINVAL;
     if (vlport < 1024)
        vlport = 0;             /* Privileged ports not allowed */
-    tp += (3 * sizeof(afs_int32));
-    newcell = tp;
-    if ((ls = *lp) & 1) {
-       linkedcell = tp + strlen(newcell) + 1;
+
+    if (afs_pd_getInt(ain, &ls) != 0)
+       return EINVAL;
+
+    if (afs_pd_getStringPtr(ain, &newcell) != 0)
+       return EINVAL;
+
+    if (ls & 1) {
+       if (afs_pd_getStringPtr(ain, &linkedcell) != 0)
+           return EINVAL;
        linkedstate |= CLinkedCell;
     }
 
@@ -2642,8 +2827,6 @@ DECL_PIOCTL(PNewCell)
 DECL_PIOCTL(PNewAlias)
 {
     /* create a new cell alias */
-    char *tp = ain;
-    register afs_int32 code;
     char *realName, *aliasName;
 
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
@@ -2652,13 +2835,12 @@ DECL_PIOCTL(PNewAlias)
     if (!afs_osi_suser(*acred))
        return EACCES;
 
-    aliasName = tp;
-    tp += strlen(aliasName) + 1;
-    realName = tp;
+    if (afs_pd_getStringPtr(ain, &aliasName) != 0)
+       return EINVAL;
+    if (afs_pd_getStringPtr(ain, &realName) != 0)
+       return EINVAL;
 
-    code = afs_NewCellAlias(aliasName, realName);
-    *aoutSize = 0;
-    return code;
+    return afs_NewCellAlias(aliasName, realName);
 }
 
 /*!
@@ -2679,65 +2861,66 @@ DECL_PIOCTL(PListCells)
     afs_int32 whichCell;
     register struct cell *tcell = 0;
     register afs_int32 i;
-    register char *cp, *tp = ain;
+    int code;
 
     AFS_STATCNT(PListCells);
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    memcpy((char *)&whichCell, tp, sizeof(afs_int32));
-    tp += sizeof(afs_int32);
+    if (afs_pd_getInt(ain, &whichCell) != 0)
+       return EINVAL;
+
     tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
-    if (tcell) {
-       cp = aout;
-       memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
-       for (i = 0; i < MAXCELLHOSTS; i++) {
-           if (tcell->cellHosts[i] == 0)
-               break;
-           memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip,
-                  sizeof(afs_int32));
-           cp += sizeof(afs_int32);
-       }
-       cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
-       strcpy(cp, tcell->cellName);
-       cp += strlen(tcell->cellName) + 1;
-       *aoutSize = cp - aout;
-       afs_PutCell(tcell, READ_LOCK);
-    }
-    if (tcell)
-       return 0;
-    else
+    if (!tcell)
        return EDOM;
+
+    code = E2BIG;
+
+    for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
+       if (tcell->cellHosts[i] == 0)
+           break;
+       if (afs_pd_putInt(aout, tcell->cellHosts[i]->addr->sa_ip) != 0)
+           goto out;
+    }
+    for (;i < AFS_MAXCELLHOSTS; i++) {
+       if (afs_pd_putInt(aout, 0) != 0)
+           goto out;
+    }
+    if (afs_pd_putString(aout, tcell->cellName) != 0)
+       goto out;
+    code = 0;
+
+out:
+    afs_PutCell(tcell, READ_LOCK);
+    return code;
 }
 
 DECL_PIOCTL(PListAliases)
 {
     afs_int32 whichAlias;
     register struct cell_alias *tcalias = 0;
-    register char *cp, *tp = ain;
+    int code;
 
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
-    if (ainSize < sizeof(afs_int32))
-       return EINVAL;
 
-    memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
-    tp += sizeof(afs_int32);
+    if (afs_pd_getInt(ain, &whichAlias) != 0)
+       return EINVAL;
 
     tcalias = afs_GetCellAlias(whichAlias);
-    if (tcalias) {
-       cp = aout;
-       strcpy(cp, tcalias->alias);
-       cp += strlen(tcalias->alias) + 1;
-       strcpy(cp, tcalias->cell);
-       cp += strlen(tcalias->cell) + 1;
-       *aoutSize = cp - aout;
-       afs_PutCellAlias(tcalias);
-    }
-    if (tcalias)
-       return 0;
-    else
+    if (tcalias == NULL)
        return EDOM;
+
+    code = E2BIG;
+    if (afs_pd_putString(aout, tcalias->alias) != 0)
+       goto out;
+    if (afs_pd_putString(aout, tcalias->cell) != 0)
+       goto out;
+
+    code = 0;
+out:
+    afs_PutCellAlias(tcalias);
+    return code;
 }
 
 /*!
@@ -2758,9 +2941,10 @@ DECL_PIOCTL(PRemoveMount)
 {
     register afs_int32 code;
     char *bufp;
+    char *name;
     struct sysname_info sysState;
     afs_size_t offset, len;
-    register struct conn *tc;
+    register struct afs_conn *tc;
     register struct dcache *tdc;
     register struct vcache *tvc;
     struct AFSFetchStatus OutDirStatus;
@@ -2768,12 +2952,14 @@ DECL_PIOCTL(PRemoveMount)
     struct AFSVolSync tsync;
     XSTATS_DECLS;
 
-
     /* "ain" is the name of the file in this dir to remove */
 
     AFS_STATCNT(PRemoveMount);
     if (!avc)
        return EINVAL;
+    if (afs_pd_getStringPtr(ain, &name) != 0)
+       return EINVAL;
+
     code = afs_VerifyVCache(avc, areq);
     if (code)
        return code;
@@ -2783,7 +2969,7 @@ DECL_PIOCTL(PRemoveMount)
     tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);  /* test for error below */
     if (!tdc)
        return ENOENT;
-    Check_AtSys(avc, ain, &sysState, areq);
+    Check_AtSys(avc, name, &sysState, areq);
     ObtainReadLock(&tdc->lock);
     do {
        code = afs_dir_Lookup(tdc, sysState.name, &tfid.Fid);
@@ -2794,9 +2980,9 @@ DECL_PIOCTL(PRemoveMount)
        afs_PutDCache(tdc);
        goto out;
     }
-    tfid.Cell = avc->fid.Cell;
-    tfid.Fid.Volume = avc->fid.Fid.Volume;
-    if (!tfid.Fid.Unique && (avc->states & CForeign)) {
+    tfid.Cell = avc->f.fid.Cell;
+    tfid.Fid.Volume = avc->f.fid.Fid.Volume;
+    if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
        tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
     } else {
        tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
@@ -2831,19 +3017,19 @@ DECL_PIOCTL(PRemoveMount)
     ObtainWriteLock(&avc->lock, 231);
     osi_dnlc_remove(avc, bufp, tvc);
     do {
-       tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+       tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
        if (tc) {
            XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
            RX_AFS_GUNLOCK();
            code =
-               RXAFS_RemoveFile(tc->id, (struct AFSFid *)&avc->fid.Fid, bufp,
+               RXAFS_RemoveFile(tc->id, (struct AFSFid *)&avc->f.fid.Fid, bufp,
                                 &OutDirStatus, &tsync);
            RX_AFS_GLOCK();
            XSTATS_END_TIME;
        } else
            code = -1;
     } while (afs_Analyze
-            (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_REMOVEFILE,
+            (tc, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_REMOVEFILE,
              SHARED_LOCK, NULL));
 
     if (code) {
@@ -2866,7 +3052,7 @@ DECL_PIOCTL(PRemoveMount)
        ReleaseWriteLock(&tdc->lock);
        afs_PutDCache(tdc);     /* drop ref count */
     }
-    avc->states &= ~CUnique;   /* For the dfs xlator */
+    avc->f.states &= ~CUnique; /* For the dfs xlator */
     ReleaseWriteLock(&avc->lock);
     code = 0;
   out:
@@ -2905,20 +3091,23 @@ DECL_PIOCTL(PVenusLogging)
 DECL_PIOCTL(PGetCellStatus)
 {
     register struct cell *tcell;
+    char *cellName;
     afs_int32 temp;
 
     AFS_STATCNT(PGetCellStatus);
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    tcell = afs_GetCellByName(ain, READ_LOCK);
+    if (afs_pd_getStringPtr(ain, &cellName) != 0)
+       return EINVAL;
+
+    tcell = afs_GetCellByName(cellName, READ_LOCK);
     if (!tcell)
        return ENOENT;
     temp = tcell->states;
     afs_PutCell(tcell, READ_LOCK);
-    memcpy(aout, (char *)&temp, sizeof(afs_int32));
-    *aoutSize = sizeof(afs_int32);
-    return 0;
+
+    return afs_pd_putInt(aout, temp);
 }
 
 /*!
@@ -2937,18 +3126,25 @@ DECL_PIOCTL(PGetCellStatus)
 DECL_PIOCTL(PSetCellStatus)
 {
     register struct cell *tcell;
-    afs_int32 temp;
+    char *cellName;
+    afs_int32 flags0, flags1;
 
     if (!afs_osi_suser(*acred))
        return EACCES;
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    tcell = afs_GetCellByName(ain + 2 * sizeof(afs_int32), WRITE_LOCK);
+    if (afs_pd_getInt(ain, &flags0) != 0)
+       return EINVAL;
+    if (afs_pd_getInt(ain, &flags1) != 0)
+       return EINVAL;
+    if (afs_pd_getStringPtr(ain, &cellName) != 0)
+       return EINVAL;
+
+    tcell = afs_GetCellByName(cellName, WRITE_LOCK);
     if (!tcell)
        return ENOENT;
-    memcpy((char *)&temp, ain, sizeof(afs_int32));
-    if (temp & CNoSUID)
+    if (flags0 & CNoSUID)
        tcell->states |= CNoSUID;
     else
        tcell->states &= ~CNoSUID;
@@ -2989,8 +3185,8 @@ DECL_PIOCTL(PFlushVolumeData)
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    volume = avc->fid.Fid.Volume;      /* who to zap */
-    cell = avc->fid.Cell;
+    volume = avc->f.fid.Fid.Volume;    /* who to zap */
+    cell = avc->f.fid.Cell;
 
     /*
      * Clear stat'd flag from all vnodes from this volume; this will invalidate all
@@ -2998,27 +3194,26 @@ DECL_PIOCTL(PFlushVolumeData)
      */
  loop:
     ObtainReadLock(&afs_xvcache);
-    i = VCHashV(&avc->fid);
+    i = VCHashV(&avc->f.fid);
     for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
            uq = QPrev(tq);
            tvc = QTOVH(tq);
-           if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
-               if (tvc->states & CVInit) {
+           if (tvc->f.fid.Fid.Volume == volume && tvc->f.fid.Cell == cell) {
+               if (tvc->f.states & CVInit) {
                    ReleaseReadLock(&afs_xvcache);
-                   afs_osi_Sleep(&tvc->states);
+                   afs_osi_Sleep(&tvc->f.states);
                    goto loop;
                }
 #ifdef AFS_DARWIN80_ENV
-               if (tvc->states & CDeadVnode) {
+               if (tvc->f.states & CDeadVnode) {
                    ReleaseReadLock(&afs_xvcache);
-                   afs_osi_Sleep(&tvc->states);
+                   afs_osi_Sleep(&tvc->f.states);
                    goto loop;
                }
 #endif
-#if    defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)  || defined(AFS_SUN5_ENV)  || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
+#if    defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)  || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
                VN_HOLD(AFSTOV(tvc));
-#else
-#ifdef AFS_DARWIN80_ENV
+#elif defined(AFS_DARWIN80_ENV)
                vp = AFSTOV(tvc);
                if (vnode_get(vp))
                    continue;
@@ -3028,14 +3223,11 @@ DECL_PIOCTL(PFlushVolumeData)
                    AFS_GLOCK();
                    continue;
                }
-#else
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
                osi_vnhold(tvc, 0);
 #else
                VREFCOUNT_INC(tvc); /* AIX, apparently */
 #endif
-#endif
-#endif
                ReleaseReadLock(&afs_xvcache);
 #ifdef AFS_BOZONLOCK_ENV
                afs_BozonLock(&tvc->pvnLock, tvc);      /* Since afs_TryToSmush will do a pvn_vptrunc */
@@ -3044,9 +3236,9 @@ DECL_PIOCTL(PFlushVolumeData)
 
                ObtainWriteLock(&afs_xcbhash, 458);
                afs_DequeueCallback(tvc);
-               tvc->states &= ~(CStatd | CDirty);
+               tvc->f.states &= ~(CStatd | CDirty);
                ReleaseWriteLock(&afs_xcbhash);
-               if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
+               if (tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
                    osi_dnlc_purgedp(tvc);
                afs_TryToSmush(tvc, *acred, 1);
                ReleaseWriteLock(&tvc->lock);
@@ -3065,7 +3257,7 @@ DECL_PIOCTL(PFlushVolumeData)
     ReleaseReadLock(&afs_xvcache);
 
 
-    MObtainWriteLock(&afs_xdcache, 328);       /* needed if you're going to flush any stuff */
+    ObtainWriteLock(&afs_xdcache, 328);        /* needed if you're going to flush any stuff */
     for (i = 0; i < afs_cacheFiles; i++) {
        if (!(afs_indexFlags[i] & IFEverUsed))
            continue;           /* never had any data */
@@ -3089,7 +3281,7 @@ DECL_PIOCTL(PFlushVolumeData)
        }
        afs_PutDCache(tdc);     /* bumped by getdslot */
     }
-    MReleaseWriteLock(&afs_xdcache);
+    ReleaseWriteLock(&afs_xdcache);
 
     ObtainReadLock(&afs_xvolume);
     for (i = 0; i < NVOLS; i++) {
@@ -3142,14 +3334,14 @@ DECL_PIOCTL(PGetVnodeXStatus)
        return EACCES;
 
     memset(&stat, 0, sizeof(struct vcxstat));
-    stat.fid = avc->fid;
-    hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
+    stat.fid = avc->f.fid;
+    hset32(stat.DataVersion, hgetlo(avc->f.m.DataVersion));
     stat.lock = avc->lock;
-    stat.parentVnode = avc->parentVnode;
-    stat.parentUnique = avc->parentUnique;
+    stat.parentVnode = avc->f.parent.vnode;
+    stat.parentUnique = avc->f.parent.unique;
     hset(stat.flushDV, avc->flushDV);
     hset(stat.mapDV, avc->mapDV);
-    stat.truncPos = avc->truncPos;
+    stat.truncPos = avc->f.truncPos;
     {                          /* just grab the first two - won't break anything... */
        struct axscache *ac;
 
@@ -3160,15 +3352,13 @@ DECL_PIOCTL(PGetVnodeXStatus)
     }
     stat.callback = afs_data_pointer_to_int32(avc->callback);
     stat.cbExpires = avc->cbExpires;
-    stat.anyAccess = avc->anyAccess;
+    stat.anyAccess = avc->f.anyAccess;
     stat.opens = avc->opens;
     stat.execsOrWriters = avc->execsOrWriters;
     stat.flockCount = avc->flockCount;
     stat.mvstat = avc->mvstat;
-    stat.states = avc->states;
-    memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
-    *aoutSize = sizeof(struct vcxstat);
-    return 0;
+    stat.states = avc->f.states;
+    return afs_pd_putBytes(aout, &stat, sizeof(struct vcxstat));
 }
 
 
@@ -3193,13 +3383,11 @@ DECL_PIOCTL(PGetVnodeXStatus2)
     memset(&stat, 0, sizeof(struct vcxstat2));
 
     stat.cbExpires = avc->cbExpires;
-    stat.anyAccess = avc->anyAccess;
+    stat.anyAccess = avc->f.anyAccess;
     stat.mvstat = avc->mvstat;
     stat.callerAccess = afs_GetAccessBits(avc, ~0, areq);
 
-    memcpy(aout, (char *)&stat, sizeof(struct vcxstat2));
-    *aoutSize = sizeof(struct vcxstat2);
-    return 0;
+    return afs_pd_putBytes(aout, &stat, sizeof(struct vcxstat2));
 }
 
 
@@ -3221,7 +3409,8 @@ DECL_PIOCTL(PGetVnodeXStatus2)
  */
 DECL_PIOCTL(PSetSysName)
 {
-    char *cp, *cp2 = NULL, inname[MAXSYSNAME], outname[MAXSYSNAME];
+    char *inname = NULL;
+    char outname[MAXSYSNAME];
     afs_int32 setsysname;
     int foundname = 0;
     register struct afs_exporter *exporter;
@@ -3229,6 +3418,7 @@ DECL_PIOCTL(PSetSysName)
     register afs_int32 pag, error;
     int t, count, num = 0, allpags = 0;
     char **sysnamelist;
+    struct afs_pdata validate;
 
     AFS_STATCNT(PSetSysName);
     if (!afs_globalVFS) {
@@ -3239,9 +3429,8 @@ DECL_PIOCTL(PSetSysName)
        return (EINVAL);
 #endif
     }
-    memset(inname, 0, MAXSYSNAME);
-    memcpy(&setsysname, ain, sizeof(afs_int32));
-    ain += sizeof(afs_int32);
+    if (afs_pd_getInt(ain, &setsysname) != 0)
+       return EINVAL;
     if (setsysname & 0x8000) {
        allpags = 1;
        setsysname &= ~0x8000;
@@ -3251,28 +3440,27 @@ DECL_PIOCTL(PSetSysName)
        /* Check my args */
        if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
            return EINVAL;
-       cp2 = ain;
-       for (cp = ain, count = 0; count < setsysname; count++) {
-           /* won't go past end of ain since maxsysname*num < ain length */
-           t = strlen(cp);
+       validate = *ain;
+       for (count = 0; count < setsysname; count++) {
+           if (afs_pd_getStringPtr(&validate, &inname) != 0)
+               return EINVAL;
+           t = strlen(inname);
            if (t >= MAXSYSNAME || t <= 0)
                return EINVAL;
            /* check for names that can shoot us in the foot */
-           if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
+           if (inname[0] == '.' && (inname[1] == 0
+               || (inname[1] == '.' && inname[2] == 0)))
                return EINVAL;
-           cp += t + 1;
        }
-       /* args ok */
+       /* args ok, so go back to the beginning of that section */
 
-       /* inname gets first entry in case we're being a translator */
-       t = strlen(ain);
-       memcpy(inname, ain, t + 1);     /* include terminating null */
-       ain += t + 1;
+       if (afs_pd_getStringPtr(ain, &inname) != 0)
+           return EINVAL;
        num = count;
     }
-    if ((*acred)->cr_gid == RMTUSER_REQ ||
-       (*acred)->cr_gid == RMTUSER_REQ_PRIV) { /* Handles all exporters */
-       if (allpags && (*acred)->cr_gid != RMTUSER_REQ_PRIV) {
+    if (afs_cr_gid(*acred) == RMTUSER_REQ ||
+       afs_cr_gid(*acred) == RMTUSER_REQ_PRIV) {       /* Handles all exporters */
+       if (allpags && afs_cr_gid(*acred) != RMTUSER_REQ_PRIV) {
            return EPERM;
        }
        pag = PagInCred(*acred);
@@ -3286,7 +3474,7 @@ DECL_PIOCTL(PSetSysName)
            afs_PutUser(au, READ_LOCK);
            return EINVAL;      /* Better than panicing */
        }
-       error = EXP_SYSNAME(exporter, (setsysname ? cp2 : NULL), &sysnamelist,
+       error = EXP_SYSNAME(exporter, inname, &sysnamelist,
                            &num, allpags);
        if (error) {
            if (error == ENODEV)
@@ -3321,16 +3509,19 @@ DECL_PIOCTL(PSetSysName)
            /* clear @sys entries from the dnlc, once afs_lookup can
             * do lookups of @sys entries and thinks it can trust them */
            /* privs ok, store the entry, ... */
+
+           if (strlen(inname) >= MAXSYSNAME-1)
+               return EINVAL;
            strcpy(afs_sysname, inname);
+
            if (setsysname > 1) {       /* ... or list */
-               cp = ain;
                for (count = 1; count < setsysname; ++count) {
                    if (!afs_sysnamelist[count])
                        osi_Panic
                            ("PSetSysName: no afs_sysnamelist entry to write\n");
-                   t = strlen(cp);
-                   memcpy(afs_sysnamelist[count], cp, t + 1);  /* include null */
-                   cp += t + 1;
+                   if (afs_pd_getString(ain, afs_sysnamelist[count],
+                                        MAXSYSNAME) != 0)
+                       return EINVAL;
                }
            }
            afs_sysnamecount = setsysname;
@@ -3338,12 +3529,11 @@ DECL_PIOCTL(PSetSysName)
        }
     }
     if (!setsysname) {
-       cp = aout;              /* not changing so report back the count and ... */
-       memcpy(cp, (char *)&foundname, sizeof(afs_int32));
-       cp += sizeof(afs_int32);
+       if (afs_pd_putInt(aout, foundname) != 0)
+           return E2BIG;
        if (foundname) {
-           strcpy(cp, outname);        /* ... the entry, ... */
-           cp += strlen(outname) + 1;
+           if (afs_pd_putString(aout, outname) != 0)
+               return E2BIG;
            for (count = 1; count < foundname; ++count) {       /* ... or list. */
                if (!sysnamelist[count])
                    osi_Panic
@@ -3351,11 +3541,10 @@ DECL_PIOCTL(PSetSysName)
                t = strlen(sysnamelist[count]);
                if (t >= MAXSYSNAME)
                    osi_Panic("PSetSysName: sysname entry garbled\n");
-               strcpy(cp, sysnamelist[count]);
-               cp += t + 1;
+               if (afs_pd_putString(aout, sysnamelist[count]) != 0)
+                   return E2BIG;
            }
        }
-       *aoutSize = cp - aout;
     }
     return 0;
 }
@@ -3379,7 +3568,7 @@ ReSortCells_cb(struct cell *cell, void *arg)
     for (i = 0; i < s; i++) {
        if (l[i] == cell->cellNum) {
            ObtainWriteLock(&cell->lock, 690);
-           afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
+           afs_SortServers(cell->cellHosts, AFS_MAXCELLHOSTS);
            ReleaseWriteLock(&cell->lock);
        }
     }
@@ -3410,7 +3599,7 @@ ReSortCells(int s, afs_int32 * l, int vlonly)
            for (k = 0; k < s; k++)
                if (j->cell == l[k]) {
                    ObtainWriteLock(&j->lock, 233);
-                   afs_SortServers(j->serverHost, MAXHOSTS);
+                   afs_SortServers(j->serverHost, AFS_MAXHOSTS);
                    ReleaseWriteLock(&j->lock);
                    break;
                }
@@ -3507,6 +3696,9 @@ afs_setsprefs(struct spref *sp, unsigned int num, unsigned int vlonly)
 DECL_PIOCTL(PSetSPrefs)
 {
     struct setspref *ssp;
+    char *ainPtr;
+    size_t ainSize;
+
     AFS_STATCNT(PSetSPrefs);
 
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
@@ -3515,11 +3707,17 @@ DECL_PIOCTL(PSetSPrefs)
     if (!afs_osi_suser(*acred))
        return EACCES;
 
+    /* The I/O handling here is ghastly, as it relies on overrunning the ends
+     * of arrays. But, i'm not quite brave enough to change it yet. */
+    ainPtr = ain->ptr;
+    ainSize = ain->remaining;
+
     if (ainSize < sizeof(struct setspref))
        return EINVAL;
 
-    ssp = (struct setspref *)ain;
-    if (ainSize < sizeof(struct spref) * ssp->num_servers)
+    ssp = (struct setspref *)ainPtr;
+    if (ainSize < (sizeof(struct setspref)
+                  + sizeof(struct spref) * ssp->num_servers-1))
        return EINVAL;
 
     afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
@@ -3542,7 +3740,6 @@ DECL_PIOCTL(PSetSPrefs)
  */
 DECL_PIOCTL(PSetSPrefs33)
 {
-    struct spref *sp;
     AFS_STATCNT(PSetSPrefs);
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
@@ -3551,8 +3748,9 @@ DECL_PIOCTL(PSetSPrefs33)
     if (!afs_osi_suser(*acred))
        return EACCES;
 
-    sp = (struct spref *)ain;
-    afs_setsprefs(sp, ainSize / (sizeof(struct spref)), 0 /*!vlonly */ );
+    afs_setsprefs((struct spref *)afs_pd_where(ain),
+                 afs_pd_remaining(ain) / sizeof(struct spref),
+                 0 /*!vlonly */ );
     return 0;
 }
 
@@ -3573,7 +3771,7 @@ DECL_PIOCTL(PSetSPrefs33)
  */
 DECL_PIOCTL(PGetSPrefs)
 {
-    struct sprefrequest *spin; /* input */
+    struct sprefrequest spin;  /* input */
     struct sprefinfo *spout;   /* output */
     struct spref *srvout;      /* one output component */
     int i, j;                  /* counters for hash table traversal */
@@ -3586,31 +3784,35 @@ DECL_PIOCTL(PGetSPrefs)
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-
-    if (ainSize < sizeof(struct sprefrequest_33)) {
-       return ENOENT;
+    /* Work out from the size whether we've got a new, or old, style pioctl */
+    if (afs_pd_remaining(ain) < sizeof(struct sprefrequest)) {
+       if (afs_pd_getBytes(ain, &spin, sizeof(struct sprefrequest_33)) != 0)
+          return ENOENT;
+       vlonly = 0;
+       spin.flags = 0;
     } else {
-       spin = ((struct sprefrequest *)ain);
+       if (afs_pd_getBytes(ain, &spin, sizeof(struct sprefrequest)) != 0)
+          return EINVAL;
+       vlonly = (spin.flags & DBservers);
     }
 
-    if (ainSize > sizeof(struct sprefrequest_33)) {
-       vlonly = (spin->flags & DBservers);
-    } else
-       vlonly = 0;
+    /* This code relies on overflowing arrays. It's ghastly, but I'm not
+     * quite brave enough to tackle it yet ...
+     */
 
     /* struct sprefinfo includes 1 server struct...  that size gets added
      * in during the loop that follows.
      */
-    *aoutSize = sizeof(struct sprefinfo) - sizeof(struct spref);
-    spout = (struct sprefinfo *)aout;
-    spout->next_offset = spin->offset;
+    spout = afs_pd_inline(aout,
+                         sizeof(struct sprefinfo) - sizeof(struct spref));
+    spout->next_offset = spin.offset;
     spout->num_servers = 0;
     srvout = spout->servers;
 
     ObtainReadLock(&afs_xserver);
     for (i = 0, j = 0; j < NSERVERS; j++) {    /* sift through hash table */
        for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
-           if (spin->offset > (unsigned short)i) {
+           if (spin.offset > (unsigned short)i) {
                continue;       /* catch up to where we left off */
            }
            spout->next_offset++;
@@ -3624,21 +3826,22 @@ DECL_PIOCTL(PGetSPrefs)
                continue;
            }
 
+           /* Check we've actually got the space we're about to use */
+           if (afs_pd_inline(aout, sizeof(struct spref)) == NULL) {
+               ReleaseReadLock(&afs_xserver);  /* no more room! */
+               return 0;
+           }
+
            srvout->host.s_addr = sa->sa_ip;
            srvout->rank = sa->sa_iprank;
-           *aoutSize += sizeof(struct spref);
            spout->num_servers++;
            srvout++;
-
-           if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
-               ReleaseReadLock(&afs_xserver);  /* no more room! */
-               return 0;
-           }
        }
     }
     ReleaseReadLock(&afs_xserver);
 
     spout->next_offset = 0;    /* start over from the beginning next time */
+
     return 0;
 }
 
@@ -3667,7 +3870,8 @@ DECL_PIOCTL(PExportAfs)
     register struct afs_exporter *exporter;
 
     AFS_STATCNT(PExportAfs);
-    memcpy((char *)&handleValue, ain, sizeof(afs_int32));
+    if (afs_pd_getInt(ain, &handleValue) != 0)
+       return EINVAL;
     type = handleValue >> 24;
     if (type == 0x71) {
        newint = 1;
@@ -3695,8 +3899,8 @@ DECL_PIOCTL(PExportAfs)
     }
     if (!changestate) {
        handleValue = exporter->exp_states;
-       memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
-       *aoutSize = sizeof(afs_int32);
+       if (afs_pd_putInt(aout, handleValue) != 0)
+           return E2BIG;
     } else {
        if (!afs_osi_suser(*acred))
            return EACCES;      /* Only superuser can do this */
@@ -3741,8 +3945,8 @@ DECL_PIOCTL(PExportAfs)
                    exporter->exp_states &= ~EXP_CALLBACK;
            }
            handleValue = exporter->exp_states;
-           memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
-           *aoutSize = sizeof(afs_int32);
+           if (afs_pd_putInt(aout, handleValue) != 0)
+               return E2BIG;
        } else {
            if (export)
                exporter->exp_states |= EXP_EXPORTED;
@@ -3788,7 +3992,9 @@ DECL_PIOCTL(PGag)
     if (!afs_osi_suser(*acred))
        return EACCES;
 
-    gagflags = (struct gaginfo *)ain;
+    gagflags = afs_pd_inline(ain, sizeof(*gagflags));
+    if (gagflags == NULL)
+       return EINVAL;
     afs_showflags = gagflags->showflags;
 
     return 0;
@@ -3813,7 +4019,9 @@ DECL_PIOCTL(PTwiddleRx)
     if (!afs_osi_suser(*acred))
        return EACCES;
 
-    rxp = (struct rxparams *)ain;
+    rxp = afs_pd_inline(ain, sizeof(*rxp));
+    if (rxp == NULL)
+       return EINVAL;
 
     if (rxp->rx_initReceiveWindow)
        rx_initReceiveWindow = rxp->rx_initReceiveWindow;
@@ -3856,8 +4064,8 @@ DECL_PIOCTL(PGetInitParams)
     if (sizeof(struct cm_initparams) > PIGGYSIZE)
        return E2BIG;
 
-    memcpy(aout, (char *)&cm_initParams, sizeof(struct cm_initparams));
-    *aoutSize = sizeof(struct cm_initparams);
+    return afs_pd_putBytes(aout, &cm_initParams,
+                          sizeof(struct cm_initparams));
     return 0;
 }
 
@@ -3868,7 +4076,7 @@ crget(void)
 {
     cred_t *cr;
     cr = crdup(get_current_cred());
-    memset((char *)cr, 0, sizeof(cred_t));
+    memset(cr, 0, sizeof(cred_t));
 #if CELL || CELL_PREPARE
     cr->cr_id = -1;
 #endif
@@ -3888,9 +4096,7 @@ crget(void)
  */
 DECL_PIOCTL(PGetRxkcrypt)
 {
-    memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
-    *aoutSize = sizeof(afs_int32);
-    return 0;
+    return afs_pd_putInt(aout, cryptall);
 }
 
 /*!
@@ -3914,9 +4120,8 @@ DECL_PIOCTL(PSetRxkcrypt)
 
     if (!afs_osi_suser(*acred))
        return EPERM;
-    if (ainSize != sizeof(afs_int32) || ain == NULL)
+    if (afs_pd_getInt(ain, &tmpval) != 0)
        return EINVAL;
-    memcpy((char *)&tmpval, ain, sizeof(afs_int32));
     /* if new mappings added later this will need to be changed */
     if (tmpval != 0 && tmpval != 1)
        return EINVAL;
@@ -3935,16 +4140,19 @@ DECL_PIOCTL(PSetRxkcrypt)
 #define        PIOCTL_HEADER   6
 static int
 HandleClientContext(struct afs_ioctl *ablob, int *com,
-                   struct AFS_UCRED **acred, struct AFS_UCRED *credp)
+                   afs_ucred_t **acred, afs_ucred_t *credp)
 {
     char *ain, *inData;
     afs_uint32 hostaddr;
     afs_int32 uid, g0, g1, i, code, pag, exporter_type, isroot = 0;
     struct afs_exporter *exporter, *outexporter;
-    struct AFS_UCRED *newcred;
+    afs_ucred_t *newcred;
     struct unixuser *au;
     afs_uint32 comp = *com & 0xff00;
     afs_uint32 h, l;
+#if defined(AFS_SUN510_ENV)
+    gid_t gids[2];
+#endif
 
 #if defined(AFS_SGIMP_ENV)
     osi_Assert(ISAFS_GLOCK());
@@ -4010,38 +4218,39 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
 #ifdef AFS_AIX41_ENV
     setuerror(0);
 #endif
-    newcred->cr_gid = isroot ? RMTUSER_REQ_PRIV : RMTUSER_REQ;
+    afs_set_cr_gid(newcred, isroot ? RMTUSER_REQ_PRIV : RMTUSER_REQ);
 #ifdef AFS_AIX51_ENV
     newcred->cr_groupset.gs_union.un_groups[0] = g0;
     newcred->cr_groupset.gs_union.un_groups[1] = g1;
 #elif defined(AFS_LINUX26_ENV)
-#ifdef AFS_LINUX26_ONEGROUP_ENV
-    newcred->cr_group_info = groups_alloc(1); /* not that anything sets this */
+# ifdef AFS_LINUX26_ONEGROUP_ENV
+    set_cr_group_info(newcred, groups_alloc(1)); /* not that anything sets this */
     l = (((g0-0x3f00) & 0x3fff) << 14) | ((g1-0x3f00) & 0x3fff);
     h = ((g0-0x3f00) >> 14);
     h = ((g1-0x3f00) >> 14) + h + h + h;
-    GROUP_AT(newcred->cr_group_info, 0) = ((h << 28) | l);
-#else
-    newcred->cr_group_info = groups_alloc(2);
-    GROUP_AT(newcred->cr_group_info, 0) = g0;
-    GROUP_AT(newcred->cr_group_info, 1) = g1;
-#endif
+    GROUP_AT(cr_group_info(newcred), 0) = ((h << 28) | l);
+# else
+    set_cr_group_info(newcred, groups_alloc(2));
+    GROUP_AT(cr_group_info(newcred), 0) = g0;
+    GROUP_AT(cr_group_info(newcred), 1) = g1;
+# endif
+#elif defined(AFS_SUN510_ENV)
+    gids[0] = g0;
+    gids[1] = g1;
+    crsetgroups(newcred, 2, gids);
 #else
     newcred->cr_groups[0] = g0;
     newcred->cr_groups[1] = g1;
 #endif
 #ifdef AFS_AIX_ENV
     newcred->cr_ngrps = 2;
-#elif !defined(AFS_LINUX26_ENV)
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
+#elif !defined(AFS_LINUX26_ENV) && !defined(AFS_SUN510_ENV)
+# if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
     newcred->cr_ngroups = 2;
-#else
+# else
     for (i = 2; i < NGROUPS; i++)
        newcred->cr_groups[i] = NOGROUP;
-#endif
-#endif
-#if    !defined(AFS_OSF_ENV) 
-    afs_nfsclient_init();      /* before looking for exporter, ensure one exists */
+# endif
 #endif
     if (!(exporter = exporter_find(exporter_type))) {
        /* Exporter wasn't initialized or an invalid exporter type */
@@ -4049,15 +4258,15 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
        return EINVAL;
     }
     if (exporter->exp_states & EXP_PWSYNC) {
-       if (uid != credp->cr_uid) {
+       if (uid != afs_cr_uid(credp)) {
            crfree(newcred);
            return ENOEXEC;     /* XXX Find a better errno XXX */
        }
     }
-    newcred->cr_uid = uid;     /* Only temporary  */
+    afs_set_cr_uid(newcred, uid);      /* Only temporary  */
     code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
     /* The client's pag is the only unique identifier for it */
-    newcred->cr_uid = pag;
+    afs_set_cr_uid(newcred, pag);
     *acred = newcred;
     if (!code && *com == PSETPAG) {
        /* Special case for 'setpag' */
@@ -4112,11 +4321,13 @@ DECL_PIOCTL(PGetCPrefs)
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    if (ainSize < sizeof(struct sprefrequest))
+    spin = afs_pd_inline(ain, sizeof(*spin));
+    if (spin == NULL)
        return EINVAL;
 
-    spin = (struct sprefrequest *)ain;
-    spout = (struct sprefinfo *)aout;
+    /* Output spout relies on writing past the end of arrays. It's horrible,
+     * but I'm not quite brave enough to tackle it yet */
+    spout = (struct sprefinfo *)aout->ptr;
 
     maxNumber = spin->num_servers;     /* max addrs this time */
     srvout = spout->servers;
@@ -4131,7 +4342,7 @@ DECL_PIOCTL(PGetCPrefs)
        srvout->host.s_addr = afs_cb_interface.addr_in[i];
 
     spout->num_servers = j;
-    *aoutSize = sizeof(struct sprefinfo) + (j - 1) * sizeof(struct spref);
+    aout->ptr += sizeof(struct sprefinfo) + (j - 1) * sizeof(struct spref);
 
     if (i >= afs_cb_interface.numberOfInterfaces)
        spout->next_offset = 0; /* start from beginning again */
@@ -4158,6 +4369,8 @@ DECL_PIOCTL(PGetCPrefs)
  */
 DECL_PIOCTL(PSetCPrefs)
 {
+    char *ainPtr;
+    size_t ainSize;
     struct setspref *sin;
     int i;
 
@@ -4165,7 +4378,13 @@ DECL_PIOCTL(PSetCPrefs)
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    sin = (struct setspref *)ain;
+    /* Yuck. Input to this function relies on reading past the end of
+     * structures. Bodge it for now.
+     */
+    ainPtr = ain->ptr;
+    ainSize = ain->remaining;
+
+    sin = (struct setspref *)ainPtr;
 
     if (ainSize < sizeof(struct setspref))
        return EINVAL;
@@ -4206,12 +4425,17 @@ DECL_PIOCTL(PFlushMount)
     register struct dcache *tdc;
     struct VenusFid tfid;
     char *bufp;
+    char *mount;
     struct sysname_info sysState;
     afs_size_t offset, len;
 
     AFS_STATCNT(PFlushMount);
     if (!avc)
        return EINVAL;
+
+    if (afs_pd_getStringPtr(ain, &mount) != 0)
+       return EINVAL;
+
     code = afs_VerifyVCache(avc, areq);
     if (code)
        return code;
@@ -4221,7 +4445,7 @@ DECL_PIOCTL(PFlushMount)
     tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
     if (!tdc)
        return ENOENT;
-    Check_AtSys(avc, ain, &sysState, areq);
+    Check_AtSys(avc, mount, &sysState, areq);
     ObtainReadLock(&tdc->lock);
     do {
        code = afs_dir_Lookup(tdc, sysState.name, &tfid.Fid);
@@ -4232,9 +4456,9 @@ DECL_PIOCTL(PFlushMount)
     if (code) {
        goto out;
     }
-    tfid.Cell = avc->fid.Cell;
-    tfid.Fid.Volume = avc->fid.Fid.Volume;
-    if (!tfid.Fid.Unique && (avc->states & CForeign)) {
+    tfid.Cell = avc->f.fid.Cell;
+    tfid.Fid.Volume = avc->f.fid.Fid.Volume;
+    if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
        tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
     } else {
        tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
@@ -4254,12 +4478,12 @@ DECL_PIOCTL(PFlushMount)
     ObtainWriteLock(&tvc->lock, 649);
     ObtainWriteLock(&afs_xcbhash, 650);
     afs_DequeueCallback(tvc);
-    tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
+    tvc->f.states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
     ReleaseWriteLock(&afs_xcbhash);
     /* now find the disk cache entries */
     afs_TryToSmush(tvc, *acred, 1);
     osi_dnlc_purgedp(tvc);
-    if (tvc->linkData && !(tvc->states & CCore)) {
+    if (tvc->linkData && !(tvc->f.states & CCore)) {
        afs_osi_Free(tvc->linkData, strlen(tvc->linkData) + 1);
        tvc->linkData = NULL;
     }
@@ -4289,22 +4513,17 @@ DECL_PIOCTL(PFlushMount)
  */
 DECL_PIOCTL(PRxStatProc)
 {
-    int code = 0;
     afs_int32 flags;
 
-    if (!afs_osi_suser(*acred)) {
-       code = EACCES;
-       goto out;
-    }
-    if (ainSize != sizeof(afs_int32)) {
-       code = EINVAL;
-       goto out;
-    }
-    memcpy((char *)&flags, ain, sizeof(afs_int32));
-    if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
-       code = EINVAL;
-       goto out;
-    }
+    if (!afs_osi_suser(*acred))
+       return EACCES;
+
+    if (afs_pd_getInt(ain, &flags) != 0)
+       return EINVAL;
+
+    if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK))
+       return EINVAL;
+
     if (flags & AFSCALL_RXSTATS_ENABLE) {
        rx_enableProcessRPCStats();
     }
@@ -4314,9 +4533,7 @@ DECL_PIOCTL(PRxStatProc)
     if (flags & AFSCALL_RXSTATS_CLEAR) {
        rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
     }
-  out:
-    *aoutSize = 0;
-    return code;
+    return 0;
 }
 
 
@@ -4335,22 +4552,17 @@ DECL_PIOCTL(PRxStatProc)
  */
 DECL_PIOCTL(PRxStatPeer)
 {
-    int code = 0;
     afs_int32 flags;
 
-    if (!afs_osi_suser(*acred)) {
-       code = EACCES;
-       goto out;
-    }
-    if (ainSize != sizeof(afs_int32)) {
-       code = EINVAL;
-       goto out;
-    }
-    memcpy((char *)&flags, ain, sizeof(afs_int32));
-    if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
-       code = EINVAL;
-       goto out;
-    }
+    if (!afs_osi_suser(*acred))
+       return EACCES;
+
+    if (afs_pd_getInt(ain, &flags) != 0)
+       return EINVAL;
+
+    if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK))
+       return EINVAL;
+
     if (flags & AFSCALL_RXSTATS_ENABLE) {
        rx_enablePeerRPCStats();
     }
@@ -4360,16 +4572,14 @@ DECL_PIOCTL(PRxStatPeer)
     if (flags & AFSCALL_RXSTATS_CLEAR) {
        rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
     }
-  out:
-    *aoutSize = 0;
-    return code;
+    return 0;
 }
 
 DECL_PIOCTL(PPrefetchFromTape)
 {
     register afs_int32 code, code1;
-    afs_int32 bytes;
-    struct conn *tc;
+    afs_int32 bytes, outval;
+    struct afs_conn *tc;
     struct rx_call *tcall;
     struct AFSVolSync tsync;
     struct AFSFetchStatus OutStatus;
@@ -4382,11 +4592,11 @@ DECL_PIOCTL(PPrefetchFromTape)
     if (!avc)
        return EINVAL;
 
-    if (ain && (ainSize == 3 * sizeof(afs_int32)))
-       Fid = (struct AFSFid *)ain;
-    else
-       Fid = &avc->fid.Fid;
-    tfid.Cell = avc->fid.Cell;
+    Fid = afs_pd_inline(ain, sizeof(struct AFSFid));
+    if (Fid == NULL)
+       Fid = &avc->f.fid.Fid;
+
+    tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = Fid->Volume;
     tfid.Fid.Vnode = Fid->Vnode;
     tfid.Fid.Unique = Fid->Unique;
@@ -4394,23 +4604,23 @@ DECL_PIOCTL(PPrefetchFromTape)
     tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
     if (!tvc) {
        afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD, ICL_TYPE_POINTER, tvc,
-                  ICL_TYPE_FID, &tfid, ICL_TYPE_FID, &avc->fid);
+                  ICL_TYPE_FID, &tfid, ICL_TYPE_FID, &avc->f.fid);
        return ENOENT;
     }
     afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD, ICL_TYPE_POINTER, tvc,
-              ICL_TYPE_FID, &tfid, ICL_TYPE_FID, &tvc->fid);
+              ICL_TYPE_FID, &tfid, ICL_TYPE_FID, &tvc->f.fid);
 
     do {
-       tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
+       tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK);
        if (tc) {
 
            RX_AFS_GUNLOCK();
            tcall = rx_NewCall(tc->id);
            code =
-               StartRXAFS_FetchData(tcall, (struct AFSFid *)&tvc->fid.Fid, 0,
+               StartRXAFS_FetchData(tcall, (struct AFSFid *)&tvc->f.fid.Fid, 0,
                                     0);
            if (!code) {
-               bytes = rx_Read(tcall, (char *)aout, sizeof(afs_int32));
+               bytes = rx_Read(tcall, (char *)&outval, sizeof(afs_int32));
                code =
                    EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
            }
@@ -4419,40 +4629,44 @@ DECL_PIOCTL(PPrefetchFromTape)
        } else
            code = -1;
     } while (afs_Analyze
-            (tc, code, &tvc->fid, areq, AFS_STATS_FS_RPCIDX_RESIDENCYRPCS,
+            (tc, code, &tvc->f.fid, areq, AFS_STATS_FS_RPCIDX_RESIDENCYRPCS,
              SHARED_LOCK, NULL));
     /* This call is done only to have the callback things handled correctly */
     afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
     afs_PutVCache(tvc);
 
-    if (!code) {
-       *aoutSize = sizeof(afs_int32);
-    }
-    return code;
+    if (code)
+       return code;
+
+    return afs_pd_putInt(aout, outval);
 }
 
-DECL_PIOCTL(PResidencyCmd)
+DECL_PIOCTL(PFsCmd)
 {
     register afs_int32 code;
-    struct conn *tc;
+    struct afs_conn *tc;
     struct vcache *tvc;
-    struct ResidencyCmdInputs *Inputs;
-    struct ResidencyCmdOutputs *Outputs;
+    struct FsCmdInputs *Inputs;
+    struct FsCmdOutputs *Outputs;
     struct VenusFid tfid;
     struct AFSFid *Fid;
 
-    Inputs = (struct ResidencyCmdInputs *)ain;
-    Outputs = (struct ResidencyCmdOutputs *)aout;
     if (!avc)
        return EINVAL;
-    if (!ain || ainSize != sizeof(struct ResidencyCmdInputs))
+
+    Inputs = afs_pd_inline(ain, sizeof(*Inputs));
+    if (Inputs == NULL)
        return EINVAL;
 
+    Outputs = afs_pd_inline(aout, sizeof(*Outputs));
+    if (Outputs == NULL)
+       return E2BIG;
+
     Fid = &Inputs->fid;
     if (!Fid->Volume)
-       Fid = &avc->fid.Fid;
+       Fid = &avc->f.fid.Fid;
 
-    tfid.Cell = avc->fid.Cell;
+    tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = Fid->Volume;
     tfid.Fid.Vnode = Fid->Vnode;
     tfid.Fid.Unique = Fid->Unique;
@@ -4465,17 +4679,17 @@ DECL_PIOCTL(PResidencyCmd)
 
     if (Inputs->command) {
        do {
-           tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
+           tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK);
            if (tc) {
                RX_AFS_GUNLOCK();
                code =
-                   RXAFS_ResidencyCmd(tc->id, Fid, Inputs,
-                                      (struct ResidencyCmdOutputs *)aout);
+                   RXAFS_FsCmd(tc->id, Fid, Inputs, 
+                                       (struct FsCmdOutputs *)aout);
                RX_AFS_GLOCK();
            } else
                code = -1;
        } while (afs_Analyze
-                (tc, code, &tvc->fid, areq,
+                (tc, code, &tvc->f.fid, areq,
                  AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK, NULL));
        /* This call is done to have the callback things handled correctly */
        afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
@@ -4493,9 +4707,6 @@ DECL_PIOCTL(PResidencyCmd)
 
     afs_PutVCache(tvc);
 
-    if (!code) {
-       *aoutSize = sizeof(struct ResidencyCmdOutputs);
-    }
     return code;
 }
 
@@ -4505,7 +4716,7 @@ DECL_PIOCTL(PNewUuid)
     if (!afs_resourceinit_flag)        /* afs deamons havn't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    if (!afs_osi_suser(acred))
+    if (!afs_osi_suser(*acred))
        return EACCES;
 
     ObtainWriteLock(&afs_xinterface, 555);
@@ -4519,12 +4730,11 @@ DECL_PIOCTL(PNewUuid)
 
 DECL_PIOCTL(PSetCachingThreshold)
 {
-    afs_int32 getting;
-    afs_int32 setting;
-
-    setting = getting = 1;
+    afs_int32 getting = 1;
+    afs_int32 setting = 1;
+    afs_int32 threshold;
 
-    if (ain == NULL || ainSize < sizeof(afs_int32))
+    if (afs_pd_getInt(ain, &threshold) != 0)
        setting = 0;
 
     if (aout == NULL)
@@ -4537,23 +4747,17 @@ DECL_PIOCTL(PSetCachingThreshold)
      * If setting, set first, and return the value now in effect
      */
     if (setting) {
-       afs_int32 threshold;
-
        if (!afs_osi_suser(*acred))
            return EPERM;
-       memcpy((char *)&threshold, ain, sizeof(afs_int32));
        cache_bypass_threshold = threshold;
         afs_warn("Cache Bypass Threshold set to: %d\n", threshold);            
        /* TODO:  move to separate pioctl, or enhance pioctl */
        cache_bypass_strategy = LARGE_FILES_BYPASS_CACHE;
     }
        
+    /* Return the current size threshold */
     if (getting) {
-       /* Return the current size threshold */
-       afs_int32 oldThreshold = cache_bypass_threshold;
-       memcpy(aout, (char *)&oldThreshold, sizeof(afs_int32));
-       *aoutSize = sizeof(afs_int32);
-    }
+       return afs_pd_putInt32(aout, cache_bypass_threshold);
 
     return(0);
 }
@@ -4567,7 +4771,7 @@ DECL_PIOCTL(PCallBackAddr)
     int srvAddrCount;
     struct server *ts;
     struct srvAddr *sa;
-    struct conn *tc;
+    struct afs_conn *tc;
     afs_int32 i, j;
     struct unixuser *tu;
     struct srvAddr **addrs;
@@ -4579,11 +4783,9 @@ DECL_PIOCTL(PCallBackAddr)
     if (!afs_osi_suser(acred))
        return EACCES;
 
-    if (ainSize < sizeof(afs_int32))
+    if (afs_pd_getInt(ain, &addr) != 0)
        return EINVAL;
 
-    memcpy(&addr, ain, sizeof(afs_int32));
-
     ObtainReadLock(&afs_xinterface);
     for (i = 0; (unsigned short)i < afs_cb_interface.numberOfInterfaces; i++) {
        if (afs_cb_interface.addr_in[i] == addr)
@@ -4664,17 +4866,17 @@ DECL_PIOCTL(PDiscon)
     static afs_int32 mode = 1; /* Start up in 'off' */
     afs_int32 force = 0;
     int code = 0;
+    char flags[3];
 
-    if (ainSize) {
-
+    if (afs_pd_getBytes(ain, &flags, 3) == 0) {
        if (!afs_osi_suser(*acred))
            return EPERM;
 
-       if (ain[0])
-           mode = ain[0] - 1;
-       if (ain[1])
-           afs_ConflictPolicy = ain[1] - 1;
-       if (ain[2])
+       if (flags[0])
+           mode = flags[0] - 1;
+       if (flags[1])
+           afs_ConflictPolicy = flags[1] - 1;
+       if (flags[2])
            force = 1;
 
        /*
@@ -4696,13 +4898,19 @@ DECL_PIOCTL(PDiscon)
            ObtainWriteLock(&afs_discon_lock, 998);
 
            afs_in_sync = 1;
+           afs_MarkAllServersUp();
            code = afs_ResyncDisconFiles(areq, *acred);
            afs_in_sync = 0;
 
            if (code && !force) {
-               printf("Files not synchronized properly, still in discon state. \
-                                               Please retry or use \"force\".\n");
+               printf("Files not synchronized properly, still in discon state. \n"
+                      "Please retry or use \"force\".\n");
+               mode = 0;
            } else {
+               if (force) {
+                   afs_DisconDiscardAll(*acred);
+               }
+               afs_ClearAllStatdFlag();
                afs_is_disconnected = 0;
                afs_is_discon_rw = 0;
                printf("\nSync succeeded. You are back online.\n");
@@ -4717,9 +4925,10 @@ DECL_PIOCTL(PDiscon)
        return EINVAL;
     }
 
-    memcpy(aout, &mode, sizeof(afs_int32));
-    *aoutSize = sizeof(afs_int32);
-    return 0;
+    if (code)
+       return code;
+
+    return afs_pd_putInt(aout, mode);
 #else
     return EINVAL;
 #endif
@@ -4727,7 +4936,7 @@ DECL_PIOCTL(PDiscon)
 
 DECL_PIOCTL(PNFSNukeCreds)
 {
-    afs_uint32 addr, code;
+    afs_uint32 addr;
     register afs_int32 i;
     register struct unixuser *tu;
 
@@ -4735,11 +4944,10 @@ DECL_PIOCTL(PNFSNukeCreds)
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    if (ainSize < sizeof(afs_int32))
+    if (afs_pd_getUint(ain, &addr) != 0)
        return EINVAL;
-    memcpy(&addr, ain, sizeof(afs_int32));
 
-    if ((*acred)->cr_gid == RMTUSER_REQ_PRIV && !addr) {
+    if (afs_cr_gid(*acred) == RMTUSER_REQ_PRIV && !addr) {
        tu = afs_GetUser(areq->uid, -1, SHARED_LOCK);
        if (!tu->exporter || !(addr = EXP_GETHOST(tu->exporter))) {
            afs_PutUser(tu, SHARED_LOCK);
@@ -4757,7 +4965,7 @@ DECL_PIOCTL(PNFSNukeCreds)
                tu->vid = UNDEFVID;
                tu->states &= ~UHasTokens;
                /* security is not having to say you're sorry */
-               memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
+               memset(&tu->ct, 0, sizeof(struct ClearToken));
                tu->refCount++;
                ReleaseWriteLock(&afs_xuser);
                afs_ResetUserConns(tu);