Fix pioctl input and output handling
[openafs.git] / src / afs / afs_pioctl.c
index d533096..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
@@ -23,6 +21,7 @@ RCSID
 #include "afsincludes.h"       /* Afs-based standard headers */
 #include "afs/afs_stats.h"     /* afs statistics */
 #include "afs/vice.h"
+#include "afs/afs_bypasscache.h"
 #include "rx/rx_globals.h"
 
 struct VenusFid afs_rootFid;
@@ -30,9 +29,194 @@ afs_int32 afs_waitForever = 0;
 short afs_waitForeverCount = 0;
 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE;        /* show all messages */
 
-#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)
+#ifdef AFS_DISCON_ENV
+afs_int32 afs_is_disconnected;
+afs_int32 afs_is_discon_rw;
+/* On reconnection, turn this knob on until it finishes,
+ * then turn it off.
+ */
+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
+ *     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, \
+                    struct afs_pdata *ain, struct afs_pdata *aout, \
+                    afs_ucred_t **acred)
 
 /* Prototypes for pioctl routines */
 DECL_PIOCTL(PGetFID);
@@ -88,12 +272,17 @@ 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);
+#endif
 
 /*
  * A macro that says whether we're going to need HandleClientContext().
@@ -106,19 +295,22 @@ DECL_PIOCTL(PPrecache);
 /* 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 *,
+                              struct afs_pdata *, struct afs_pdata *,
+                              afs_ucred_t **);
 
-static int (*(VpioctlSw[])) () = {
+static pioctlFunction VpioctlSw[] = {
     PBogus,                    /* 0 */
        PSetAcl,                /* 1 */
        PGetAcl,                /* 2 */
@@ -186,12 +378,12 @@ static int (*(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 */
 };
 
-static int (*(CpioctlSw[])) () = {
+static pioctlFunction CpioctlSw[] = {
     PBogus,                    /* 0 */
        PNewAlias,              /* 1 -- create new cell alias */
        PListAliases,           /* 2 -- list cell aliases */
@@ -205,11 +397,17 @@ static int (*(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 */
+    PNFSNukeCreds,             /* 1 -- nuke all creds for NFS client */
+#if defined(AFS_CACHE_BYPASS)
+    PSetCachingThreshold        /* 2 -- get/set cache-bypass size threshold */
+#else
+    PNoop                       /* 2 -- get/set cache-bypass size threshold */
+#endif
 };
 
 #define PSetClientContext 99   /*  Special pioctl to setup caller's creds  */
@@ -226,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,
@@ -239,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 */
 
@@ -277,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
@@ -344,30 +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__
-kioctl(fdes, com, arg, ext, arg2, arg3)
-#else /* __64BIT__ */
-kioctl32(fdes, com, arg, ext, arg2, arg3)
-#endif /* __64BIT__ */
-     caddr_t arg2, arg3;
-#else
-kioctl(fdes, com, arg, ext)
-#endif
-     int fdes, com;
-     caddr_t arg, ext;
+# 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__ */
+int
+kioctl32(int fdes, int com, caddr_t arg, caddr_t ext, caddr_t arg2, 
+            caddr_t arg3)
+#    endif /* __64BIT__ */
+#   else
+int
+kioctl(int fdes, int com, caddr_t arg, caddr_t ext)
+#   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;
@@ -375,31 +575,17 @@ struct afs_ioctl_sys {
     int arg;
 };
 
-afs_xioctl(uap, rvp)
-     struct afs_ioctl_sys *uap;
-     rval_t *rvp;
+int 
+afs_xioctl(struct afs_ioctl_sys *uap, rval_t *rvp)
 {
-#elif defined(AFS_OSF_ENV)
-afs_xioctl(p, args, retval)
-     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(td, uap, retval)
-     struct thread *td;
-     register struct ioctl_args *uap;
-     register_t *retval;
+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;
@@ -407,12 +593,9 @@ struct ioctl_args {
 };
 
 int
-afs_xioctl(p, uap, retval)
-     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;
@@ -422,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)
 {
@@ -431,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') {
@@ -524,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)
@@ -672,36 +819,16 @@ 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(p, args, retval)
-     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)
 int
-afs_pioctl(td, args, retval)
-     struct thread *td;
-     void *args;
-     int *retval;
+afs_pioctl(struct thread *td, void *args, int *retval)
 {
     struct a {
        char *path;
@@ -717,10 +844,7 @@ afs_pioctl(td, args, retval)
 
 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 int
-afs_pioctl(p, args, retval)
-     struct proc *p;
-     void *args;
-     int *retval;
+afs_pioctl(afs_proc_t *p, void *args, int *retval)
 {
     struct a {
        char *path;
@@ -730,15 +854,15 @@ afs_pioctl(p, args, 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
@@ -752,27 +876,27 @@ afs_pioctl(p, args, retval)
 
 int
 #ifdef AFS_SUN5_ENV
-afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
-     rval_t *rvp;
-     struct AFS_UCRED *credp;
+afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow, 
+                  rval_t *vvp, afs_ucred_t *credp)
 #else
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_syscall_pioctl(path, com, cmarg, follow, credp)
-     struct AFS_UCRED *credp;
+#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, 
+                  afs_ucred_t *credp)
 #else
-afs_syscall_pioctl(path, com, cmarg, follow)
+afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
 #endif
 #endif
-     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
@@ -868,11 +992,14 @@ afs_syscall_pioctl(path, com, cmarg, 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();
@@ -970,6 +1097,10 @@ afs_syscall_pioctl(path, com, cmarg, 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
     }
@@ -983,37 +1114,53 @@ afs_syscall_pioctl(path, com, cmarg, 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;
-    int (*(*pioctlSw)) ();
+    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) {
@@ -1030,98 +1177,110 @@ 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);
+       code = afs_pd_alloc(&output, AFS_LRALLOCSIZ);
     }
-    if (!outData) {
-       if (inSize > AFS_LRALLOCSIZ) {
-           osi_Free(inData, inSize + 1);
-       } else {
-           osi_FreeLargeSpace(inData);
-       }
-       afs_PutFakeStat(&fakestate);
-       return ENOMEM;
-    }
-    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);
 }
 
+/*!
+ * VIOCGETFID (22) - Get file ID quickly
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    fid of requested file
+ *
+ * \retval EINVAL      Error if some of the initial arguments aren't set
+ *
+ * \post get the file id of some file
+ */
 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;
 }
 
-DECL_PIOCTL(PSetAcl)
+/*!
+ * VIOCSETAL (1) - Set access control list
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the ACL being set
+ * \param[out] aout    the ACL being set returned
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ *
+ * \post Changed ACL, via direct writing to the wire
+ */
+int dummy_PSetAcl(char *ain, char *aout)
 {
-    register afs_int32 code;
-    struct conn *tconn;
-    struct AFSOpaque acl;
+    return 0;
+}
+
+DECL_PIOCTL(PSetAcl)
+{
+    register afs_int32 code;
+    struct afs_conn *tconn;
+    struct AFSOpaque acl;
     struct AFSVolSync tsync;
     struct AFSFetchStatus OutStatus;
     XSTATS_DECLS;
@@ -1129,70 +1288,100 @@ 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;
 }
 
 int afs_defaultAsynchrony = 0;
 
+/*!
+ * VIOC_STOREBEHIND (47) Adjust store asynchrony
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      sbstruct (store behind structure) input
+ * \param[out] aout    resulting sbstruct
+ *
+ * \retval EPERM       Error if the user doesn't have super-user credentials
+ * \retval EACCES      Error if there isn't enough access to not check the mode bits
+ *
+ * \post sets asynchrony based on a file, from a struct sbstruct "I THINK"
+ */
 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));
 }
 
+/*!
+ * VIOC_GCPAGS (48) - Disable automatic PAG gc'ing
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    not in use
+ *
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ *
+ * \post set the gcpags to GCPAGS_USERDISABLED
+ */
 DECL_PIOCTL(PGCPAGs)
 {
     if (!afs_osi_suser(*acred)) {
@@ -1202,23 +1391,39 @@ DECL_PIOCTL(PGCPAGs)
     return 0;
 }
 
+/*!
+ * VIOCGETAL (2) - Get access control list
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    the ACL
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ * \retval ERANGE      Error if the vnode of the file id is too large
+ * \retval -1          Error if getting the ACL failed
+ *
+ * \post Obtain the ACL, based on file ID
+ *
+ * \notes there is a hack to tell which type of ACL is being returned, checks the top 2-bytes to judge what type of ACL it is, only for dfs xlat or ACLs
+ */
 DECL_PIOCTL(PGetAcl)
 {
     struct AFSOpaque acl;
     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
@@ -1228,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);
@@ -1243,27 +1448,59 @@ 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;
 }
 
+/*!
+ * PNoop returns success.  Used for functions which are not implemented or are no longer in use.
+ *
+ * \ingroup pioctl
+ *
+ * \notes Functions involved in this: 17 (VIOCENGROUP) -- used to be enable group; 18 (VIOCDISGROUP) -- used to be disable group; 2 (?) -- get/set cache-bypass size threshold
+ */
 DECL_PIOCTL(PNoop)
 {
     AFS_STATCNT(PNoop);
     return 0;
 }
 
+/*!
+ * PBogus returns fail.  Used for functions which are not implemented or are no longer in use.
+ *
+ * \ingroup pioctl
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ *
+ * \notes Functions involved in this: 0 (?); 4 (?); 6 (?); 7 (VIOCSTAT); 8 (?); 13 (VIOCGETTIME) -- used to be quick check time; 15 (VIOCPREFETCH) -- prefetch is now special-cased; see pioctl code!; 16 (VIOCNOP) -- used to be testing code; 19 (VIOCLISTGROUPS) -- used to be list group; 23 (VIOCWAITFOREVER) -- used to be waitforever; 57 (VIOC_FPRIOSTATUS) -- arla: set file prio; 58 (VIOC_FHGET) -- arla: fallback getfh; 59 (VIOC_FHOPEN) -- arla: fallback fhopen; 60 (VIOC_XFSDEBUG) -- arla: controls xfsdebug; 61 (VIOC_ARLADEBUG) -- arla: controls arla debug; 62 (VIOC_AVIATOR) -- arla: debug interface; 63 (VIOC_XFSDEBUG_PRINT) -- arla: print xfs status; 64 (VIOC_CALCULATE_CACHE) -- arla: force cache check; 65 (VIOC_BREAKCELLBACK) -- arla: break callback; 68 (?) -- arla: fetch stats;
+ */
 DECL_PIOCTL(PBogus)
 {
     AFS_STATCNT(PBogus);
     return EINVAL;
 }
 
+/*!
+ * VIOC_FILE_CELL_NAME (30) - Get cell in which file lives
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use (avc used to pass in file id)
+ * \param[out] aout    cell name
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ * \retval ESRCH       Error if the file isn't part of a cell
+ *
+ * \post Get a cell based on a passed in file id
+ */
 DECL_PIOCTL(PGetFileCell)
 {
     register struct cell *tcell;
@@ -1271,15 +1508,30 @@ 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;
 }
 
+/*!
+ * VIOC_GET_WS_CELL (31) - Get cell in which workstation lives
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    cell name
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval ESRCH       Error if the machine isn't part of a cell, for whatever reason
+ *
+ * \post Get the primary cell that the machine is a part of.
+ */
 DECL_PIOCTL(PGetWSCell)
 {
     struct cell *tcell = NULL;
@@ -1291,12 +1543,25 @@ 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;
 }
 
+/*!
+ * VIOC_GET_PRIMARY_CELL (33) - Get primary cell for caller
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use (user id found via areq)
+ * \param[out] aout    cell name
+ *
+ * \retval ESRCH       Error if the user id doesn't have a primary cell specified
+ *
+ * \post Get the primary cell for a certain user, based on the user's uid
+ */
 DECL_PIOCTL(PGetUserCell)
 {
     register afs_int32 i;
@@ -1323,18 +1588,31 @@ 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;
 }
 
+/*!
+ * VIOCSETTOK (3) - Set authentication tokens
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the krb tickets from which to set the afs tokens
+ * \param[out] aout    not in use
+ *
+ * \retval EINVAL      Error if the ticket is either too long or too short
+ * \retval EIO         Error if the AFS initState is below 101
+ * \retval ESRCH       Error if the cell for which the Token is being set can't be found
+ *
+ * \post Set the Tokens for a specific cell name, unless there is none set, then default to primary
+ *
+ */
 DECL_PIOCTL(PSetTokens)
 {
     afs_int32 i;
@@ -1342,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;
@@ -1350,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 {
@@ -1389,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;
        }
@@ -1449,16 +1735,27 @@ DECL_PIOCTL(PSetTokens)
     }
 }
 
+/*!
+ * VIOCGETVOLSTAT (4) - Get volume status
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    status of the volume
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ *
+ * \post The status of a volume (based on the FID of the volume), or an offline message /motd
+ */
 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);
@@ -1467,95 +1764,101 @@ 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);
     return code;
 }
 
+/*!
+ * VIOCSETVOLSTAT (5) - Set volume status
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      values to set the status at, offline message, message of the day, volume name, minimum quota, maximum quota
+ * \param[out] aout    status of a volume, offlines messages, minimum quota, maximumm quota
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ * \retval EROFS       Error if the volume is read only, or a backup volume
+ * \retval ENODEV      Error if the volume can't be accessed
+ * \retval E2BIG       Error if the volume name, offline message, and motd are too big
+ *
+ * \post Set the status of a volume, including any offline messages, a minimum quota, and a maximum quota
+ */
 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;
@@ -1566,41 +1869,52 @@ 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;
 }
 
+/*!
+ * VIOCFLUSH (6) - Invalidate cache entry
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    not in use
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ *
+ * \post Flush any information the cache manager has on an entry
+ */
 DECL_PIOCTL(PFlush)
 {
     AFS_STATCNT(PFlush);
@@ -1610,17 +1924,7 @@ DECL_PIOCTL(PFlush)
     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_ResetVCache(avc, *acred);
     ReleaseWriteLock(&avc->lock);
 #ifdef AFS_BOZONLOCK_ENV
     afs_BozonUnlock(&avc->pvnLock, avc);
@@ -1628,6 +1932,20 @@ DECL_PIOCTL(PFlush)
     return 0;
 }
 
+/*!
+ * VIOC_AFS_STAT_MT_PT (29) - Stat mount point
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the last component in a path, related to mountpoint that we're looking for information about
+ * \param[out] aout    volume, cell, link data 
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ * \retval ENOTDIR     Error if the 'mount point' argument isn't a directory
+ * \retval EIO         Error if the link data can't be accessed
+ *
+ * \post Get the volume, and cell, as well as the link data for a mount point
+ */
 DECL_PIOCTL(PNewStatMount)
 {
     register afs_int32 code;
@@ -1635,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;
@@ -1650,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);
@@ -1661,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);
@@ -1685,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;
@@ -1699,14 +2022,31 @@ DECL_PIOCTL(PNewStatMount)
     return code;
 }
 
+/*!
+ * VIOCGETTOK (8) - Get authentication tokens
+ *  
+ * \ingroup pioctl
+ *      
+ * \param[in] ain       userid
+ * \param[out] aout     token
+ * 
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval EDOM                Error if the input parameter is out of the bounds of the available tokens
+ * \retval ENOTCONN    Error if there aren't tokens for this cell
+ *  
+ * \post If the input paramater exists, get the token that corresponds to the parameter value, if there is no token at this value, get the token for the first cell
+ *
+ * \notes "it's a weird interface (from comments in the code)"
+ */
+
 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 */
@@ -1721,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);
@@ -1754,38 +2096,62 @@ 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;
 }
 
+/*!
+ * VIOCUNLOG (9) - Invalidate tokens
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    not in use
+ *
+ * \retval EIO Error if the afs daemon hasn't been started yet
+ *
+ * \post remove tokens from a user, specified by the user id
+ *
+ * \notes sets the token's time to 0, which then causes it to be removed
+ * \notes Unlog is the same as un-pag in OpenAFS
+ */
 DECL_PIOCTL(PUnlog)
 {
     register afs_int32 i;
@@ -1802,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
@@ -1829,6 +2195,18 @@ DECL_PIOCTL(PUnlog)
     return 0;
 }
 
+/*!
+ * VIOC_AFS_MARINER_HOST (32) - Get/set mariner (cache manager monitor) host
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      host address to be set
+ * \param[out] aout    old host address
+ *
+ * \post depending on whether or not a variable is set, either get the host for the cache manager monitor, or set the old address and give it a new address
+ *
+ * \notes Errors turn off mariner
+ */
 DECL_PIOCTL(PMariner)
 {
     afs_int32 newHostAddr;
@@ -1841,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;
@@ -1849,17 +2229,33 @@ 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;
 }
 
+/*!
+ * VIOCCKSERV (10) - Check that servers are up
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      name of the cell
+ * \param[out] aout    current down server list
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ * \retval ENOENT      Error if we are unable to obtain the cell
+ *
+ * \post Either a fast check (where it doesn't contact servers) or a local check (checks local cell only)
+ */
 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;
 
@@ -1868,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;
@@ -1881,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
@@ -1912,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) {
@@ -1920,18 +2325,28 @@ 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;
 }
 
+/*!
+ * VIOCCKBACK (11) - Check backup volume mappings
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    not in use
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ *
+ * \post Check the root volume, and then check the names if the volume check variable is set to force, has expired, is busy, or if the mount points variable is set
+ */
 DECL_PIOCTL(PCheckVolNames)
 {
     AFS_STATCNT(PCheckVolNames);
@@ -1944,11 +2359,25 @@ DECL_PIOCTL(PCheckVolNames)
     return 0;
 }
 
+/*!
+ * VIOCCKCONN (12) - Check connections for a user
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    not in use
+ *
+ * \retval EACCESS Error if no user is specififed, the user has no tokens set, or if the user's tokens are bad
+ *
+ * \post check to see if a user has the correct authentication.  If so, allow access.
+ *
+ * \notes Check the connections to all the servers specified
+ */
 DECL_PIOCTL(PCheckAuth)
 {
     int i;
     struct srvAddr *sa;
-    struct conn *tc;
+    struct afs_conn *tc;
     struct unixuser *tu;
     afs_int32 retValue;
 
@@ -1981,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;
@@ -2016,39 +2445,69 @@ Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
     return 0;
 }
 
+/*!
+ * VIOCWHEREIS (14) - Find out where a volume is located
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    volume location
+ *
+ * \retval EINVAL      Error if some of the default arguments don't exist
+ * \retval ENODEV      Error if there is no such volume
+ *
+ * \post fine a volume, based on a volume file id
+ *
+ * \notes check each of the servers specified
+ */
 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;
 }
 
+/*!
+ * VIOCACCESS (20) - Access using PRS_FS bits
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      PRS_FS bits
+ * \param[out] aout    not in use
+ *
+ * \retval EINVAL      Error if some of the initial arguments aren't set
+ * \retval EACCES      Error if access is denied
+ *
+ * \post check to make sure access is allowed
+ */
 DECL_PIOCTL(PViceAccess)
 {
     register afs_int32 code;
@@ -2057,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;
@@ -2068,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;
@@ -2075,23 +2557,43 @@ 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;
 }
 
+/*!
+ * VIOCSETCACHESIZE (24) - Set venus cache size in 1000 units
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the size the venus cache should be set to
+ * \param[out] aout    not in use
+ *
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ * \retval EROFS       Error if the cache is set to be in memory
+ *
+ * \post Set the cache size based on user input.  If no size is given, set it to the default OpenAFS cache size.
+ *
+ * \notes recompute the general cache parameters for every single block allocated
+ */
 DECL_PIOCTL(PSetCacheSize)
 {
     afs_int32 newValue;
     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 {
@@ -2111,6 +2613,16 @@ DECL_PIOCTL(PSetCacheSize)
 }
 
 #define MAXGCSTATS     16
+/*!
+ * VIOCGETCACHEPARMS (40) - Get cache stats
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      afs index flags
+ * \param[out] aout    cache blocks, blocks used, blocks files (in an array)
+ *
+ * \post Get the cache blocks, and how many of the cache blocks there are
+ */
 DECL_PIOCTL(PGetCacheSize)
 {
     afs_int32 results[MAXGCSTATS];
@@ -2120,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;
@@ -2159,14 +2671,25 @@ DECL_PIOCTL(PGetCacheSize)
            }
         }
     }
-    memcpy(aout, (char *)results, sizeof(results));
-    *aoutSize = sizeof(results);
-    return 0;
+    return afs_pd_putBytes(aout, results, sizeof(results));
 }
 
+/*!
+ * VIOCFLUSHCB (25) - Flush callback only
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    not in use
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ * \retval 0           0 returned if the volume is set to read-only
+ *
+ * \post Flushes callbacks, by setting the length of callbacks to one, setting the next callback to be sent to the CB_DROPPED value, and then dequeues everything else.
+ */
 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;
@@ -2176,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();
@@ -2196,29 +2719,44 @@ 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);
     return 0;
 }
 
+/*!
+ * VIOCNEWCELL (26) - Configure new cell
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the name of the cell, the hosts that will be a part of the cell, whether or not it's linked with another cell, the other cell it's linked with, the file server port, and the volume server port
+ * \param[out] aout    not in use
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval EACCES      Error if the user doesn't have super-user cedentials
+ * \retval EINVAL      Error if some 'magic' var doesn't have a certain bit set
+ *
+ * \post creates a new cell
+ */
 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 */
@@ -2227,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;
+    }
 
-    lp = (afs_int32 *) tp;
-    fsport = *lp++;
-    vlport = *lp++;
+    /* 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;
+
+    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;
     }
 
@@ -2268,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 */
@@ -2278,88 +2835,116 @@ 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);
 }
 
+/*!
+ * VIOCGETCELL (27) - Get cell info
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      The cell index of a specific cell
+ * \param[out] aout    list of servers in the cell
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval EDOM                Error if there is no cell asked about
+ *
+ * \post Lists the cell's server names and and addresses
+ */
 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;
 }
 
+/*!
+ * VIOC_AFS_DELETE_MT_PT (28) - Delete mount point
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the name of the file in this dir to remove
+ * \param[out] aout    not in use
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ * \retval ENOTDIR     Error if the argument to remove is not a directory
+ * \retval ENOENT      Error if there is no cache to remove the mount point from or if a vcache doesn't exist
+ *
+ * \post Ensure that everything is OK before deleting the mountpoint.  If not, don't delete.  Delete a mount point based on a file id.
+ */
 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;
@@ -2367,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;
@@ -2382,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);
@@ -2393,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);
@@ -2430,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) {
@@ -2465,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:
@@ -2474,45 +3061,90 @@ DECL_PIOCTL(PRemoveMount)
     return code;
 }
 
+/*!
+ * VIOC_VENUSLOG (34) - Enable/Disable venus logging
+ *
+ * \ingroup pioctl
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ *
+ * \notes Obsoleted, perhaps should be PBogus
+ */
 DECL_PIOCTL(PVenusLogging)
 {
     return EINVAL;             /* OBSOLETE */
 }
 
+/*!
+ * VIOC_GETCELLSTATUS (35) - Get cell status info
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      The cell you want status information on
+ * \param[out] aout    cell state (as a struct)
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval ENOENT      Error if the cell doesn't exist
+ *
+ * \post Returns the state of the cell as defined in a struct cell
+ */
 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);
 }
 
+/*!
+ * VIOC_SETCELLSTATUS (36) - Set corresponding info
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      The cell you want to set information about, and the values you want to set
+ * \param[out] aout    not in use
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ *
+ * \post Set the state of the cell in a defined struct cell, based on whether or not SetUID is allowed
+ */
 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;
@@ -2520,6 +3152,21 @@ DECL_PIOCTL(PSetCellStatus)
     return 0;
 }
 
+/*!
+ * VIOC_FLUSHVOLUME (37) - Flush whole volume's data
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use (args in avc)
+ * \param[out] aout    not in use
+ *
+ * \retval EINVAL      Error if some of the standard args aren't set
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ *
+ * \post Wipe everything on the volume.  This is done dependent on which platform this is for.
+ *
+ * \notes Does not flush a file that a user has open and is using, because it will be re-created on next write.  Also purges the dnlc, because things are screwed up.
+ */
 DECL_PIOCTL(PFlushVolumeData)
 {
     register afs_int32 i;
@@ -2538,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
@@ -2547,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;
@@ -2577,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 */
@@ -2593,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);
@@ -2614,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 */
@@ -2638,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++) {
@@ -2658,7 +3301,19 @@ DECL_PIOCTL(PFlushVolumeData)
 }
 
 
-
+/*!
+ * VIOCGETVCXSTATUS (41) - gets vnode x status
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use (avc used)
+ * \param[out] aout    vcxstat: the file id, the data version, any lock, the parent vnode, the parent unique id, the trunc position, the callback, cbExpires, what access is being made, what files are open, any users executing/writing, the flock ount, the states, the move stat
+ *
+ * \retval EINVAL      Error if some of the initial default arguments aren't set
+ * \retval EACCES      Error if access to check the mode bits is denied
+ *
+ * \post gets stats for the vnode, a struct listed in vcxstat
+ */
 DECL_PIOCTL(PGetVnodeXStatus)
 {
     register afs_int32 code;
@@ -2679,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;
 
@@ -2697,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));
 }
 
 
@@ -2730,22 +3383,34 @@ 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));
 }
 
-/* We require root for local sysname changes, but not for remote */
-/* (since we don't really believe remote uids anyway) */
- /* outname[] shouldn't really be needed- this is left as an excercise */
- /* for the reader.  */
+
+/*!
+ * VIOC_AFS_SYSNAME (38) - Change @sys value
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      new value for @sys
+ * \param[out] aout    count, entry, list (debug values?)
+ *
+ * \retval EINVAL      Error if afsd isn't running, the new sysname is too large, the new sysname causes issues (starts with a .0 or ..0), there is no PAG set in the credentials, the user of a PAG can't be found, (!(exporter = au->exporter)) "NOT SURE ON THIS"
+ * \retval ENODEV      Error if there isn't already a system named that ("I THINK")
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ *
+ * \post Set the value of @sys if these things work: if the input isn't too long or if input doesn't start with .0 or ..0
+ *
+ * \notes We require root for local sysname changes, but not for remote (since we don't really believe remote uids anyway) outname[] shouldn't really be needed- this is left as an exercise for the reader.
+ */
 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;
@@ -2753,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) {
@@ -2763,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;
@@ -2775,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);
@@ -2810,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)
@@ -2845,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;
@@ -2862,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
@@ -2875,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;
 }
@@ -2903,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);
        }
     }
@@ -2934,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;
                }
@@ -2946,10 +3611,7 @@ ReSortCells(int s, afs_int32 * l, int vlonly)
 
 static int debugsetsp = 0;
 static int
-afs_setsprefs(sp, num, vlonly)
-     struct spref *sp;
-     unsigned int num;
-     unsigned int vlonly;
+afs_setsprefs(struct spref *sp, unsigned int num, unsigned int vlonly)
 {
     struct srvAddr *sa;
     int i, j, k, matches, touchedSize;
@@ -3019,11 +3681,24 @@ afs_setsprefs(sp, num, vlonly)
     return 0;
 }
 
- /* Note that this may only be performed by the local root user.
-  */
+/*!
+ * VIOC_SETPREFS (46) - Set server ranks
+ *
+ * \param[in] ain      the sprefs value you want the sprefs to be set to
+ * \param[out] aout    not in use
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ * \retval EINVAL      Error if the struct setsprefs is too large or if it multiplied by the number of servers is too large
+ *
+ * \post set the sprefs using the afs_setsprefs() function
+ */
 DECL_PIOCTL(PSetSPrefs)
 {
     struct setspref *ssp;
+    char *ainPtr;
+    size_t ainSize;
+
     AFS_STATCNT(PSetSPrefs);
 
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
@@ -3032,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,
@@ -3044,9 +3725,21 @@ DECL_PIOCTL(PSetSPrefs)
     return 0;
 }
 
+/* 
+ * VIOC_SETPREFS33 (42) - Set server ranks (deprecated)
+ *
+ * \param[in] ain      the server preferences to be set
+ * \param[out] aout    not in use
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ *
+ * \post set the server preferences, calling a function
+ *
+ * \notes this may only be performed by the local root user.
+ */
 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 */
@@ -3055,21 +3748,30 @@ 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;
 }
 
-/* some notes on the following code...
- * in the hash table of server structs, all servers with the same IP address
- * will be on the same overflow chain.
- * This could be sped slightly in some circumstances by having it cache the
- * immediately previous slot in the hash table and some supporting information
- * Only reports file servers now.
+/* 
+ * VIOC_GETSPREFS (43) - Get server ranks
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the server preferences to get
+ * \param[out] aout    the server preferences information
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval ENOENT      Error if the sprefrequest is too large
+ *
+ * \post Get the sprefs
+ *
+ * \notes in the hash table of server structs, all servers with the same IP address; will be on the same overflow chain; This could be sped slightly in some circumstances by having it cache the immediately previous slot in the hash table and some supporting information; Only reports file servers now.
  */
 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 */
@@ -3082,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++;
@@ -3120,26 +3826,42 @@ 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;
 }
 
 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
 int afs_NFSRootOnly = 1;
+/*!
+ * VIOC_EXPORTAFS (39) - Export afs to nfs clients
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      a struct Vic * EIOctl containing export values needed to change between nfs and afs
+ * \param[out] aout    a struct of the exporter states (exporter->exp_states)
+ *
+ * \retval ENODEV      Error if the exporter doesn't exist
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ *
+ * \post Changes the state of various values to reflect the change of the export values between nfs and afs.
+ *
+ * \notes Legacy code obtained from IBM.
+ */
 DECL_PIOCTL(PExportAfs)
 {
     afs_int32 export, newint =
@@ -3148,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;
@@ -3176,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 */
@@ -3222,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;
@@ -3250,6 +3973,18 @@ DECL_PIOCTL(PExportAfs)
     return 0;
 }
 
+/*!
+ * VIOC_GAG (44) - Silence Cache Manager
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the flags to either gag or de-gag the cache manager
+ * \param[out] aout    not in use
+ *
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ *
+ * \post set the gag flags, then show these flags
+ */
 DECL_PIOCTL(PGag)
 {
     struct gaginfo *gagflags;
@@ -3257,13 +3992,26 @@ 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;
 }
 
-
+/*!
+ * VIOC_TWIDDLE (45) - Adjust RX knobs
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the previous settings of the 'knobs'
+ * \param[out] aout    not in use
+ *
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ *
+ * \post build out the struct rxp, from a struct rx
+ */
 DECL_PIOCTL(PTwiddleRx)
 {
     struct rxparams *rxp;
@@ -3271,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;
@@ -3297,13 +4047,25 @@ DECL_PIOCTL(PTwiddleRx)
     return 0;
 }
 
+/*!
+ * VIOC_GETINITPARAMS (49) - Get initial cache manager parameters
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    initial cache manager params
+ *
+ * \retval E2BIG       Error if the initial parameters are bigger than some PIGGYSIZE
+ *
+ * \post return the initial cache manager parameters
+ */
 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;
 }
 
@@ -3314,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
@@ -3322,22 +4084,44 @@ crget(void)
 }
 #endif
 
+/*!
+ * VIOC_GETRXKCRYPT (55) - Get rxkad encryption flag
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      not in use
+ * \param[out] aout    value of cryptall
+ *
+ * \post get the value of cryptall (presumably whether or not things should be encrypted)
+ */
 DECL_PIOCTL(PGetRxkcrypt)
 {
-    memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
-    *aoutSize = sizeof(afs_int32);
-    return 0;
+    return afs_pd_putInt(aout, cryptall);
 }
 
+/*!
+ * VIOC_SETRXKCRYPT (56) - Set rxkad encryption flag
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the argument whether or not things should be encrypted
+ * \param[out] aout    not in use
+ *
+ * \retval EPERM       Error if the user doesn't have super-user credentials
+ * \retval EINVAL      Error if the input is too big, or if the input is outside the bounds of what it can be set to
+ *
+ * \post set whether or not things should be encrypted
+ *
+ * \notes may need to be modified at a later date to take into account other values for cryptall (beyond true or false)
+ */
 DECL_PIOCTL(PSetRxkcrypt)
 {
     afs_int32 tmpval;
 
     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;
@@ -3356,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());
@@ -3431,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 */
@@ -3470,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' */
@@ -3507,8 +4295,20 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
 }
 #endif /* AFS_NEED_CLIENTCONTEXT */
 
-/* get all interface addresses of this client */
 
+/*! 
+ * VIOC_GETCPREFS (50) - Get client interface
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      sprefrequest input
+ * \param[out] aout    spref information
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval EINVAL      Error if some of the standard args aren't set
+ *
+ * \post get all interface addresses and other information of the client interface
+ */
 DECL_PIOCTL(PGetCPrefs)
 {
     struct sprefrequest *spin; /* input */
@@ -3521,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;
@@ -3540,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 */
@@ -3551,8 +4353,24 @@ DECL_PIOCTL(PGetCPrefs)
     return 0;
 }
 
+/*!
+ * VIOC_SETCPREFS (51) - Set client interface
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the interfaces you want set
+ * \param[out] aout    not in use
+ *
+ * \retval EIO         Error if the afs daemon hasn't started yet
+ * \retval EINVAL      Error if the input is too large for the struct
+ * \retval ENOMEM      Error if there are too many servers
+ *
+ * \post set the callbak interfaces addresses to those of the hosts
+ */
 DECL_PIOCTL(PSetCPrefs)
 {
+    char *ainPtr;
+    size_t ainSize;
     struct setspref *sin;
     int i;
 
@@ -3560,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;
@@ -3580,6 +4404,20 @@ DECL_PIOCTL(PSetCPrefs)
     return 0;
 }
 
+/*!
+ * VIOC_AFS_FLUSHMOUNT (52) - Flush mount symlink data
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the last part of a path to a mount point, which tells us what to flush
+ * \param[out] aout    not in use
+ *
+ * \retval EINVAL      Error if some of the initial arguments aren't set
+ * \retval ENOTDIR     Error if the initial argument for the mount point isn't a directory
+ * \retval ENOENT      Error if the dcache entry isn't set
+ *
+ * \post remove all of the mount data from the dcache regarding a certain mount point
+ */
 DECL_PIOCTL(PFlushMount)
 {
     register afs_int32 code;
@@ -3587,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;
@@ -3602,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);
@@ -3613,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);
@@ -3635,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;
     }
@@ -3655,24 +4498,32 @@ DECL_PIOCTL(PFlushMount)
     return code;
 }
 
+/*!
+ * VIOC_RXSTAT_PROC (53) - Control process RX statistics
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the flags that control which stats to use
+ * \param[out] aout    not in use
+ *
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ * \retval EINVAL      Error if the flag input is too long
+ *
+ * \post either enable process RPCStats, disable process RPCStats, or clear the process RPCStats
+ */
 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();
     }
@@ -3682,30 +4533,36 @@ DECL_PIOCTL(PRxStatProc)
     if (flags & AFSCALL_RXSTATS_CLEAR) {
        rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
     }
-  out:
-    *aoutSize = 0;
-    return code;
+    return 0;
 }
 
 
+/*!
+ * VIOC_RXSTAT_PEER (54) - Control peer RX statistics
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      the flags that control which statistics to use
+ * \param[out] aout    not in use
+ *
+ * \retval EACCES      Error if the user doesn't have super-user credentials
+ * \retval EINVAL      Error if the flag input is too long
+ *
+ * \post either enable peer RPCStatws, disable peer RPCStats, or clear the peer RPCStats
+ */
 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();
     }
@@ -3715,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;
@@ -3737,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;
@@ -3749,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);
            }
@@ -3774,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;
@@ -3820,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);
@@ -3848,9 +4707,6 @@ DECL_PIOCTL(PResidencyCmd)
 
     afs_PutVCache(tvc);
 
-    if (!code) {
-       *aoutSize = sizeof(struct ResidencyCmdOutputs);
-    }
     return code;
 }
 
@@ -3860,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);
@@ -3870,6 +4726,44 @@ DECL_PIOCTL(PNewUuid)
     return 0;
 }
 
+#if defined(AFS_CACHE_BYPASS)
+
+DECL_PIOCTL(PSetCachingThreshold)
+{
+    afs_int32 getting = 1;
+    afs_int32 setting = 1;
+    afs_int32 threshold;
+
+    if (afs_pd_getInt(ain, &threshold) != 0)
+       setting = 0;
+
+    if (aout == NULL)
+       getting = 0;
+
+    if (setting == 0 && getting == 0)
+       return EINVAL;
+       
+    /* 
+     * If setting, set first, and return the value now in effect
+     */
+    if (setting) {
+       if (!afs_osi_suser(*acred))
+           return EPERM;
+       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 afs_pd_putInt32(aout, cache_bypass_threshold);
+
+    return(0);
+}
+
+#endif /* defined(AFS_CACHE_BYPASS) */
+
 DECL_PIOCTL(PCallBackAddr)
 {
 #ifndef UKERNEL
@@ -3877,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;
@@ -3889,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)
@@ -3971,21 +4863,72 @@ DECL_PIOCTL(PCallBackAddr)
 DECL_PIOCTL(PDiscon)
 {
 #ifdef AFS_DISCON_ENV
-    static afs_int32 mode;
+    static afs_int32 mode = 1; /* Start up in 'off' */
+    afs_int32 force = 0;
+    int code = 0;
+    char flags[3];
+
+    if (afs_pd_getBytes(ain, &flags, 3) == 0) {
+       if (!afs_osi_suser(*acred))
+           return EPERM;
+
+       if (flags[0])
+           mode = flags[0] - 1;
+       if (flags[1])
+           afs_ConflictPolicy = flags[1] - 1;
+       if (flags[2])
+           force = 1;
 
-    if (ainSize == sizeof(afs_int32)) {
-       memcpy(&mode, ain, sizeof(afs_int32));
+       /*
+        * All of these numbers are hard coded in fs.c. If they
+        * change here, they should change there and vice versa
+        */
+       switch (mode) {
+       case 0: /* Disconnect ("offline" mode), breaking all callbacks */
+           if (!AFS_IS_DISCONNECTED) {
+               ObtainWriteLock(&afs_discon_lock, 999);
+               afs_DisconGiveUpCallbacks();
+               afs_RemoveAllConns();
+               afs_is_disconnected = 1;
+               afs_is_discon_rw = 1;
+               ReleaseWriteLock(&afs_discon_lock);
+           }
+           break;
+       case 1: /* Fully connected, ("online" mode). */
+           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. \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");
+           }
 
-       /* 3 is magic, should be a #define. */
-       afs_SetCheckServerNATmode(mode == 3);
-    } else if (ainSize != 0) {
+           ReleaseWriteLock(&afs_discon_lock);
+           break;
+       default:
+           return EINVAL;
+       }
+    } else {
        return EINVAL;
     }
 
-    /* Return new mode */
-    memcpy(aout, &mode, sizeof(afs_int32));
-    *aoutSize = sizeof(struct VenusFid);
-    return 0;
+    if (code)
+       return code;
+
+    return afs_pd_putInt(aout, mode);
 #else
     return EINVAL;
 #endif
@@ -3993,7 +4936,7 @@ DECL_PIOCTL(PDiscon)
 
 DECL_PIOCTL(PNFSNukeCreds)
 {
-    afs_uint32 addr, code;
+    afs_uint32 addr;
     register afs_int32 i;
     register struct unixuser *tu;
 
@@ -4001,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);
@@ -4023,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);