vol, volser, and viced type fixes
[openafs.git] / src / volser / volprocs.c
index 438f2f8..b55af40 100644 (file)
@@ -5,17 +5,20 @@
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * Portions Copyright (c) 2007-2008 Sine Nomine Associates
  */
 
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID("$Header$");
 
 #include <stdio.h>
 #include <sys/types.h>
+#include <string.h>
 #include <errno.h>
 #ifdef AFS_NT40_ENV
+#include <stdlib.h>
 #include <fcntl.h>
 #include <winsock2.h>
 #else
@@ -24,14 +27,6 @@ RCSID("$Header$");
 #include <unistd.h>
 #endif
 
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
 #include <dirent.h>
 #include <sys/stat.h>
 #include <rx/xdr.h>
@@ -39,12 +34,15 @@ RCSID("$Header$");
 #include <rx/rxkad.h>
 #include <afs/afsint.h>
 #include <signal.h>
+#ifdef AFS_PTHREAD_ENV
+#include <assert.h>
+#else /* AFS_PTHREAD_ENV */
 #include <afs/assert.h>
+#endif /* AFS_PTHREAD_ENV */
 #include <afs/prs_fs.h>
 #include <afs/nfs.h>
 #include <lwp.h>
 #include <lock.h>
-#include <afs/auth.h>
 #include <afs/cellconfig.h>
 #include <afs/keys.h>
 #include <ubik.h>
@@ -54,18 +52,30 @@ RCSID("$Header$");
 #endif
 #include <afs/vnode.h>
 #include <afs/volume.h>
+#include <afs/volume_inline.h>
 #include <afs/partition.h>
 #include "vol.h"
+#include <afs/daemon_com.h>
 #include <afs/fssync.h>
 #include <afs/acl.h>
 #include "afs/audit.h"
+#include <afs/dir.h>
+#include <afs/afsutil.h>
+#include <afs/vol_prototypes.h>
+#include <afs/errors.h>
 
 #include "volser.h"
+#include "voltrans_inline.h"
 #include "volint.h"
+
+#include "volser_internal.h"
+#include "physio.h"
+#include "dumpstuff.h"
+
 extern int DoLogging;
-extern struct volser_trans *FindTrans(), *NewTrans(),*TransList();
 extern struct afsconf_dir *tdir;
-extern char *volutil_PartitionName();
+
+extern void LogError(afs_int32 errcode);
 
 /* Forward declarations */
 static int GetPartName(afs_int32 partid, char *pname);
@@ -76,81 +86,136 @@ static int GetPartName(afs_int32 partid, char *pname);
 #define ENOTCONN 134
 #endif
 
-afs_int32 localTid=1;
-afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(), VolDeleteVolume(), VolClone();
-afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(), VolForward(), VolDump();
-afs_int32 VolForwardMultiple();
-afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(), VolSetInfo(), VolGetName();
-afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(), VolXListOneVolume(), VolXListVolumes();
-afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(), VolSetIdsTypes(), VolSetDate(), VolSetFlags();
+afs_int32 localTid = 1;
+static afs_int32 VolPartitionInfo(struct rx_call *, char *pname,
+                                 struct diskPartition64 *);
+static afs_int32 VolNukeVolume(struct rx_call *, afs_int32, afs_uint32);
+static afs_int32 VolCreateVolume(struct rx_call *, afs_int32, char *,
+                                afs_int32, afs_uint32, afs_uint32 *,
+                                afs_int32 *);
+static afs_int32 VolDeleteVolume(struct rx_call *, afs_int32);
+static afs_int32 VolClone(struct rx_call *, afs_int32, afs_uint32,
+                         afs_int32, char *, afs_uint32 *);
+static afs_int32 VolReClone(struct rx_call *, afs_int32, afs_int32);
+static afs_int32 VolTransCreate(struct rx_call *, afs_uint32, afs_int32,
+                               afs_int32, afs_int32 *);
+static afs_int32 VolGetNthVolume(struct rx_call *, afs_int32, afs_uint32 *,
+                                afs_int32 *);
+static afs_int32 VolGetFlags(struct rx_call *, afs_int32, afs_int32 *);
+static afs_int32 VolSetFlags(struct rx_call *, afs_int32, afs_int32 );
+static afs_int32 VolForward(struct rx_call *, afs_int32, afs_int32,
+                           struct destServer *destination, afs_int32,
+                           struct restoreCookie *cookie);
+static afs_int32 VolDump(struct rx_call *, afs_int32, afs_int32, afs_int32);
+static afs_int32 VolRestore(struct rx_call *, afs_int32, afs_int32,
+                           struct restoreCookie *);
+static afs_int32 VolEndTrans(struct rx_call *, afs_int32, afs_int32 *);
+static afs_int32 VolSetForwarding(struct rx_call *, afs_int32, afs_int32);
+static afs_int32 VolGetStatus(struct rx_call *, afs_int32,
+                             struct volser_status *);
+static afs_int32 VolSetInfo(struct rx_call *, afs_int32, struct volintInfo *);
+static afs_int32 VolGetName(struct rx_call *, afs_int32, char **);
+static afs_int32 VolListPartitions(struct rx_call *, struct pIDs *);
+static afs_int32 XVolListPartitions(struct rx_call *, struct partEntries *);
+static afs_int32 VolListOneVolume(struct rx_call *, afs_int32, afs_uint32,
+                                 volEntries *);
+static afs_int32 VolXListOneVolume(struct rx_call *, afs_int32, afs_uint32,
+                                  volXEntries *);
+static afs_int32 VolListVolumes(struct rx_call *, afs_int32, afs_int32,
+                               volEntries *);
+static afs_int32 VolXListVolumes(struct rx_call *, afs_int32, afs_int32,
+                               volXEntries *);
+static afs_int32 VolMonitor(struct rx_call *, transDebugEntries *);
+static afs_int32 VolSetIdsTypes(struct rx_call *, afs_int32, char [],
+                               afs_int32, afs_uint32, afs_uint32,
+                               afs_uint32);
+static afs_int32 VolSetDate(struct rx_call *, afs_int32, afs_int32);
 
 /* this call unlocks all of the partition locks we've set */
-VPFullUnlock() {
-    register struct DiskPartition *tp;
-    for(tp = DiskPartitionList; tp; tp = tp->next) {
-       if (tp->lock_fd != -1) {
+int 
+VPFullUnlock_r(void)
+{
+    register struct DiskPartition64 *tp;
+    for (tp = DiskPartitionList; tp; tp = tp->next) {
+       if (tp->lock_fd != INVALID_FD) {
            close(tp->lock_fd); /* releases flock held on this partition */
-           tp->lock_fd = -1;
+           tp->lock_fd = INVALID_FD;
        }
     }
     return 0;
 }
 
+int
+VPFullUnlock(void)
+{
+    int code;
+    VOL_LOCK;
+    code = VPFullUnlock_r();
+    VOL_UNLOCK;
+    return code;
+}
+
 /* get partition id from a name */
-afs_int32 PartitionID(aname)
-char *aname; {
+afs_int32
+PartitionID(char *aname)
+{
     register char tc;
     register int code = 0;
     char ascii[3];
 
     tc = *aname;
-    if (tc == 0) return -1;    /* unknown */
+    if (tc == 0)
+       return -1;              /* unknown */
 
     /* otherwise check for vicepa or /vicepa, or just plain "a" */
     ascii[2] = 0;
     if (!strncmp(aname, "/vicep", 6)) {
-       strncpy(ascii, aname+6, 2);
-    }
-    else return        -1;     /* bad partition name */
+       strncpy(ascii, aname + 6, 2);
+    } else
+       return -1;              /* bad partition name */
     /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
-         from 0.  Do the appropriate conversion */
+     * from 0.  Do the appropriate conversion */
     if (ascii[1] == 0) {
        /* one char name, 0..25 */
-       if (ascii[0] <  'a' || ascii[0] > 'z')  return -1;  /* wrongo */
+       if (ascii[0] < 'a' || ascii[0] > 'z')
+           return -1;          /* wrongo */
        return ascii[0] - 'a';
-    }
-    else {
+    } else {
        /* two char name, 26 .. <whatever> */
-       if (ascii[0] <  'a' || ascii[0] > 'z')  return -1;  /* wrongo */
-       if (ascii[1] <  'a' || ascii[1] > 'z')  return -1;  /* just as bad */
+       if (ascii[0] < 'a' || ascii[0] > 'z')
+           return -1;          /* wrongo */
+       if (ascii[1] < 'a' || ascii[1] > 'z')
+           return -1;          /* just as bad */
        code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
-       if (code > VOLMAXPARTS) return -1;
+       if (code > VOLMAXPARTS)
+           return -1;
        return code;
     }
 }
 
-static int ConvertVolume(avol, aname, asize)
-afs_int32 avol;
-char *aname;
-afs_int32 asize; {
-    if (asize < 18) return -1;
+static int
+ConvertVolume(afs_uint32 avol, char *aname, afs_int32 asize)
+{
+    if (asize < 18)
+       return -1;
     /* It's better using the Generic VFORMAT since otherwise we have to make changes to too many places... The 14 char limitation in names hits us again in AIX; print in field of 9 digits (still 10 for the rest), right justified with 0 padding */
-    sprintf(aname, VFORMAT, avol);
+    (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
     return 0;
 }
 
-static int ConvertPartition(apartno, aname, asize)
-int apartno;
-char *aname;
-int asize; {
-    if (asize < 10) return E2BIG;
-    if (apartno < 0) return EINVAL;
+static int
+ConvertPartition(int apartno, char *aname, int asize)
+{
+    if (asize < 10)
+       return E2BIG;
+    if (apartno < 0)
+       return EINVAL;
     strcpy(aname, "/vicep");
     if (apartno < 26) {
-       aname[6] = 'a'+apartno;
+       aname[6] = 'a' + apartno;
        aname[7] = 0;
-    }
-    else {
+    } else {
        apartno -= 26;
        aname[6] = 'a' + (apartno / 26);
        aname[7] = 'a' + (apartno % 26);
@@ -159,14 +224,70 @@ int asize; {
     return 0;
 }
 
+static struct Volume *
+VAttachVolumeByName_retry(Error *ec, char *partition, char *name, int mode)
+{
+    struct Volume *vp;
+
+    *ec = 0;
+    vp = VAttachVolumeByName(ec, partition, name, mode);
+
+#ifdef AFS_DEMAND_ATTACH_FS
+    {
+        int i;
+        /*
+         * The fileserver will take care of keeping track of how many
+         * demand-salvages have been performed, and will force the volume to
+         * ERROR if we've done too many. The limit on This loop is just a
+         * failsafe to prevent trying to salvage forever. We want to attempt
+         * attachment at least SALVAGE_COUNT_MAX times, since we want to
+         * avoid prematurely exiting this loop, if we can.
+         */
+        for (i = 0; i < SALVAGE_COUNT_MAX*2 && *ec == VSALVAGING; i++) {
+            sleep(SALVAGE_PRIO_UPDATE_INTERVAL);
+            vp = VAttachVolumeByName(ec, partition, name, mode);
+        }
+
+        if (*ec == VSALVAGING) {
+            *ec = VSALVAGE;
+        }
+    }
+#endif /* AFS_DEMAND_ATTACH_FS */
+
+    return vp;
+}
+
+static struct Volume *
+VAttachVolume_retry(Error *ec, afs_uint32 avolid, int amode)
+{
+    struct Volume *vp;
+
+    *ec = 0;
+    vp = VAttachVolume(ec, avolid, amode);
+
+#ifdef AFS_DEMAND_ATTACH_FS
+    {
+        int i;
+        /* see comment above in VAttachVolumeByName_retry */
+        for (i = 0; i < SALVAGE_COUNT_MAX*2 && *ec == VSALVAGING; i++) {
+            sleep(SALVAGE_PRIO_UPDATE_INTERVAL);
+            vp = VAttachVolume(ec, avolid, amode);
+        }
+
+        if (*ec == VSALVAGING) {
+            *ec = VSALVAGE;
+        }
+    }
+#endif /* AFS_DEMAND_ATTACH_FS */
+
+    return vp;
+}
+
 /* the only attach function that takes a partition is "...ByName", so we use it */
-struct Volume *XAttachVolume(error, avolid, apartid, amode)
-afs_int32 *error;
-afs_int32 avolid;
-afs_int32 apartid;
-int amode; {
+static struct Volume *
+XAttachVolume(afs_int32 *error, afs_uint32 avolid, afs_int32 apartid, int amode)
+{
     char pbuf[30], vbuf[20];
-    register struct Volume *tv;
 
     if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
        *error = EINVAL;
@@ -176,66 +297,72 @@ int amode; {
        *error = EINVAL;
        return NULL;
     }
-    tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
-    return tv;
+
+    return VAttachVolumeByName_retry((Error *)error, pbuf, vbuf, amode);
 }
 
 /* Adapted from the file server; create a root directory for this volume */
-static ViceCreateRoot(vp)
-Volume * vp;
+static int
+ViceCreateRoot(Volume *vp)
 {
     DirHandle dir;
-    struct acl_accessList * ACL;
-    ViceFid    did;
+    struct acl_accessList *ACL;
+    AFSFid did;
     Inode inodeNumber, nearInode;
-    char buf[SIZEOF_LARGEDISKVNODE];
-    struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf;
+    struct VnodeDiskObject *vnode;
     struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
     IHandle_t *h;
     FdHandle_t *fdP;
-    int code;
-    int length;
+    afs_fsize_t length;
+    ssize_t nBytes;
+    afs_foff_t off;
 
-    memset(vnode, 0, SIZEOF_LARGEDISKVNODE);    
+    vnode = (struct VnodeDiskObject *)malloc(SIZEOF_LARGEDISKVNODE);
+    if (!vnode)
+       return ENOMEM;
+    memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
 
     V_pref(vp, nearInode);
-    inodeNumber = IH_CREATE(V_linkHandle(vp), V_device(vp),
-                           VPartitionPath(V_partition(vp)), nearInode, 
-                           V_parentId(vp), 1, 1, 0);
+    inodeNumber =
+       IH_CREATE(V_linkHandle(vp), V_device(vp),
+                 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
+                 1, 1, 0);
     assert(VALID_INO(inodeNumber));
 
-    SetSalvageDirHandle(&dir, V_id(vp), vp->device, inodeNumber);
+    SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
     did.Volume = V_id(vp);
-    did.Vnode = (VnodeId)1;
+    did.Vnode = (VnodeId) 1;
     did.Unique = 1;
 
-    assert(!(MakeDir(&dir, &did, &did)));
-    DFlush();                                    /* flush all modified dir buffers out */
-    DZap(&dir);                                  /* Remove all buffers for this dir */
-    length = Length(&dir);                       /* Remember size of this directory */
+    assert(!(MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
+    DFlush();                  /* flush all modified dir buffers out */
+    DZap((afs_int32 *)&dir);                   /* Remove all buffers for this dir */
+    length = Length(&dir);     /* Remember size of this directory */
 
-    FidZap(&dir);    /* Done with the dir handle obtained via SetSalvageDirHandle() */
+    FidZap(&dir);              /* Done with the dir handle obtained via SetSalvageDirHandle() */
 
- /* build a single entry ACL that gives all rights to system:administrators */
- /* this section of code assumes that access list format is not going to
-  * change
-  */
+    /* build a single entry ACL that gives all rights to system:administrators */
+    /* this section of code assumes that access list format is not going to
+     * change
+     */
     ACL = VVnodeDiskACL(vnode);
     ACL->size = sizeof(struct acl_accessList);
     ACL->version = ACL_ACLVERSION;
     ACL->total = 1;
     ACL->positive = 1;
     ACL->negative = 0;
-    ACL->entries[0].id = -204;  /* this assumes System:administrators is group -204 */
-    ACL->entries[0].rights = PRSFS_READ | PRSFS_WRITE  | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER;
+    ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
+    ACL->entries[0].rights =
+       PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
+       | PRSFS_LOCK | PRSFS_ADMINISTER;
 
     vnode->type = vDirectory;
     vnode->cloned = 0;
     vnode->modeBits = 0777;
     vnode->linkCount = 2;
-    vnode->length = length;
+    VNDISK_SET_LEN(vnode, length);
     vnode->uniquifier = 1;
-    V_uniquifier(vp) = vnode->uniquifier+1;
+    V_uniquifier(vp) = vnode->uniquifier + 1;
     vnode->dataVersion = 1;
     VNDISK_SET_INO(vnode, inodeNumber);
     vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp);
@@ -248,90 +375,110 @@ Volume   * vp;
            vp->vnodeIndex[vLarge].handle->ih_ino);
     fdP = IH_OPEN(h);
     assert(fdP != NULL);
-    code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
-    assert(code >= 0);
-    code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
-    assert(code == SIZEOF_LARGEDISKVNODE);
+    off = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
+    assert(off >= 0);
+    nBytes = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
+    assert(nBytes == SIZEOF_LARGEDISKVNODE);
     FDH_REALLYCLOSE(fdP);
     IH_RELEASE(h);
-    V_diskused(vp) = nBlocks(vnode->length);
+    VNDISK_GET_LEN(length, vnode);
+    V_diskused(vp) = nBlocks(length);
 
+    free(vnode);
     return 1;
 }
 
-afs_int32 SAFSVolPartitionInfo (acid,pname,partition)
-struct rx_call *acid;
-char *pname;
-struct diskPartition *partition;
+afs_int32
+SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition 
+                    *partition)
+{
+    afs_int32 code;
+    struct diskPartition64 *dp = (struct diskPartition64 *)
+       malloc(sizeof(struct diskPartition64));
+
+    code = VolPartitionInfo(acid, pname, dp);
+    if (!code) {
+       strncpy(partition->name, dp->name, 32);
+       strncpy(partition->devName, dp->devName, 32);
+       partition->lock_fd = dp->lock_fd;
+       partition->free=RoundInt64ToInt32(dp->free);
+       partition->minFree=RoundInt64ToInt32(dp->minFree);
+    }
+    free(dp);
+    osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
+    return code;
+}
+
+afs_int32
+SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64 
+                    *partition)
 {
-  afs_int32 code;
-  
-  code = VolPartitionInfo (acid,pname,partition);
-  osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
-  return code;
+    afs_int32 code;
+
+    code = VolPartitionInfo(acid, pname, partition);
+    osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
+    return code;
 }
 
-afs_int32 VolPartitionInfo (acid,pname,partition)
-struct rx_call *acid;
-char *pname;
-struct diskPartition *partition;
+afs_int32
+VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64 
+                *partition)
 {
-    register struct DiskPartition *dp;
+    register struct DiskPartition64 *dp;
 
 /*
     if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
 */
-    VResetDiskUsage(); 
+    VResetDiskUsage();
     dp = VGetPartition(pname, 0);
-    if(dp) {
-       strncpy(partition->name,dp->name,32);
-       strncpy(partition->devName,dp->devName,32);
-       partition->lock_fd = dp->lock_fd ;
+    if (dp) {
+       strncpy(partition->name, dp->name, 32);
+       strncpy(partition->devName, dp->devName, 32);
+       partition->lock_fd = (int)dp->lock_fd;
        partition->free = dp->free;
        partition->minFree = dp->totalUsable;
        return 0;
-    }
-    else 
+    } else
        return VOLSERILLEGAL_PARTITION;
 }
 
 /* obliterate a volume completely, and slowly. */
-afs_int32 SAFSVolNukeVolume (acid, apartID, avolID)
-struct rx_call *acid;
-afs_int32 apartID, avolID; 
+afs_int32
+SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
 {
-  afs_int32 code;
-  
-  code = VolNukeVolume (acid, apartID, avolID);
-  osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
-  return code;
+    afs_int32 code;
+
+    code = VolNukeVolume(acid, apartID, avolID);
+    osi_auditU(acid, VS_NukVolEvent, code, AUD_LONG, avolID, AUD_END);
+    return code;
 }
 
-afs_int32 VolNukeVolume (acid, apartID, avolID)
-struct rx_call *acid;
-afs_int32 apartID, avolID; 
+static afs_int32
+VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
 {
-    register char *tp;
     char partName[50];
     afs_int32 error;
+    Error verror;
     register afs_int32 code;
     struct Volume *tvp;
     char caller[MAXKTCNAMELEN];
 
     /* check for access */
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
-    if (DoLogging) Log("%s is executing VolNukeVolume %u\n", caller, avolID);
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;
+    if (DoLogging)
+       Log("%s is executing VolNukeVolume %u\n", caller, avolID);
 
-    tp = volutil_PartitionName(apartID);
-    if (!tp) return VOLSERNOVOL;
-    strcpy(partName, tp);      /* remember it for later */
+    if (volutil_PartitionName2_r(apartID, partName, sizeof(partName)) != 0)
+       return VOLSERNOVOL;
     /* we first try to attach the volume in update mode, so that the file
      * server doesn't try to use it (and abort) while (or after) we delete it.
      * If we don't get the volume, that's fine, too.  We just won't put it back.
      */
     tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
     code = nuke(partName, avolID);
-    if (tvp) VDetachVolume(&error, tvp);
+    if (tvp)
+       VDetachVolume(&verror, tvp);
     return code;
 }
 
@@ -341,74 +488,71 @@ afs_int32 apartID, avolID;
  * for the volume id (useful for things like volume restore).
  * Return the new volume id in *avolid.
  */
-afs_int32 SAFSVolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
-struct rx_call *acid;
-afs_int32 apart;
-afs_int32 atype;
-char *aname;
-afs_int32 aparent;
-afs_int32 *atrans;
-afs_int32 *avolid; 
-{
-  afs_int32 code;
-
-  code = VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans);
-  osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, 
-                                        AUD_LONG, *avolid, 
-                                       AUD_STR,  aname,
-                                       AUD_LONG, atype,
-                                       AUD_LONG, aparent,
-                                       AUD_END);
-  return code;
-}
-
-afs_int32 VolCreateVolume (acid, apart, aname, atype, aparent, avolid, atrans)
-struct rx_call *acid;
-afs_int32 apart;
-afs_int32 atype;
-char *aname;
-afs_int32 aparent;
-afs_int32 *atrans;
-afs_int32 *avolid; 
+afs_int32
+SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname, 
+                   afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid, 
+                   afs_int32 *atrans)
 {
-    afs_int32 error;
+    afs_int32 code;
+
+    code =
+       VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
+    osi_auditU(acid, VS_CrVolEvent, code, AUD_LONG, *atrans, AUD_LONG,
+              *avolid, AUD_STR, aname, AUD_LONG, atype, AUD_LONG, aparent,
+              AUD_END);
+    return code;
+}
+
+static afs_int32
+VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname, 
+                   afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid, 
+                   afs_int32 *atrans)
+{
+    Error error;
     register Volume *vp;
-    afs_int32 junk;    /* discardable error code */
-    register afs_int32 volumeID, doCreateRoot=1;
+    Error junk;                /* discardable error code */
+    afs_uint32 volumeID;
+    afs_int32 doCreateRoot = 1;
     register struct volser_trans *tt;
     char ppath[30];
     char caller[MAXKTCNAMELEN];
 
-    if (strlen(aname) > 31) return VOLSERBADNAME;
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
-    if (DoLogging) Log("%s is executing CreateVolume '%s'\n", caller, aname);
-    if (error = ConvertPartition(apart, ppath, sizeof(ppath))) return error;/*a standard unix error*/
-    if (atype != readwriteVolume && atype != readonlyVolume && atype != backupVolume)
+    if (strlen(aname) > 31)
+       return VOLSERBADNAME;
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;
+    if (DoLogging)
+       Log("%s is executing CreateVolume '%s'\n", caller, aname);
+    if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
+       return error;           /*a standard unix error */
+    if (atype != readwriteVolume && atype != readonlyVolume
+       && atype != backupVolume)
        return EINVAL;
     if ((volumeID = *avolid) == 0) {
-       
-           Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n",aname);
-           return E2BIG;
-       
+
+       Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
+       return E2BIG;
+
     }
     if ((aparent == volumeID) && (atype == readwriteVolume)) {
        doCreateRoot = 0;
     }
-    if (aparent == 0) aparent = volumeID;
+    if (aparent == 0)
+       aparent = volumeID;
     tt = NewTrans(volumeID, apart);
     if (!tt) {
        Log("1 createvolume: failed to create trans\n");
-       return VOLSERVOLBUSY;           /* volume already busy! */
+       return VOLSERVOLBUSY;   /* volume already busy! */
     }
     vp = VCreateVolume(&error, ppath, volumeID, aparent);
     if (error) {
-       Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n",error);
+       Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
        LogError(error);
-       DeleteTrans(tt);
+       DeleteTrans(tt, 1);
        return EIO;
     }
     V_uniquifier(vp) = 1;
-    V_creationDate(vp) = V_copyDate(vp);
+    V_updateDate(vp) = V_creationDate(vp) = V_copyDate(vp);
     V_inService(vp) = V_blessed(vp) = 1;
     V_type(vp) = atype;
     AssignVolumeName(&V_disk(vp), aname, 0);
@@ -416,119 +560,119 @@ afs_int32 *avolid;
        ViceCreateRoot(vp);
     V_destroyMe(vp) = DESTROY_ME;
     V_inService(vp) = 0;
-    V_maxquota(vp) = 5000;             /* set a quota of 5000 at init time */
+    V_maxquota(vp) = 5000;     /* set a quota of 5000 at init time */
     VUpdateVolume(&error, vp);
     if (error) {
        Log("1 Volser: create UpdateVolume failed, code %d\n", error);
        LogError(error);
-       DeleteTrans(tt);
+       DeleteTrans(tt, 1);
        VDetachVolume(&junk, vp);       /* rather return the real error code */
        return error;
     }
+    VTRANS_OBJ_LOCK(tt);
     tt->volume = vp;
     *atrans = tt->tid;
-    strcpy(tt->lastProcName,"CreateVolume");
-    tt->rxCallPtr = acid;
+    TSetRxCall_r(tt, acid, "CreateVolume");
+    VTRANS_OBJ_UNLOCK(tt);
     Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
+    TClearRxCall(tt);
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
     return 0;
 }
 
 /* delete the volume associated with this transaction */
-afs_int32 SAFSVolDeleteVolume (acid, atrans)
-afs_int32 atrans; 
-struct rx_call *acid; 
+afs_int32
+SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolDeleteVolume (acid, atrans);
-  osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
-  return code;
+    code = VolDeleteVolume(acid, atrans);
+    osi_auditU(acid, VS_DelVolEvent, code, AUD_LONG, atrans, AUD_END);
+    return code;
 }
 
-afs_int32 VolDeleteVolume (acid, atrans)
-afs_int32 atrans; 
-struct rx_call *acid; 
+static afs_int32
+VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
 {
     register struct volser_trans *tt;
-    afs_int32 error;
+    Error error;
     char caller[MAXKTCNAMELEN];
 
-     if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;
     tt = FindTrans(atrans);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: Delete: volume %u already deleted \n",tt->volid);
+       Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    if (DoLogging) Log("%s is executing Delete Volume %u\n", caller, tt->volid);
-    strcpy(tt->lastProcName,"DeleteVolume");
-    tt->rxCallPtr = acid;
+    if (DoLogging)
+       Log("%s is executing Delete Volume %u\n", caller, tt->volid);
+    TSetRxCall(tt, acid, "DeleteVolume");
     VPurgeVolume(&error, tt->volume);  /* don't check error code, it is not set! */
-    tt->vflags |= VTDeleted;           /* so we know not to do anything else to it */
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
-  
-    Log("1 Volser: Delete: volume %u deleted \n",tt->volid);
-    return 0;      /* vpurgevolume doesn't set an error code */
+    V_destroyMe(tt->volume) = DESTROY_ME; /* so endtrans does the right fssync opcode */
+    VTRANS_OBJ_LOCK(tt);
+    tt->vflags |= VTDeleted;   /* so we know not to do anything else to it */
+    TClearRxCall_r(tt);
+    VTRANS_OBJ_UNLOCK(tt);
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
+
+    Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
+    return 0;                  /* vpurgevolume doesn't set an error code */
 }
 
 /* make a clone of the volume associated with atrans, possibly giving it a new
  * number (allocate a new number if *newNumber==0, otherwise use *newNumber
- * for the clone's id).  The new clone is given the name newName.  Finally, due to
- * efficiency considerations, if purgeId is non-zero, we purge that volume when doing
- * the clone operation.  This may be useful when making new backup volumes, for instance
- * since the net result of a clone and a purge generally leaves many inode ref counts
- * the same, while doing them separately would result in far more iincs and idecs being
- * peformed (and they are slow operations).
+ * for the clone's id).  The new clone is given the name newName.  Finally,
+ * due to efficiency considerations, if purgeId is non-zero, we purge that
+ * volume when doing the clone operation.  This may be useful when making
+ * new backup volumes, for instance since the net result of a clone and a
+ * purge generally leaves many inode ref counts the same, while doing them
+ * separately would result in far more iincs and idecs being peformed
+ * (and they are slow operations).
  */
-afs_int32 SAFSVolClone (acid, atrans, purgeId, newType, newName, newNumber)
-struct rx_call *acid;
-afs_int32 atrans;
-afs_int32 newType;
-afs_int32 *newNumber;
-afs_int32 purgeId;   /* for efficiency reasons, sometimes faster to piggyback a purge here */
-char *newName; 
-{
-  afs_int32 code;
-
-  code = VolClone (acid, atrans, purgeId, newType, newName, newNumber);
-  osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, 
-                                       AUD_LONG, purgeId,
-                                       AUD_STR,  newName,
-                                       AUD_LONG, newType,
-                                       AUD_LONG, *newNumber, AUD_END);
-  return code;
-}
-
-afs_int32 VolClone (acid, atrans, purgeId, newType, newName, newNumber)
-struct rx_call *acid;
-afs_int32 atrans;
-afs_int32 newType;
-afs_int32 *newNumber;
-afs_int32 purgeId;   /* for efficiency reasons, sometimes faster to piggyback a purge here */
-char *newName; 
-{
-    VolumeId newId;
+/* for efficiency reasons, sometimes faster to piggyback a purge here */
+afs_int32
+SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId, 
+            afs_int32 newType, char *newName, afs_uint32 *newNumber)
+{
+    afs_int32 code;
+
+    code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
+    osi_auditU(acid, VS_CloneEvent, code, AUD_LONG, atrans, AUD_LONG, purgeId,
+              AUD_STR, newName, AUD_LONG, newType, AUD_LONG, *newNumber,
+              AUD_END);
+    return code;
+}
+
+static afs_int32
+VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId, 
+            afs_int32 newType, char *newName, afs_uint32 *newNumber)
+{
+    afs_uint32 newId;
     register struct Volume *originalvp, *purgevp, *newvp;
     Error error, code;
-    register struct volser_trans *tt,*ttc;
+    register struct volser_trans *tt, *ttc;
     char caller[MAXKTCNAMELEN];
-    
-    if (strlen(newName)>31) return VOLSERBADNAME;
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
-    if (DoLogging) Log("%s is executing Clone Volume new name=%s\n", caller, newName);
+
+    if (strlen(newName) > 31)
+       return VOLSERBADNAME;
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
+    if (DoLogging)
+       Log("%s is executing Clone Volume new name=%s\n", caller, newName);
     error = 0;
     originalvp = (Volume *) 0;
     purgevp = (Volume *) 0;
     newvp = (Volume *) 0;
-    tt = ttc = (struct volser_trans *) 0;
+    tt = ttc = (struct volser_trans *)0;
 
-    if (!newNumber || !*newNumber) 
-    {
-        Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
+    if (!newNumber || !*newNumber) {
+       Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
        goto fail;
     }
     newId = *newNumber;
@@ -536,63 +680,63 @@ char *newName;
     if (newType != readonlyVolume && newType != backupVolume)
        return EINVAL;
     tt = FindTrans(atrans);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: Clone: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    ttc = NewTrans(newId,tt->partition);
-    if (!ttc) 
-    {                              /* someone is messing with the clone already */
+    ttc = NewTrans(newId, tt->partition);
+    if (!ttc) {                        /* someone is messing with the clone already */
        TRELE(tt);
-       return VBUSY;
+       return VOLSERVOLBUSY;
     }
-    strcpy(tt->lastProcName,"Clone");
-    tt->rxCallPtr = acid;
-    
-    
+    TSetRxCall(tt, acid, "Clone");
+
+
     if (purgeId) {
-       purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
+       purgevp = VAttachVolume_retry(&error, purgeId, V_VOLUPD);
        if (error) {
            Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
            goto fail;
        }
-    }
-    else {
+    } else {
        purgevp = NULL;
     }
     originalvp = tt->volume;
-    if ((V_type(originalvp) == backupVolume) || (V_type(originalvp) == readonlyVolume)){
-        Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
+    if ((V_type(originalvp) == backupVolume)
+       || (V_type(originalvp) == readonlyVolume)) {
+       Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
        error = EROFS;
        goto fail;
     }
     if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
-       Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
-          V_id(originalvp));
-       error = VOFFLINE;
-       goto fail;
+       Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
+           V_id(originalvp));
+       error = VOFFLINE;
+       goto fail;
     }
     if (purgevp) {
        if (originalvp->device != purgevp->device) {
-            Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
+           Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
            error = EXDEV;
            goto fail;
        }
        if (V_type(purgevp) != readonlyVolume) {
-            Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
+           Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
            error = EINVAL;
            goto fail;
        }
-       if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(purgevp)) {
+       if (V_type(originalvp) == readonlyVolume
+           && V_parentId(originalvp) != V_parentId(purgevp)) {
            Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
            error = EXDEV;
            goto fail;
        }
-       if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(purgevp)) {
-            Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
-               purgeId, tt->volid);
+       if (V_type(originalvp) == readwriteVolume
+           && tt->volid != V_parentId(purgevp)) {
+           Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
            error = EXDEV;
            goto fail;
        }
@@ -600,7 +744,9 @@ char *newName;
 
     error = 0;
 
-    newvp = VCreateVolume(&error, originalvp->partition->name, newId, V_parentId(originalvp));
+    newvp =
+       VCreateVolume(&error, originalvp->partition->name, newId,
+                     V_parentId(originalvp));
     if (error) {
        Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
        newvp = (Volume *) 0;
@@ -608,26 +754,26 @@ char *newName;
     }
     if (newType == readonlyVolume)
        V_cloneId(originalvp) = newId;
-     Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid, newId);
+    Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
+       newId);
     if (purgevp)
-        Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
+       Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
     CloneVolume(&error, originalvp, newvp, purgevp);
-    purgevp = NULL;  /* clone releases it, maybe even if error */
+    purgevp = NULL;            /* clone releases it, maybe even if error */
     if (error) {
-        Log("1 Volser: Clone: clone operation failed with code %d\n", error);
-        LogError(error);
+       Log("1 Volser: Clone: clone operation failed with code %u\n", error);
+       LogError(error);
        goto fail;
     }
     if (newType == readonlyVolume) {
        AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".readonly");
        V_type(newvp) = readonlyVolume;
-    }
-    else if (newType == backupVolume) {
+    } else if (newType == backupVolume) {
        AssignVolumeName(&V_disk(newvp), V_name(originalvp), ".backup");
        V_type(newvp) = backupVolume;
        V_backupId(originalvp) = newId;
     }
-    strcpy(newvp->header->diskstuff.name,newName);
+    strcpy(newvp->header->diskstuff.name, newName);
     V_creationDate(newvp) = V_copyDate(newvp);
     ClearVolumeStats(&V_disk(newvp));
     V_destroyMe(newvp) = DESTROY_ME;
@@ -639,108 +785,111 @@ char *newName;
     V_inUse(newvp) = 0;
     VUpdateVolume(&error, newvp);
     if (error) {
-        Log("1 Volser: Clone: VUpdate failed code %d\n", error);
-        LogError(error);
+       Log("1 Volser: Clone: VUpdate failed code %u\n", error);
+       LogError(error);
        goto fail;
     }
-    VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
+    VDetachVolume(&error, newvp);      /* allow file server to get it's hands on it */
     newvp = NULL;
     VUpdateVolume(&error, originalvp);
     if (error) {
-        Log("1 Volser: Clone: original update %d\n", error);
-        LogError(error);
+       Log("1 Volser: Clone: original update %u\n", error);
+       LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt)){
-       tt = (struct volser_trans *) 0;
+    TClearRxCall(tt);
+    if (TRELE(tt)) {
+       tt = (struct volser_trans *)0;
        error = VOLSERTRELE_ERROR;
        goto fail;
     }
-    DeleteTrans(ttc);
+    DeleteTrans(ttc, 1);
     return 0;
 
-fail:
-    if (purgevp) VDetachVolume(&code, purgevp);
-    if (newvp) VDetachVolume(&code, newvp);
+  fail:
+    if (purgevp)
+       VDetachVolume(&code, purgevp);
+    if (newvp)
+       VDetachVolume(&code, newvp);
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
     }
-    if(ttc) DeleteTrans(ttc);
+    if (ttc)
+       DeleteTrans(ttc, 1);
     return error;
 }
 
 /* reclone this volume into the specified id */
-afs_int32 SAFSVolReClone (acid, atrans, cloneId)
-struct rx_call *acid;
-afs_int32 atrans;
-afs_int32 cloneId; 
+afs_int32
+SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 cloneId)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolReClone (acid, atrans, cloneId);
-  osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG, cloneId, AUD_END);
-  return code;
+    code = VolReClone(acid, atrans, cloneId);
+    osi_auditU(acid, VS_ReCloneEvent, code, AUD_LONG, atrans, AUD_LONG,
+              cloneId, AUD_END);
+    return code;
 }
 
-afs_int32 VolReClone (acid, atrans, cloneId)
-struct rx_call *acid;
-afs_int32 atrans;
-afs_int32 cloneId; 
+static afs_int32
+VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
 {
     register struct Volume *originalvp, *clonevp;
     Error error, code;
     afs_int32 newType;
-    register struct volser_trans *tt,*ttc;
+    register struct volser_trans *tt, *ttc;
     char caller[MAXKTCNAMELEN];
-    
-    /*not a super user*/
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
-    if (DoLogging) Log("%s is executing Reclone Volume %u\n", caller, cloneId);
+
+    /*not a super user */
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;
+    if (DoLogging)
+       Log("%s is executing Reclone Volume %u\n", caller, cloneId);
     error = 0;
     clonevp = originalvp = (Volume *) 0;
-    tt = (struct volser_trans *) 0;
+    tt = (struct volser_trans *)0;
 
     tt = FindTrans(atrans);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolReClone: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
     ttc = NewTrans(cloneId, tt->partition);
-    if (!ttc){ /* someone is messing with the clone already */
+    if (!ttc) {                        /* someone is messing with the clone already */
        TRELE(tt);
-       return VBUSY;
+       return VOLSERVOLBUSY;
     }
-    strcpy(tt->lastProcName,"ReClone");
-    tt->rxCallPtr = acid;
-    
+    TSetRxCall(tt, acid, "ReClone");
+
     originalvp = tt->volume;
-    if ((V_type(originalvp) == backupVolume) ||
-       (V_type(originalvp) == readonlyVolume)){
-        Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
+    if ((V_type(originalvp) == backupVolume)
+       || (V_type(originalvp) == readonlyVolume)) {
+       Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
        error = EROFS;
        goto fail;
     }
     if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) {
-       Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
-          V_id(originalvp));
-       error = VOFFLINE;
-       goto fail;
+       Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
+           V_id(originalvp));
+       error = VOFFLINE;
+       goto fail;
     }
 
-    clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
+    clonevp = VAttachVolume_retry(&error, cloneId, V_VOLUPD);
     if (error) {
        Log("1 Volser: can't attach clone %d\n", cloneId);
        goto fail;
     }
 
-    newType = V_type(clonevp);         /* type of the new volume */
+    newType = V_type(clonevp); /* type of the new volume */
 
     if (originalvp->device != clonevp->device) {
-       Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, cloneId);
+       Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
+           tt->volid, cloneId);
        error = EXDEV;
        goto fail;
     }
@@ -749,24 +898,26 @@ afs_int32 cloneId;
        error = EINVAL;
        goto fail;
     }
-    if (V_type(originalvp) == readonlyVolume && V_parentId(originalvp) != V_parentId(clonevp)) {
+    if (V_type(originalvp) == readonlyVolume
+       && V_parentId(originalvp) != V_parentId(clonevp)) {
        Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
        error = EXDEV;
        goto fail;
     }
-    if (V_type(originalvp) == readwriteVolume && tt->volid != V_parentId(clonevp)) {
-       Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n",
-           cloneId, tt->volid);
+    if (V_type(originalvp) == readwriteVolume
+       && tt->volid != V_parentId(clonevp)) {
+       Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
        error = EXDEV;
        goto fail;
     }
 
     error = 0;
-    Log("1 Volser: Clone: Recloning volume %u to volume %u\n",
-       tt->volid, cloneId);
+    Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
+       cloneId);
     CloneVolume(&error, originalvp, clonevp, clonevp);
     if (error) {
-       Log("1 Volser: Clone: reclone operation failed with code %d\n", error);
+       Log("1 Volser: Clone: reclone operation failed with code %d\n",
+           error);
        LogError(error);
        goto fail;
     }
@@ -775,8 +926,7 @@ afs_int32 cloneId;
     if (newType == readonlyVolume) {
        AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".readonly");
        V_type(clonevp) = readonlyVolume;
-    }
-    else if (newType == backupVolume) {
+    } else if (newType == backupVolume) {
        AssignVolumeName(&V_disk(clonevp), V_name(originalvp), ".backup");
        V_type(clonevp) = backupVolume;
        V_backupId(originalvp) = cloneId;
@@ -796,40 +946,47 @@ afs_int32 cloneId;
     V_inUse(clonevp) = 0;
     VUpdateVolume(&error, clonevp);
     if (error) {
-       Log("1 Volser: Clone: VUpdate failed code %d\n", error);
+       Log("1 Volser: Clone: VUpdate failed code %u\n", error);
        LogError(error);
        goto fail;
     }
-    VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
+    /* VUpdateVolume succeeded. Mark it in service so there's no window 
+     * between FSYNC_VOL_ON and VolSetFlags where it's offline with no  
+     * specialStatus; this is a reclone and this volume started online  
+     */
+    V_inService(clonevp) = 1;
+    VDetachVolume(&error, clonevp);    /* allow file server to get it's hands on it */
     clonevp = NULL;
     VUpdateVolume(&error, originalvp);
     if (error) {
-        Log("1 Volser: Clone: original update %d\n", error);
-        LogError(error);
+       Log("1 Volser: Clone: original update %u\n", error);
+       LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt)){
-       tt = (struct volser_trans *) 0;
+    TClearRxCall(tt);
+    if (TRELE(tt)) {
+       tt = (struct volser_trans *)0;
        error = VOLSERTRELE_ERROR;
        goto fail;
     }
-    
-    DeleteTrans(ttc);
+
+    DeleteTrans(ttc, 1);
 
     {
-    struct DiskPartition *tpartp = originalvp->partition;    
-    FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
+       struct DiskPartition64 *tpartp = originalvp->partition;
+       FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
     }
     return 0;
 
-fail:
-    if (clonevp) VDetachVolume(&code, clonevp);
+  fail:
+    if (clonevp)
+       VDetachVolume(&code, clonevp);
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
     }
-    if(ttc) DeleteTrans(ttc);
+    if (ttc)
+       DeleteTrans(ttc, 1);
     return error;
 }
 
@@ -837,40 +994,42 @@ fail:
  * volume transaction is spec'd by iflags.  New trans id is returned in ttid.
  * See volser.h for definition of iflags (the constants are named IT*).
  */
-afs_int32 SAFSVolTransCreate (acid, volume, partition, iflags, ttid)
-struct rx_call *acid;
-afs_int32 volume;
-afs_int32 partition;
-afs_int32 iflags;
-afs_int32 *ttid; 
+afs_int32
+SAFSVolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
+                  afs_int32 iflags, afs_int32 *ttid)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolTransCreate (acid, volume, partition, iflags, ttid);
-  osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume, AUD_END);
-  return code;
+    code = VolTransCreate(acid, volume, partition, iflags, ttid);
+    osi_auditU(acid, VS_TransCrEvent, code, AUD_LONG, *ttid, AUD_LONG, volume,
+              AUD_END);
+    return code;
 }
 
-afs_int32 VolTransCreate (acid, volume, partition, iflags, ttid)
-struct rx_call *acid;
-afs_int32 volume;
-afs_int32 partition;
-afs_int32 iflags;
-afs_int32 *ttid; 
+static afs_int32
+VolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
+                  afs_int32 iflags, afs_int32 *ttid)
 {
     register struct volser_trans *tt;
     register Volume *tv;
-    afs_int32 error, code;
+    afs_int32 error;
+    Error code;
     afs_int32 mode;
     char caller[MAXKTCNAMELEN];
 
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
-    if (iflags & ITCreate) mode = V_SECRETLY;
-    else if (iflags & ITBusy) mode = V_CLONE;
-    else if (iflags & ITReadOnly) mode = V_READONLY;
-    else if (iflags & ITOffline) mode = V_VOLUPD;
-    else  { 
-       Log("1 Volser: TransCreate: Could not create trans, error %u\n",EINVAL);
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
+    if (iflags & ITCreate)
+       mode = V_SECRETLY;
+    else if (iflags & ITBusy)
+       mode = V_CLONE;
+    else if (iflags & ITReadOnly)
+       mode = V_READONLY;
+    else if (iflags & ITOffline)
+       mode = V_VOLUPD;
+    else {
+       Log("1 Volser: TransCreate: Could not create trans, error %u\n",
+           EINVAL);
        LogError(EINVAL);
        return EINVAL;
     }
@@ -883,81 +1042,79 @@ afs_int32 *ttid;
     tv = XAttachVolume(&error, volume, partition, mode);
     if (error) {
        /* give up */
-       if (tv) VDetachVolume(&code, tv);
-       DeleteTrans(tt);
+       if (tv)
+           VDetachVolume(&code, tv);
+       DeleteTrans(tt, 1);
        return error;
     }
+    VTRANS_OBJ_LOCK(tt);
     tt->volume = tv;
     *ttid = tt->tid;
     tt->iflags = iflags;
     tt->vflags = 0;
-    strcpy(tt->lastProcName,"TransCreate");
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
-    
+    TSetRxCall_r(tt, NULL, "TransCreate");
+    VTRANS_OBJ_UNLOCK(tt);
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
+
     return 0;
 }
 
 /* using aindex as a 0-based index, return the aindex'th volume on this server
  * Both the volume number and partition number (one-based) are returned.
  */
-afs_int32 SAFSVolGetNthVolume (acid, aindex, avolume, apart)
-struct rx_call *acid;
-afs_int32 aindex;
-afs_int32 *avolume;
-afs_int32 *apart; 
+afs_int32
+SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_uint32 *avolume,
+                   afs_int32 *apart)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolGetNthVolume (acid, aindex, avolume, apart);
-  osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
-  return code;
+    code = VolGetNthVolume(acid, aindex, avolume, apart);
+    osi_auditU(acid, VS_GetNVolEvent, code, AUD_LONG, *avolume, AUD_END);
+    return code;
 }
 
-afs_int32 VolGetNthVolume (acid, aindex, avolume, apart)
-struct rx_call *acid;
-afs_int32 aindex;
-afs_int32 *avolume;
-afs_int32 *apart; 
+static afs_int32
+VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_uint32 *avolume,
+                   afs_int32 *apart)
 {
-      Log("1 Volser: GetNthVolume: Not yet implemented\n");
+    Log("1 Volser: GetNthVolume: Not yet implemented\n");
     return VOLSERNO_OP;
 }
 
 /* return the volume flags (VT* constants in volser.h) associated with this
  * transaction.
  */
-afs_int32 SAFSVolGetFlags (acid, atid, aflags)
-struct rx_call *acid;
-afs_int32 atid;
-afs_int32 *aflags; 
+afs_int32
+SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolGetFlags (acid, atid, aflags);
-  osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
-  return code;
+    code = VolGetFlags(acid, atid, aflags);
+    osi_auditU(acid, VS_GetFlgsEvent, code, AUD_LONG, atid, AUD_END);
+    return code;
 }
 
-afs_int32 VolGetFlags (acid, atid, aflags)
-struct rx_call *acid;
-afs_int32 atid;
-afs_int32 *aflags; 
+static afs_int32
+VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
 {
     register struct volser_trans *tt;
-    
+
     tt = FindTrans(atid);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolGetFlags: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
+           tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"GetFlags");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "GetFlags");
     *aflags = tt->vflags;
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
-    
+    TClearRxCall(tt);
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
+
     return 0;
 }
 
@@ -965,40 +1122,39 @@ afs_int32 *aflags;
  * transaction.  Effects take place immediately on volume, although volume
  * remains attached as usual by the transaction.
  */
-afs_int32 SAFSVolSetFlags (acid, atid, aflags)
-struct rx_call *acid;
-afs_int32 atid;
-afs_int32 aflags; 
+afs_int32
+SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolSetFlags (acid, atid, aflags);
-  osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags, AUD_END);
-  return code;
+    code = VolSetFlags(acid, atid, aflags);
+    osi_auditU(acid, VS_SetFlgsEvent, code, AUD_LONG, atid, AUD_LONG, aflags,
+              AUD_END);
+    return code;
 }
 
-afs_int32 VolSetFlags (acid, atid, aflags)
-struct rx_call *acid;
-afs_int32 atid;
-afs_int32 aflags; 
+static afs_int32
+VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
 {
     register struct volser_trans *tt;
     register struct Volume *vp;
-    afs_int32 error;
+    Error error;
     char caller[MAXKTCNAMELEN];
 
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
     /* find the trans */
     tt = FindTrans(atid);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolSetFlags: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
+           tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"SetFlags");
-    tt->rxCallPtr = acid;
-    vp = tt->volume;   /* pull volume out of transaction */
+    TSetRxCall(tt, acid, "SetFlags");
+    vp = tt->volume;           /* pull volume out of transaction */
 
     /* check if we're allowed to make any updates */
     if (tt->iflags & ITReadOnly) {
@@ -1009,22 +1165,23 @@ afs_int32 aflags;
     /* handle delete-on-salvage flag */
     if (aflags & VTDeleteOnSalvage) {
        V_destroyMe(tt->volume) = DESTROY_ME;
-    }
-    else {
+    } else {
        V_destroyMe(tt->volume) = 0;
     }
-    
+
     if (aflags & VTOutOfService) {
        V_inService(vp) = 0;
-    }
-    else {
+    } else {
        V_inService(vp) = 1;
     }
     VUpdateVolume(&error, vp);
+    VTRANS_OBJ_LOCK(tt);
     tt->vflags = aflags;
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
-    
+    TClearRxCall_r(tt);
+    VTRANS_OBJ_UNLOCK(tt);
+    if (TRELE(tt) && !error)
+       return VOLSERTRELE_ERROR;
+
     return error;
 }
 
@@ -1032,30 +1189,24 @@ afs_int32 aflags;
  * date.  Send the dump to a different transaction (destTrans) on the server
  * specified by the destServer structure.
  */
-afs_int32 SAFSVolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
-struct rx_call *acid;
-afs_int32 fromTrans;
-afs_int32 fromDate;
-struct destServer *destination;
-struct restoreCookie *cookie;
-afs_int32 destTrans; 
-{
-  afs_int32 code;
-
-  code = VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie);
-  osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, 
-                                          AUD_HOST, destination->destHost, 
-                                          AUD_LONG, destTrans, AUD_END);
-  return code;
-}
-
-afs_int32 VolForward (acid, fromTrans, fromDate, destination, destTrans,cookie)
-struct rx_call *acid;
-afs_int32 fromTrans;
-afs_int32 fromDate;
-struct destServer *destination;
-struct restoreCookie *cookie;
-afs_int32 destTrans; 
+afs_int32
+SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
+              struct destServer *destination, afs_int32 destTrans, 
+              struct restoreCookie *cookie)
+{
+    afs_int32 code;
+
+    code =
+       VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
+    osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
+              destination->destHost, AUD_LONG, destTrans, AUD_END);
+    return code;
+}
+
+static afs_int32
+VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
+              struct destServer *destination, afs_int32 destTrans, 
+              struct restoreCookie *cookie)
 {
     register struct volser_trans *tt;
     register afs_int32 code;
@@ -1066,22 +1217,24 @@ afs_int32 destTrans;
     afs_int32 securityIndex;
     char caller[MAXKTCNAMELEN];
 
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
     /* initialize things */
-    tcon = (struct rx_connection *) 0;
-    tt = (struct volser_trans *) 0;
+    tcon = (struct rx_connection *)0;
+    tt = (struct volser_trans *)0;
 
     /* find the local transaction */
     tt = FindTrans(fromTrans);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
     vp = tt->volume;
-    strcpy(tt->lastProcName,"Forward");
-    
+    TSetRxCall(tt, NULL, "Forward");
+
     /* get auth info for the this connection (uses afs from ticket file) */
     code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
     if (code) {
@@ -1090,40 +1243,46 @@ afs_int32 destTrans;
     }
 
     /* make an rpc connection to the other server */
-    tcon = rx_NewConnection(htonl(destination->destHost), htons(destination->destPort),VOLSERVICE_ID, securityObject, securityIndex);
+    tcon =
+       rx_NewConnection(htonl(destination->destHost),
+                        htons(destination->destPort), VOLSERVICE_ID,
+                        securityObject, securityIndex);
     if (!tcon) {
-        tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return ENOTCONN;
     }
     tcall = rx_NewCall(tcon);
-    tt->rxCallPtr = tcall;
+    TSetRxCall(tt, tcall, "Forward");
     /* start restore going.  fromdate == 0 --> doing an incremental dump/restore */
-    code = StartAFSVolRestore(tcall, destTrans, (fromDate? 1 : 0),cookie);
+    code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
     if (code) {
        goto fail;
     }
 
     /* these next calls implictly call rx_Write when writing out data */
-    code = DumpVolume(tcall, vp, fromDate, 0);/* last field = don't dump all dirs */
-    if (code) goto fail;
-    EndAFSVolRestore(tcall);               /* probably doesn't do much */
-    tt->rxCallPtr = (struct rx_call *)0;
+    code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
+    if (code)
+       goto fail;
+    EndAFSVolRestore(tcall);   /* probably doesn't do much */
+    TClearRxCall(tt);
     code = rx_EndCall(tcall, 0);
-    rx_DestroyConnection(tcon); /* done with the connection */
+    rx_DestroyConnection(tcon);        /* done with the connection */
     tcon = NULL;
-    if (code) goto fail;
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
-   
+    if (code)
+       goto fail;
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
+
     return 0;
-    
-fail:
+
+  fail:
     if (tcon) {
-       rx_EndCall(tcall,0); 
+       (void)rx_EndCall(tcall, 0);
        rx_DestroyConnection(tcon);
     }
-    if (tt){
-       tt->rxCallPtr = (struct rx_call *)0;
+    if (tt) {
+        TClearRxCall(tt);
        TRELE(tt);
     }
     return code;
@@ -1139,305 +1298,331 @@ fail:
  * need just an incremental (and from the same time), if that's 
  * what we're doing. 
  */
-afs_int32 SAFSVolForwardMultiple (acid, fromTrans, fromDate, destinations, 
-                             spare, cookie, results)
-     struct rx_call *acid;
-     afs_int32 fromTrans;
-     afs_int32 fromDate;
-     afs_int32 spare;
-     manyDests *destinations;
-     struct restoreCookie *cookie;
-     manyResults *results;
-{
-  afs_int32 securityIndex;
-  struct rx_securityClass *securityObject;
-  char caller[MAXKTCNAMELEN];
-  struct volser_trans *tt;
-  afs_int32  ec, code, *codes;
-  struct rx_connection **tcons;
-  struct rx_call **tcalls;
-  struct Volume *vp;
-  int i, nconns, is_incremental;
-
-  if (results)
-     memset(results, 0, sizeof(manyResults));
-
-  if (!afsconf_SuperUser(tdir, acid, caller))
-    return VOLSERBAD_ACCESS;/*not a super user*/
-  tt = FindTrans(fromTrans);
-  if (!tt) 
-    return ENOENT;
-  if (tt->vflags & VTDeleted) {
-    Log("1 Volser: VolForward: volume %u has been deleted \n",tt->volid);
-    TRELE(tt);
-    return ENOENT;
-  }
-  vp = tt->volume;
-  strcpy(tt->lastProcName, "ForwardMulti");
-  
-  /* (fromDate == 0) ==> incremental dump */
-  is_incremental = (fromDate ? 1 : 0);
-  
-  i= results->manyResults_len = destinations->manyDests_len;
-  results->manyResults_val = codes = (afs_int32 *)malloc(i * sizeof(afs_int32));
-  tcons = (struct rx_connection **) malloc (i*sizeof (struct rx_connection *));
-  tcalls = (struct rx_call **) malloc (i*sizeof (struct rx_call *));
-
-  /* get auth info for this connection (uses afs from ticket file) */
-  code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
-  if (code) {
-    goto fail;  /* in order to audit each failure */
-  }
-  
-  /* make connections to all the other servers */
-  for (i=0; i < destinations->manyDests_len; i++) {
-    struct replica *dest = &(destinations->manyDests_val[i]);
-    tcons[i] = rx_NewConnection(htonl(dest->server.destHost),
-                               htons(dest->server.destPort),
-                               VOLSERVICE_ID, securityObject, securityIndex);
-    if (!tcons[i]) {
-      codes[i] = ENOTCONN;
+afs_int32
+SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32 
+                      fromDate, manyDests *destinations, afs_int32 spare,
+                      struct restoreCookie *cookie, manyResults *results)
+{
+    afs_int32 securityIndex;
+    struct rx_securityClass *securityObject;
+    char caller[MAXKTCNAMELEN];
+    struct volser_trans *tt;
+    afs_int32 ec, code, *codes;
+    struct rx_connection **tcons;
+    struct rx_call **tcalls;
+    struct Volume *vp;
+    int i, is_incremental;
+
+    if (results) {
+       memset(results, 0, sizeof(manyResults));
+       i = results->manyResults_len = destinations->manyDests_len;
+       results->manyResults_val = codes =
+         (afs_int32 *) malloc(i * sizeof(afs_int32));
+    }  
+    if (!results || !results->manyResults_val)
+       return ENOMEM;
+
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
+    tt = FindTrans(fromTrans);
+    if (!tt)
+       return ENOENT;
+    if (tt->vflags & VTDeleted) {
+       Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
+       TRELE(tt);
+       return ENOENT;
     }
-    else {
-      if (!(tcalls[i] = rx_NewCall(tcons[i])))
-       codes[i]=ENOTCONN;
-      else {
-       codes[i] = StartAFSVolRestore(tcalls[i], dest->trans,
-                                     is_incremental,cookie);
-       if (codes[i]) {
-         rx_EndCall (tcalls[i],0); tcalls[i] = 0;
-         rx_DestroyConnection(tcons[i]); tcons[i] = 0;
+    vp = tt->volume;
+    TSetRxCall(tt, NULL, "ForwardMulti");
+
+    /* (fromDate == 0) ==> full dump */
+    is_incremental = (fromDate ? 1 : 0);
+
+    tcons =
+       (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
+    if (!tcons) {
+       return ENOMEM;
+    }
+    tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
+    if (!tcalls) {
+       free(tcons);
+       return ENOMEM;
+    }
+
+    /* get auth info for this connection (uses afs from ticket file) */
+    code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
+    if (code) {
+       goto fail;              /* in order to audit each failure */
+    }
+
+    /* make connections to all the other servers */
+    for (i = 0; i < destinations->manyDests_len; i++) {
+       struct replica *dest = &(destinations->manyDests_val[i]);
+       tcons[i] =
+           rx_NewConnection(htonl(dest->server.destHost),
+                            htons(dest->server.destPort), VOLSERVICE_ID,
+                            securityObject, securityIndex);
+       if (!tcons[i]) {
+           codes[i] = ENOTCONN;
+       } else {
+           if (!(tcalls[i] = rx_NewCall(tcons[i])))
+               codes[i] = ENOTCONN;
+           else {
+               codes[i] =
+                   StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
+                                      cookie);
+               if (codes[i]) {
+                   (void)rx_EndCall(tcalls[i], 0);
+                   tcalls[i] = 0;
+                   rx_DestroyConnection(tcons[i]);
+                   tcons[i] = 0;
+               }
+           }
+       }
+    }
+
+    /* these next calls implictly call rx_Write when writing out data */
+    code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
+
+
+  fail:
+    for (i--; i >= 0; i--) {
+       struct replica *dest = &(destinations->manyDests_val[i]);
+
+       if (!code && tcalls[i] && !codes[i]) {
+           EndAFSVolRestore(tcalls[i]);
+       }
+       if (tcalls[i]) {
+           ec = rx_EndCall(tcalls[i], 0);
+           if (!codes[i])
+               codes[i] = ec;
        }
-      }
-    }
-  }
-  
-  /* these next calls implictly call rx_Write when writing out data */
-  code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
-  
-
-fail:
-  for (i--; i >=0 ; i--) {
-      struct replica *dest = &(destinations->manyDests_val[i]);
-
-      if (!code && tcalls[i] && !codes[i]) {
-          EndAFSVolRestore(tcalls[i]);
-      }
-      if (tcalls[i]) {
-          ec = rx_EndCall(tcalls[i], 0);
-         if (!codes[i]) codes[i] = ec;
-      }
-      if (tcons[i]) {
-          rx_DestroyConnection(tcons[i]); /* done with the connection */
-      }
-
-      osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), 
-                AUD_LONG, fromTrans, AUD_HOST, dest->server.destHost, 
-                AUD_LONG, dest->trans, AUD_END);
-  }
-  free (tcons);
-  free (tcalls);
-  
-  if (tt) {
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt) && !code)  /* return the first code if it's set */
-      return VOLSERTRELE_ERROR;
-  }
-   
-  return code;
-}
-
-afs_int32 SAFSVolDump (acid, fromTrans, fromDate)
-struct rx_call *acid;
-afs_int32 fromTrans;
-afs_int32 fromDate; 
-{
-  afs_int32 code;
-
-  code = VolDump (acid, fromTrans, fromDate);
-  osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
-  return code;
-}
-
-afs_int32 VolDump (acid, fromTrans, fromDate)
-struct rx_call *acid;
-afs_int32 fromTrans;
-afs_int32 fromDate; 
+       if (tcons[i]) {
+           rx_DestroyConnection(tcons[i]);     /* done with the connection */
+       }
+
+       osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
+                  fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
+                  dest->trans, AUD_END);
+    }
+    free(tcons);
+    free(tcalls);
+
+    if (tt) {
+        TClearRxCall(tt);
+       if (TRELE(tt) && !code) /* return the first code if it's set */
+           return VOLSERTRELE_ERROR;
+    }
+
+    return code;
+}
+
+afs_int32
+SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
+{
+    afs_int32 code;
+
+    code = VolDump(acid, fromTrans, fromDate, 0);
+    osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
+    return code;
+}
+
+afs_int32
+SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
+             afs_int32 flags)
+{
+    afs_int32 code;
+
+    code = VolDump(acid, fromTrans, fromDate, flags);
+    osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
+    return code;
+}
+
+static afs_int32
+VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
+       afs_int32 flags)
 {
     int code = 0;
     register struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
-    
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
+
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
     tt = FindTrans(fromTrans);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolDump: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"Dump");
-    tt->rxCallPtr = acid;
-    code = DumpVolume(acid, tt->volume, fromDate, 1);  /* squirt out the volume's data, too */
-    if(code){tt->rxCallPtr = (struct rx_call *)0; TRELE(tt); return code;}
-    tt->rxCallPtr = (struct rx_call *)0; 
-    
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
-    
+    TSetRxCall(tt, acid, "Dump");
+    code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
+                     ? 0 : 1); /* squirt out the volume's data, too */
+    if (code) {
+        TClearRxCall(tt);
+       TRELE(tt);
+       return code;
+    }
+    TClearRxCall(tt);
+
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
+
     return 0;
 }
 
 /* 
  * Ha!  No more helper process!
  */
-afs_int32 SAFSVolRestore (acid, atrans, aflags,cookie)
-struct rx_call *acid;
-afs_int32 aflags;
-afs_int32 atrans; 
-struct restoreCookie *cookie;
+afs_int32
+SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
+              struct restoreCookie *cookie)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolRestore (acid, atrans, aflags,cookie);
-  osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
-  return code;
+    code = VolRestore(acid, atrans, aflags, cookie);
+    osi_auditU(acid, VS_RestoreEvent, code, AUD_LONG, atrans, AUD_END);
+    return code;
 }
 
-afs_int32 VolRestore (acid, atrans, aflags,cookie)
-struct rx_call *acid;
-int aflags;
-afs_int32 atrans; 
-struct restoreCookie *cookie;
+static afs_int32
+VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
+          struct restoreCookie *cookie)
 {
     register struct volser_trans *tt;
-    register afs_int32 code,tcode;
+    register afs_int32 code, tcode;
     char caller[MAXKTCNAMELEN];
 
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
     tt = FindTrans(atrans);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolRestore: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"Restore");
-    tt->rxCallPtr = acid;
-    code = RestoreVolume(acid, tt->volume, (aflags & 1),cookie);   /* last is incrementalp */
-    FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l);/*break call backs on the
-                                                    restored volume */
-    tt->rxCallPtr = (struct rx_call *)0; 
+    TSetRxCall(tt, acid, "Restore");
+
+    DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
+
+    code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie);      /* last is incrementalp */
+    FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
+    TClearRxCall(tt);
     tcode = TRELE(tt);
-    
-    return (code? code : tcode);
+
+    return (code ? code : tcode);
 }
 
 /* end a transaction, returning the transaction's final error code in rcode */
-afs_int32 SAFSVolEndTrans (acid, destTrans, rcode)
-struct rx_call *acid;
-afs_int32 destTrans;
-afs_int32 *rcode; 
+afs_int32
+SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolEndTrans (acid, destTrans, rcode);
-  osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
-  return code;
+    code = VolEndTrans(acid, destTrans, rcode);
+    osi_auditU(acid, VS_EndTrnEvent, code, AUD_LONG, destTrans, AUD_END);
+    return code;
 }
 
-afs_int32 VolEndTrans (acid, destTrans, rcode)
-struct rx_call *acid;
-afs_int32 destTrans;
-afs_int32 *rcode; 
+static afs_int32
+VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
 {
     register struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
-    
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
+
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
     tt = FindTrans(destTrans);
-    if (!tt) {return ENOENT;}
+    if (!tt) {
+       return ENOENT;
+    }
     *rcode = tt->returnCode;
-    DeleteTrans(tt);   /* this does an implicit TRELE */
-    
+    DeleteTrans(tt, 1);                /* this does an implicit TRELE */
+
     return 0;
 }
 
-afs_int32 SAFSVolSetForwarding (acid, atid, anewsite)
-struct rx_call *acid;
-afs_int32 atid;
-afs_int32 anewsite;
+afs_int32
+SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolSetForwarding (acid, atid, anewsite);
-  osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST, anewsite, AUD_END);
-  return code;
+    code = VolSetForwarding(acid, atid, anewsite);
+    osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
+              anewsite, AUD_END);
+    return code;
 }
 
-afs_int32 VolSetForwarding (acid, atid, anewsite)
-struct rx_call *acid;
-afs_int32 atid;
-afs_int32 anewsite;
+static afs_int32
+VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
 {
-    
     register struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
-    
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
+    char partName[16];
+
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
     tt = FindTrans(atid);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
+           tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"SetForwarding");
-    tt->rxCallPtr = acid;
-    FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
-   
+    TSetRxCall(tt, acid, "SetForwarding");
+    if (volutil_PartitionName2_r(tt->partition, partName, sizeof(partName)) != 0) {
+       partName[0] = '\0';
+    }
+    FSYNC_VolOp(tt->volid, partName, FSYNC_VOL_MOVE, anewsite, NULL);
+    TClearRxCall(tt);
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
+
     return 0;
 }
 
-afs_int32 SAFSVolGetStatus (acid, atrans, astatus)
-struct rx_call *acid;
-afs_int32 atrans;
-register struct volser_status *astatus;
+afs_int32
+SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
+                register struct volser_status *astatus)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolGetStatus (acid, atrans, astatus);
-  osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
-  return code;
+    code = VolGetStatus(acid, atrans, astatus);
+    osi_auditU(acid, VS_GetStatEvent, code, AUD_LONG, atrans, AUD_END);
+    return code;
 }
 
-afs_int32 VolGetStatus (acid, atrans, astatus)
-struct rx_call *acid;
-afs_int32 atrans;
-register struct volser_status *astatus;
+static afs_int32
+VolGetStatus(struct rx_call *acid, afs_int32 atrans,
+            register struct volser_status *astatus)
 {
     register struct Volume *tv;
     register struct VolumeDiskData *td;
     struct volser_trans *tt;
-    
-    
+
+
     tt = FindTrans(atrans);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolGetStatus: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
+           tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"GetStatus");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "GetStatus");
     tv = tt->volume;
     if (!tv) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return ENOENT;
     }
-    
+
     td = &tv->header->diskstuff;
     astatus->volID = td->id;
     astatus->nextUnique = td->uniquifier;
@@ -1455,52 +1640,52 @@ register struct volser_status *astatus;
     astatus->expirationDate = td->expirationDate;
     astatus->backupDate = td->backupDate;
     astatus->copyDate = td->copyDate;
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
-    
+    TClearRxCall(tt);
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
+
     return 0;
 }
 
-afs_int32 SAFSVolSetInfo (acid, atrans, astatus)
-struct rx_call *acid;
-afs_int32 atrans;
-register struct volintInfo *astatus;
+afs_int32
+SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
+              register struct volintInfo *astatus)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolSetInfo (acid, atrans, astatus);
-  osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
-  return code;
+    code = VolSetInfo(acid, atrans, astatus);
+    osi_auditU(acid, VS_SetInfoEvent, code, AUD_LONG, atrans, AUD_END);
+    return code;
 }
 
-afs_int32 VolSetInfo (acid, atrans, astatus)
-struct rx_call *acid;
-afs_int32 atrans;
-register struct volintInfo *astatus;
+static afs_int32
+VolSetInfo(struct rx_call *acid, afs_int32 atrans,
+              register struct volintInfo *astatus)
 {
     register struct Volume *tv;
     register struct VolumeDiskData *td;
     struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
-    afs_int32 error;
+    Error error;
 
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/    
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
     tt = FindTrans(atrans);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolSetInfo: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"SetStatus");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetStatus");
     tv = tt->volume;
     if (!tv) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return ENOENT;
     }
-    
+
     td = &tv->header->diskstuff;
     /*
      * Add more fields as necessary
@@ -1509,107 +1694,109 @@ register struct volintInfo *astatus;
        td->maxquota = astatus->maxquota;
     if (astatus->dayUse != -1)
        td->dayUse = astatus->dayUse;
+    if (astatus->creationDate != -1)
+       td->creationDate = astatus->creationDate;
+    if (astatus->updateDate != -1)
+       td->updateDate = astatus->updateDate;
+    if (astatus->spare2 != -1)
+       td->volUpdateCounter = (unsigned int)astatus->spare2;
     VUpdateVolume(&error, tv);
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
+    TClearRxCall(tt);
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
     return 0;
 }
 
 
-afs_int32 SAFSVolGetName (acid, atrans, aname)
-struct rx_call *acid;
-afs_int32 atrans;
-char **aname; 
+afs_int32
+SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolGetName (acid, atrans, aname);
-  osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
-  return code;
+    code = VolGetName(acid, atrans, aname);
+    osi_auditU(acid, VS_GetNameEvent, code, AUD_LONG, atrans, AUD_END);
+    return code;
 }
 
-afs_int32 VolGetName (acid, atrans, aname)
-struct rx_call *acid;
-afs_int32 atrans;
-char **aname; 
+static afs_int32
+VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
 {
     register struct Volume *tv;
     register struct VolumeDiskData *td;
     struct volser_trans *tt;
     register int len;
-    
-    *aname = NULL;
+
+    /* We need to at least fill it in */
+    *aname = (char *)malloc(1);
+    if (!*aname)
+       return ENOMEM;
     tt = FindTrans(atrans);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolGetName: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"GetName");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "GetName");
     tv = tt->volume;
     if (!tv) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return ENOENT;
     }
-    
+
     td = &tv->header->diskstuff;
-    len        = strlen(td->name)+1;       /* don't forget the null */
+    len = strlen(td->name) + 1;        /* don't forget the null */
     if (len >= SIZE) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return E2BIG;
     }
-    *aname = (char *)malloc(len);
+    *aname = (char *)realloc(*aname, len);
     strcpy(*aname, td->name);
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt)) return VOLSERTRELE_ERROR;
-    
+    TClearRxCall(tt);
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
+
     return 0;
 }
+
 /*this is a handshake to indicate that the next call will be SAFSVolRestore
  * - a noop now !*/
-afs_int32 SAFSVolSignalRestore (acid, volname, volType, parentId, cloneId)
-struct rx_call *acid;
-char volname[];
-afs_int32 parentId, cloneId;
-int volType;
+afs_int32
+SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
+                    afs_uint32 parentId, afs_uint32 cloneId)
 {
-  return 0;
+    return 0;
 }
 
 
 /*return a list of all partitions on the server. The non mounted
  *partitions are returned as -1 in the corresponding slot in partIds*/
-afs_int32 SAFSVolListPartitions (acid, partIds)
-struct rx_call *acid;
-struct pIDs *partIds;
+afs_int32
+SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolListPartitions (acid, partIds);
-  osi_auditU(acid, VS_ListParEvent, code, AUD_END);
-  return code;
+    code = VolListPartitions(acid, partIds);
+    osi_auditU(acid, VS_ListParEvent, code, AUD_END);
+    return code;
 }
 
-afs_int32 VolListPartitions (acid, partIds)
-struct rx_call *acid;
-struct pIDs *partIds;
-{   
+static afs_int32
+VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
+{
     char namehead[9];
-    int code;
-    char i;
+    int i;
 
-    strcpy(namehead, "/vicep");        /*7 including null terminator*/
+    strcpy(namehead, "/vicep");        /*7 including null terminator */
 
     /* Just return attached partitions. */
     namehead[7] = '\0';
-    for (i=0; i<26; i++) {
+    for (i = 0; i < 26; i++) {
        namehead[6] = i + 'a';
-       if (VGetPartition(namehead, 0))
-           partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
+       partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
     }
 
     return 0;
@@ -1617,225 +1804,550 @@ struct pIDs *partIds;
 
 /*return a list of all partitions on the server. The non mounted
  *partitions are returned as -1 in the corresponding slot in partIds*/
-afs_int32 SAFSVolXListPartitions (acid, pEntries)
-struct rx_call *acid;
-struct partEntries *pEntries;
+afs_int32
+SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = XVolListPartitions (acid, pEntries);
-  osi_auditU(acid, VS_ListParEvent, code, AUD_END);
-  return code;
+    code = XVolListPartitions(acid, pEntries);
+    osi_auditU(acid, VS_ListParEvent, code, AUD_END);
+    return code;
 }
 
-afs_int32 XVolListPartitions (acid, pEntries)
-struct rx_call *acid;
-struct partEntries *pEntries;
-{   
-    struct stat rbuf, pbuf;
+static afs_int32
+XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
+{
     char namehead[9];
     struct partList partList;
-    struct DiskPartition *dp;
-    int i, j=0, k;
+    struct DiskPartition64 *dp;
+    int i, j = 0;
 
-    strcpy(namehead, "/vicep");        /*7 including null terminator*/
+    strcpy(namehead, "/vicep");        /*7 including null terminator */
 
     /* Only report attached partitions */
-    for(i = 0 ; i < VOLMAXPARTS; i++){
+    for (i = 0; i < VOLMAXPARTS; i++) {
+#ifdef AFS_DEMAND_ATTACH_FS
+       dp = VGetPartitionById(i, 0);
+#else
        if (i < 26) {
            namehead[6] = i + 'a';
            namehead[7] = '\0';
        } else {
+           int k;
+
            k = i - 26;
-           namehead[6] = 'a' + (k/26);
-           namehead[7] = 'a' + (k%26);
+           namehead[6] = 'a' + (k / 26);
+           namehead[7] = 'a' + (k % 26);
            namehead[8] = '\0';
        }
        dp = VGetPartition(namehead, 0);
+#endif
        if (dp)
            partList.partId[j++] = i;
     }
     pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
-    memcpy((char *)pEntries->partEntries_val, (char *)&partList, j * sizeof(int));
+    if (!pEntries->partEntries_val)
+       return ENOMEM;
+    memcpy((char *)pEntries->partEntries_val, (char *)&partList,
+          j * sizeof(int));
     pEntries->partEntries_len = j;
     return 0;
 
 }
 
 /*extract the volume id from string vname. Its of the form " V0*<id>.vol  "*/
-afs_int32 ExtractVolId(vname)
-char vname[];
+afs_int32
+ExtractVolId(char vname[])
 {
     int i;
-    char name[VOLSER_MAXVOLNAME +1];
+    char name[VOLSER_MAXVOLNAME + 1];
 
-    strcpy(name,vname);
+    strcpy(name, vname);
     i = 0;
-    while(name[i] == 'V' || name[i] == '0')
+    while (name[i] == 'V' || name[i] == '0')
        i++;
-    
-    name[11] = '\0';   /* smash the "." */
-    return(atol(&name[i]));
+
+    name[11] = '\0';           /* smash the "." */
+    return (atol(&name[i]));
 }
 
 /*return the name of the next volume header in the directory associated with dirp and dp.
 *the volume id is  returned in volid, and volume header name is returned in volname*/
-GetNextVol(DIR *dirp, char *volname, afs_int32 *volid)
-{  
+int
+GetNextVol(DIR * dirp, char *volname, afs_uint32 * volid)
+{
     struct dirent *dp;
 
-    dp = readdir(dirp);/*read next entry in the directory */
-    if(dp){
-       
-       if((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)){
+    dp = readdir(dirp);                /*read next entry in the directory */
+    if (dp) {
+       if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT)) {
            *volid = ExtractVolId(dp->d_name);
-           strcpy(volname,dp->d_name);
-           return 0;/*return the name of the file representing a volume */
+           strcpy(volname, dp->d_name);
+           return 0;           /*return the name of the file representing a volume */
+       } else {
+           strcpy(volname, "");
+           return 0;           /*volname doesnot represent a volume */
+       }
+    } else {
+       strcpy(volname, "EOD");
+       return 0;               /*end of directory */
+    }
+
+}
+
+/**
+ * volint vol info structure type.
+ */
+typedef enum {
+    VOLINT_INFO_TYPE_BASE,  /**< volintInfo type */
+    VOLINT_INFO_TYPE_EXT    /**< volintXInfo type */
+} volint_info_type_t;
+
+/**
+ * handle to various on-wire vol info types.
+ */
+typedef struct {
+    volint_info_type_t volinfo_type;
+    union {
+       void * opaque;
+       volintInfo * base;
+       volintXInfo * ext;
+    } volinfo_ptr;
+} volint_info_handle_t;
+
+/**
+ * store value to a field at the appropriate location in on-wire structure.
+ */
+#define VOLINT_INFO_STORE(handle, name, val) \
+    do { \
+        if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
+            (handle)->volinfo_ptr.base->name = (val); \
+        } else { \
+            (handle)->volinfo_ptr.ext->name = (val); \
+        } \
+    } while(0)
+
+/**
+ * get pointer to appropriate offset of field in on-wire structure.
+ */
+#define VOLINT_INFO_PTR(handle, name) \
+    (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
+     &((handle)->volinfo_ptr.base->name) : \
+     &((handle)->volinfo_ptr.ext->name))
+
+/**
+ * fill in appropriate type of on-wire volume metadata structure.
+ *
+ * @param vp      pointer to volume object
+ * @param handle  pointer to wire format handle object
+ *
+ * @pre vp object must contain header & pending_vol_op structurs (populate if from RPC)
+ * @pre handle object must have a valid pointer and enumeration value
+ *
+ * @note passing a NULL value for vp means that the fileserver doesn't
+ *       know about this particular volume, thus implying it is offline.
+ *
+ * @return operation status
+ *   @retval 0 success
+ *   @retval 1 failure
+ */
+static int
+FillVolInfo(Volume * vp, volint_info_handle_t * handle)
+{
+    unsigned int numStatBytes, now;
+    register struct VolumeDiskData *hdr = &vp->header->diskstuff;
+
+    /*read in the relevant info */
+    strcpy((char *)VOLINT_INFO_PTR(handle, name), hdr->name);
+    VOLINT_INFO_STORE(handle, status, VOK);    /*its ok */
+    VOLINT_INFO_STORE(handle, volid, hdr->id);
+    VOLINT_INFO_STORE(handle, type, hdr->type);        /*if ro volume */
+    VOLINT_INFO_STORE(handle, cloneID, hdr->cloneId);  /*if rw volume */
+    VOLINT_INFO_STORE(handle, backupID, hdr->backupId);
+    VOLINT_INFO_STORE(handle, parentID, hdr->parentId);
+    VOLINT_INFO_STORE(handle, copyDate, hdr->copyDate);
+    VOLINT_INFO_STORE(handle, size, hdr->diskused);
+    VOLINT_INFO_STORE(handle, maxquota, hdr->maxquota);
+    VOLINT_INFO_STORE(handle, filecount, hdr->filecount);
+    now = FT_ApproxTime();
+    if ((now - hdr->dayUseDate) > OneDay) {
+       VOLINT_INFO_STORE(handle, dayUse, 0);
+    } else {
+       VOLINT_INFO_STORE(handle, dayUse, hdr->dayUse);
+    }
+    VOLINT_INFO_STORE(handle, creationDate, hdr->creationDate);
+    VOLINT_INFO_STORE(handle, accessDate, hdr->accessDate);
+    VOLINT_INFO_STORE(handle, updateDate, hdr->updateDate);
+    VOLINT_INFO_STORE(handle, backupDate, hdr->backupDate);
+
+#ifdef AFS_DEMAND_ATTACH_FS
+    /*
+     * for DAFS, we "lie" about volume state --
+     * instead of returning the raw state from the disk header,
+     * we compute state based upon the fileserver's internal
+     * in-core state enumeration value reported to us via fssync,
+     * along with the blessed and inService flags from the header.
+     *   -- tkeiser 11/27/2007
+     */
+
+    /* Conditions that offline status is based on: 
+               volume is unattached state
+               volume state is in (one of several error states)
+               volume not in service
+               volume is not marked as blessed (not on hold)
+               volume in salvage req. state
+               volume needsSalvaged 
+               next op would set volume offline
+               next op would not leave volume online (based on several conditions)
+    */
+    if (!vp ||
+       (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
+       VIsErrorState(V_attachState(vp)) ||
+       !hdr->inService ||
+       !hdr->blessed || 
+       (V_attachState(vp) == VOL_STATE_SALVSYNC_REQ) ||
+       hdr->needsSalvaged ||
+       (vp->pending_vol_op && 
+               (vp->pending_vol_op->com.command == FSYNC_VOL_OFF || 
+               !VVolOpLeaveOnline_r(vp, vp->pending_vol_op) )
+       )
+       ) {
+       VOLINT_INFO_STORE(handle, inUse, 0);
+    } else {
+       VOLINT_INFO_STORE(handle, inUse, 1);
+    }
+#else
+    /* offline status based on program type, where != fileServer enum (1) is offline */
+    if (hdr->inUse == fileServer) {
+       VOLINT_INFO_STORE(handle, inUse, 1);
+    } else {
+       VOLINT_INFO_STORE(handle, inUse, 0);
+    }
+#endif
+
+
+    switch(handle->volinfo_type) {
+       /* NOTE: VOLINT_INFO_STORE not used in this section because values are specific to one volinfo_type */
+    case VOLINT_INFO_TYPE_BASE:
+
+#ifdef AFS_DEMAND_ATTACH_FS
+       /* see comment above where we set inUse bit */
+       if (hdr->needsSalvaged || 
+           (vp && VIsErrorState(V_attachState(vp)))) {
+           handle->volinfo_ptr.base->needsSalvaged = 1;
+       } else {
+           handle->volinfo_ptr.base->needsSalvaged = 0;
+       }
+#else
+       handle->volinfo_ptr.base->needsSalvaged = hdr->needsSalvaged;
+#endif
+       handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
+       handle->volinfo_ptr.base->spare0 = hdr->minquota;
+       handle->volinfo_ptr.base->spare1 = 
+           (long)hdr->weekUse[0] +
+           (long)hdr->weekUse[1] +
+           (long)hdr->weekUse[2] +
+           (long)hdr->weekUse[3] +
+           (long)hdr->weekUse[4] +
+           (long)hdr->weekUse[5] +
+           (long)hdr->weekUse[6];
+       handle->volinfo_ptr.base->flags = 0;
+       handle->volinfo_ptr.base->spare2 = hdr->volUpdateCounter;
+       handle->volinfo_ptr.base->spare3 = 0;
+       break;
+
+
+    case VOLINT_INFO_TYPE_EXT:
+       numStatBytes =
+           4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
+                (4 * VOLINT_STATS_NUM_TIME_FIELDS));
+
+       /*
+        * Copy out the stat fields in a single operation.
+        */
+       if ((now - hdr->dayUseDate) > OneDay) {
+           memset(&(handle->volinfo_ptr.ext->stat_reads[0]),
+                  0, numStatBytes);
+       } else {
+           memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
+                  (char *)&(hdr->stat_reads[0]), 
+                  numStatBytes);
        }
-       else {
-           strcpy(volname,"");
-           return 0;/*volname doesnot represent a volume*/
+       break;
+    }
+
+    return 0;
+}
+
+#ifdef AFS_DEMAND_ATTACH_FS
+
+/**
+ * get struct Volume out of the fileserver.
+ *
+ * @param[in] volumeId  volumeId for which we want state information
+ * @param[in] pname     partition name string
+ * @param[inout] vp     pointer to pointer to Volume object which 
+ *                      will be populated (see note)
+ *
+ * @return operation status
+ *   @retval 0         success
+ *   @retval non-zero  failure
+ *
+ * @note if FSYNC_VolOp fails in certain ways, *vp will be set to NULL
+ *
+ * @internal
+ */
+static int
+GetVolObject(afs_uint32 volumeId, char * pname, Volume ** vp)
+{
+    int code;
+    SYNC_response res;
+
+    res.hdr.response_len = sizeof(res.hdr);
+    res.payload.buf = *vp;
+    res.payload.len = sizeof(Volume);
+
+    code = FSYNC_VolOp(volumeId,
+                      pname,
+                      FSYNC_VOL_QUERY,
+                      0,
+                      &res);
+
+    if (code != SYNC_OK) {
+       switch (res.hdr.reason) {
+       case FSYNC_WRONG_PART:
+       case FSYNC_UNKNOWN_VOLID:
+           *vp = NULL;
+           code = SYNC_OK;
+           break;
        }
     }
-    else {strcpy(volname,"EOD"); return 0;/*end of directory */}
-    
+
+    return code;
+}
+
+#endif
+
+/**
+ * mode of volume list operation.
+ */
+typedef enum {
+    VOL_INFO_LIST_SINGLE,   /**< performing a single volume list op */
+    VOL_INFO_LIST_MULTIPLE  /**< performing a multi-volume list op */
+} vol_info_list_mode_t;
+
+/**
+ * abstract interface to populate wire-format volume metadata structures.
+ *
+ * @param[in]  partId    partition id
+ * @param[in]  volumeId  volume id
+ * @param[in]  pname     partition name
+ * @param[in]  volname   volume file name
+ * @param[in]  handle    handle to on-wire volume metadata object
+ * @param[in]  mode      listing mode
+ *
+ * @return operation status
+ *   @retval 0      success
+ *   @retval -2     DESTROY_ME flag is set
+ *   @retval -1     general failure; some data filled in
+ *   @retval -3     couldn't create vtrans; some data filled in
+ */
+static int
+GetVolInfo(afs_uint32 partId,
+          afs_uint32 volumeId,
+          char * pname, 
+          char * volname, 
+          volint_info_handle_t * handle,
+          vol_info_list_mode_t mode)
+{
+    int code = -1;
+    Error error;
+    struct volser_trans *ttc = NULL;
+    struct Volume *fill_tv, *tv = NULL;
+#ifdef AFS_DEMAND_ATTACH_FS
+    struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf; /* Create a structure, and a pointer to that structure */
+    SYNC_PROTO_BUF_DECL(fs_res_buf); /* Buffer for the pending_vol_op */
+    SYNC_response fs_res; /* Response handle for the pending_vol_op */
+    FSSYNC_VolOp_info pending_vol_op_res; /* Pending vol ops to full in volume */
+
+    /* Set up response handle for pending_vol_op */
+    fs_res.hdr.response_len = sizeof(fs_res.hdr);
+    fs_res.payload.buf = fs_res_buf;
+    fs_res.payload.len = SYNC_PROTO_MAX_LEN;
+#endif
+
+    ttc = NewTrans(volumeId, partId);
+    if (!ttc) {
+       code = -3;
+       VOLINT_INFO_STORE(handle, status, VOLSERVOLBUSY);
+       VOLINT_INFO_STORE(handle, volid, volumeId);
+       goto drop;
+    }
+
+    /* Get volume from volserver */
+    tv = VAttachVolumeByName_retry(&error, pname, volname, V_PEEK);
+    if (error) {
+       Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n", 
+           volumeId, pname, volname, error);
+       goto drop;
+    }
+
+    /*
+     * please note that destroyMe and needsSalvaged checks used to be ordered
+     * in the opposite manner for ListVolumes and XListVolumes.  I think it's
+     * more correct to check destroyMe before needsSalvaged.
+     *   -- tkeiser 11/28/2007
+     */
+
+    if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
+       switch (mode) {
+       case VOL_INFO_LIST_MULTIPLE:
+           code = -2;
+           goto drop;
+
+       case VOL_INFO_LIST_SINGLE:
+           Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n", 
+               volumeId, pname, volname);
+
+       default:
+           goto drop;
+       }
+    }
+
+    if (tv->header->diskstuff.needsSalvaged) {
+       /*this volume will be salvaged */
+       Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n", 
+           volumeId, pname, volname);
+    }
+
+#ifdef AFS_DEMAND_ATTACH_FS
+    /* If using DAFS, get volume from fsserver */
+    if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK || fs_tv == NULL) {
+
+       goto drop;
+    }
+
+    /* fs_tv is a shallow copy, must populate certain structures before passing along */
+    if (FSYNC_VolOp(volumeId, pname, FSYNC_VOL_QUERY_VOP, 0, &fs_res) == SYNC_OK) { 
+       /* If we if the pending vol op */
+       memcpy(&pending_vol_op_res, fs_res.payload.buf, sizeof(FSSYNC_VolOp_info));
+       fs_tv->pending_vol_op=&pending_vol_op_res;
+    } else {
+       fs_tv->pending_vol_op=NULL;
+    }
+
+    /* populate the header from the volserver copy */
+    fs_tv->header=tv->header;
+
+    /* When using DAFS, use the fs volume info, populated with required structures */
+    fill_tv = fs_tv;
+#else 
+    /* When not using DAFS, just use the local volume info */
+    fill_tv = tv;
+#endif
+
+    /* ok, we have all the data we need; fill in the on-wire struct */
+    code = FillVolInfo(fill_tv, handle);
+
+ drop:
+    if (code == -1) {
+       VOLINT_INFO_STORE(handle, status, 0);
+       strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
+       VOLINT_INFO_STORE(handle, volid, volumeId);
+    }
+    if (tv) {
+       VDetachVolume(&error, tv);
+       tv = NULL;
+       if (error) {
+           VOLINT_INFO_STORE(handle, status, 0);
+           strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
+           Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
+               volumeId, pname, volname);
+       }
+    }
+    if (ttc) {
+       DeleteTrans(ttc, 1);
+       ttc = NULL;
+    }
+    return code;
 }
 
+
 /*return the header information about the <volid> */
-afs_int32 SAFSVolListOneVolume (acid, partid, volumeId, volumeInfo)
-struct rx_call *acid;
-afs_int32 volumeId, partid;
-volEntries *volumeInfo;
+afs_int32
+SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,  
+                     afs_uint32 volumeId, volEntries *volumeInfo)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolListOneVolume (acid, partid, volumeId, volumeInfo);
-  osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
-  return code;
+    code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
+    osi_auditU(acid, VS_Lst1VolEvent, code, AUD_LONG, volumeId, AUD_END);
+    return code;
 }
 
-afs_int32 VolListOneVolume (acid, partid, volumeId, volumeInfo)
-struct rx_call *acid;
-afs_int32 volumeId, partid;
-volEntries *volumeInfo;
-{   volintInfo *pntr;
-    register struct Volume *tv;
-    struct DiskPartition *partP;
-    struct volser_trans *ttc;
+static afs_int32
+VolListOneVolume(struct rx_call *acid, afs_int32 partid, 
+                 afs_uint32 volumeId, volEntries *volumeInfo)
+{
+    volintInfo *pntr;
+    struct DiskPartition64 *partP;
     char pname[9], volname[20];
-    afs_int32 error = 0;
     DIR *dirp;
-    afs_int32 volid;
+    afs_uint32 volid;
     int found = 0;
-    unsigned int now;
+    int code;
+    volint_info_handle_t handle;
+
+    volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
+    if (!volumeInfo->volEntries_val)
+       return ENOMEM;
+    memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
 
-    volumeInfo->volEntries_val = (volintInfo *) malloc( sizeof(volintInfo));
     pntr = volumeInfo->volEntries_val;
     volumeInfo->volEntries_len = 1;
-    if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
-    if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
+    if (GetPartName(partid, pname))
+       return VOLSERILLEGAL_PARTITION;
+    if (!(partP = VGetPartition(pname, 0)))
+       return VOLSERILLEGAL_PARTITION;
     dirp = opendir(VPartitionPath(partP));
-    if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
-    strcpy(volname,"");
-    ttc = (struct volser_trans *) 0;   
-    tv = (Volume *) 0;                 /* volume not attached */
+    if (dirp == NULL)
+       return VOLSERILLEGAL_PARTITION;
 
-    while(strcmp(volname,"EOD") && !found){/*while there are more volumes in the partition */
+    strcpy(volname, "");
+
+    while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
 
-       if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
+       if (!strcmp(volname, "")) {     /* its not a volume, fetch next file */
            GetNextVol(dirp, volname, &volid);
-           continue; /*back to while loop */
+           continue;           /*back to while loop */
        }
-       
-       if(volid == volumeId) { /*copy other things too */
-           found = 1;
-           IOMGR_Poll(); /*make sure that the client doesnot time out*/
-           ttc = NewTrans(volid,partid);
-           if(!ttc){
-               pntr->status = VBUSY;
-               pntr->volid = volid;
-               goto drop;
-           }
-           tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
-           if(error) {
-               pntr->status = 0; /*things are messed up */
-               strcpy(pntr->name,volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n",volid,pname,volname,error);
-               goto drop;
-           }
-           if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
-               /*this volume will be salvaged */
-               pntr->status = 0;
-               strcpy(pntr->name,volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n",volid,volname);
-               goto drop;
-           }
 
-           if(tv->header->diskstuff.needsSalvaged){
-               /*this volume will be salvaged */
-               pntr->status = 0;
-               strcpy(pntr->name,volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid,volname);
-               goto drop;
-           }
-
-           /*read in the relevant info */
-           pntr->status = VOK ; /*its ok */
-           pntr->volid = tv->header->diskstuff.id;
-           strcpy(pntr->name,tv->header->diskstuff.name);
-           pntr->type = tv->header->diskstuff.type; /*if ro volume*/
-           pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
-           pntr->backupID = tv->header->diskstuff.backupId;
-           pntr->parentID = tv->header->diskstuff.parentId;
-           pntr->copyDate = tv->header->diskstuff.copyDate;
-           pntr->inUse = tv->header->diskstuff.inUse;
-           pntr->size = tv->header->diskstuff.diskused;
-           pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
-           pntr->destroyMe = tv->header->diskstuff.destroyMe;
-           pntr->maxquota = tv->header->diskstuff.maxquota;
-           pntr->filecount = tv->header->diskstuff.filecount;
-           now = FT_ApproxTime();
-           if (now - tv->header->diskstuff.dayUseDate > OneDay)
-                pntr->dayUse = 0;
-           else
-                pntr->dayUse = tv->header->diskstuff.dayUse;
-           pntr->creationDate = tv->header->diskstuff.creationDate;
-           pntr->accessDate = tv->header->diskstuff.accessDate;
-           pntr->updateDate = tv->header->diskstuff.updateDate;
-           pntr->backupDate = tv->header->diskstuff.backupDate;
-           pntr->spare0 = tv->header->diskstuff.minquota;
-           pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
-               (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
-               (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
-               (long) tv->header->diskstuff.weekUse[6];
-           pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
-           VDetachVolume(&error,tv);/*free the volume */
-           tv = (Volume *) 0;
-           if(error) {
-               pntr->status = 0; /*things are messed up */
-               strcpy(pntr->name,volname);
-               Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
-               goto drop;
-           }
+       if (volid == volumeId) {        /*copy other things too */
+           found = 1;
+           break;
        }
+
        GetNextVol(dirp, volname, &volid);
     }
-    drop:
-               if (tv) {
-           VDetachVolume(&error, tv);
-           tv = (Volume *) 0;
-       }
-        if(ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *) 0;
-       }
-        
+
+    if (found) {
+#ifndef AFS_PTHREAD_ENV
+       IOMGR_Poll();   /*make sure that the client does not time out */
+#endif
+
+       handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
+       handle.volinfo_ptr.base = volumeInfo->volEntries_val;
+       
+       code = GetVolInfo(partid, 
+                         volid, 
+                         pname, 
+                         volname,
+                         &handle,
+                         VOL_INFO_LIST_SINGLE);
+    }
+
     closedir(dirp);
-    if(found)return 0 ;
-    else return ENODEV;
+    return (found) ? 0 : ENODEV;
 }
 
 /*------------------------------------------------------------------------
@@ -1861,46 +2373,41 @@ volEntries *volumeInfo;
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-afs_int32 SAFSVolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
-    struct rx_call *a_rxCidP;
-    afs_int32 a_partID;
-    afs_int32 a_volID;
-    volXEntries *a_volumeXInfoP;
-{
-  afs_int32 code;
-
-  code = VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
-  osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
-  return code;
-}
-
-afs_int32 VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
-    struct rx_call *a_rxCidP;
-    afs_int32 a_partID;
-    afs_int32 a_volID;
-    volXEntries *a_volumeXInfoP;
-
-{ /*SAFSVolXListOneVolume*/
-
-    volintXInfo *xInfoP;                 /*Ptr to the extended vol info*/
-    register struct Volume *tv;                  /*Volume ptr*/
-    struct volser_trans *ttc;            /*Volume transaction ptr*/
-    struct DiskPartition *partP;         /*Ptr to partition */
-    char pname[9], volname[20];                  /*Partition, volume names*/
-    afs_int32 error;                     /*Error code*/
-    afs_int32 code;                              /*Return code*/
-    DIR *dirp;                           /*Partition directory ptr*/
-    afs_int32 currVolID;                         /*Current volume ID*/
-    int found = 0;                       /*Did we find the volume we need?*/
-    struct VolumeDiskData *volDiskDataP;  /*Ptr to on-disk volume data*/
-    int numStatBytes;                    /*Num stat bytes to copy per volume*/
-    unsigned int now;
+afs_int32
+SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID, 
+                     afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
+{
+    afs_int32 code;
+
+    code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
+    osi_auditU(a_rxCidP, VS_XLst1VlEvent, code, AUD_LONG, a_volID, AUD_END);
+    return code;
+}
+
+static afs_int32
+VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID, 
+                  afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
+{                              /*SAFSVolXListOneVolume */
+
+    volintXInfo *xInfoP;       /*Ptr to the extended vol info */
+    struct DiskPartition64 *partP;     /*Ptr to partition */
+    char pname[9], volname[20];        /*Partition, volume names */
+    DIR *dirp;                 /*Partition directory ptr */
+    afs_uint32 currVolID;              /*Current volume ID */
+    int found = 0;             /*Did we find the volume we need? */
+    int code;
+    volint_info_handle_t handle;
 
     /*
      * Set up our pointers for action, marking our structure to hold exactly
      * one entry.  Also, assume we'll fail in our quest.
      */
-    a_volumeXInfoP->volXEntries_val = (volintXInfo *) malloc(sizeof(volintXInfo));
+    a_volumeXInfoP->volXEntries_val =
+       (volintXInfo *) malloc(sizeof(volintXInfo));
+    if (!a_volumeXInfoP->volXEntries_val)
+       return ENOMEM;
+    memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
+
     xInfoP = a_volumeXInfoP->volXEntries_val;
     a_volumeXInfoP->volXEntries_len = 1;
     code = ENODEV;
@@ -1909,38 +2416,35 @@ afs_int32 VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
      * If the partition name we've been given is bad, bogue out.
      */
     if (GetPartName(a_partID, pname))
-       return(VOLSERILLEGAL_PARTITION);
+       return (VOLSERILLEGAL_PARTITION);
 
     /*
      * Open the directory representing the given AFS parttion.  If we can't
      * do that, we lose.
      */
-    if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
+    if (!(partP = VGetPartition(pname, 0)))
+       return VOLSERILLEGAL_PARTITION;
     dirp = opendir(VPartitionPath(partP));
     if (dirp == NULL)
-       return(VOLSERILLEGAL_PARTITION);
+       return (VOLSERILLEGAL_PARTITION);
+
+    strcpy(volname, "");
 
     /*
      * Sweep through the partition directory, looking for the desired entry.
      * First, of course, figure out how many stat bytes to copy out of each
      * volume.
      */
-    numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
-                     (4*VOLINT_STATS_NUM_TIME_FIELDS));
-    strcpy(volname, "");
-    ttc = (struct volser_trans *)0;    /*No transaction yet*/
-    tv = (Volume *)0;                  /*Volume not yet attached*/
-
-    while (strcmp(volname,"EOD") && !found) {
+    while (strcmp(volname, "EOD") && !found) {
        /*
         * If this is not a volume, move on to the next entry in the
         * partition's directory.
         */
-       if (!strcmp(volname,"")) {
+       if (!strcmp(volname, "")) {
            GetNextVol(dirp, volname, &currVolID);
            continue;
        }
-       
+
        if (currVolID == a_volID) {
            /*
             * We found the volume entry we're interested.  Pull out the
@@ -1948,293 +2452,135 @@ afs_int32 VolXListOneVolume (a_rxCidP, a_partID, a_volID, a_volumeXInfoP)
             * doesn't time out) and to set up a transaction on the volume.
             */
            found = 1;
-           IOMGR_Poll();
-           ttc = NewTrans(currVolID, a_partID);
-           if (!ttc) {
-               /*
-                * Couldn't get a transaction on this volume; let our caller
-                * know it's busy.
-                */
-               xInfoP->status = VBUSY;
-               xInfoP->volid = currVolID;
-               goto drop;
-           }
+           break;
+       }                       /*Found desired volume */
 
-           /*
-            * Attach the volume, give up on the volume if we can't.
-            */
-           tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
-           if (error) {
-               xInfoP->status = 0; /*things are messed up */
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = currVolID;
-               Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
-                   currVolID);
-               goto drop;
-           }
-
-           /*
-            * Also bag out on this volume if it's been marked as needing a
-            * salvage or to-be-destroyed.
-            */
-           volDiskDataP = &(tv->header->diskstuff);
-           if (volDiskDataP->destroyMe == DESTROY_ME) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = currVolID;
-               Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
-               goto drop;
-           }
-
-           if (volDiskDataP->needsSalvaged) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = currVolID;
-               Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n",
-                   currVolID);
-               goto drop;
-           }
+       GetNextVol(dirp, volname, &currVolID);
+    }
 
-           /*
-            * Pull out the desired info and stuff it into the area we'll be
-            * returning to our caller.
-            */
-           strcpy(xInfoP->name,volDiskDataP->name);
-           xInfoP->volid        = volDiskDataP->id;
-           xInfoP->type         = volDiskDataP->type;
-           xInfoP->backupID     = volDiskDataP->backupId;
-           xInfoP->parentID     = volDiskDataP->parentId;
-           xInfoP->cloneID      = volDiskDataP->cloneId;
-           xInfoP->status       = VOK;
-           xInfoP->copyDate     = volDiskDataP->copyDate;
-           xInfoP->inUse        = volDiskDataP->inUse;
-           xInfoP->creationDate = volDiskDataP->creationDate;
-           xInfoP->accessDate   = volDiskDataP->accessDate;
-           xInfoP->updateDate   = volDiskDataP->updateDate;
-           xInfoP->backupDate   = volDiskDataP->backupDate;
-           now = FT_ApproxTime();
-           if (now - volDiskDataP->dayUseDate > OneDay)
-              xInfoP->dayUse    = 0;
-           else
-              xInfoP->dayUse    = volDiskDataP->dayUse;
-           xInfoP->filecount    = volDiskDataP->filecount;
-           xInfoP->maxquota     = volDiskDataP->maxquota;
-           xInfoP->size         = volDiskDataP->diskused;
+    if (found) {
+#ifndef AFS_PTHREAD_ENV
+       IOMGR_Poll();
+#endif
 
-           /*
-            * Copy out the stat fields in a single operation.
-            */
-           memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
+       handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
+       handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
 
-           /*
-            * We're done copying.  Detach the volume and iterate (at this
-            * point, since we found our volume, we'll then drop out of the
-            * loop).
-            */
-           VDetachVolume(&error, tv);
-           tv = (Volume *)0;
-           if (error) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
-                   volname);
-               goto drop;
-           }
+       code = GetVolInfo(a_partID,
+                         a_volID,
+                         pname,
+                         volname,
+                         &handle,
+                         VOL_INFO_LIST_SINGLE);
 
-           /*
-            * At this point, we're golden.
-            */
-           code = 0;
-       } /*Found desired volume*/
-       GetNextVol(dirp, volname, &currVolID);
     }
 
     /*
-     * Drop the transaction we have for this volume.
-     */
-    drop:
-               if (tv) {
-           VDetachVolume(&error, tv);
-           tv = (Volume *)0;
-       }
-        if (ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *)0;
-       }
-
-    /*
      * Clean up before going to dinner: close the partition directory,
      * return the proper value.
      */
     closedir(dirp);
-    return(code);
-
-} /*SAFSVolXListOneVolume*/
+    return (found) ? 0 : ENODEV;
+}                              /*SAFSVolXListOneVolume */
 
 /*returns all the volumes on partition partid. If flags = 1 then all the 
 * relevant info about the volumes  is also returned */
-afs_int32 SAFSVolListVolumes (acid, partid, flags, volumeInfo)
-struct rx_call *acid;
-afs_int32 flags, partid;
-volEntries *volumeInfo;
+afs_int32
+SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags, 
+                  volEntries *volumeInfo)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolListVolumes (acid, partid, flags, volumeInfo);
-  osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
-  return code;
+    code = VolListVolumes(acid, partid, flags, volumeInfo);
+    osi_auditU(acid, VS_ListVolEvent, code, AUD_END);
+    return code;
 }
 
-afs_int32 VolListVolumes (acid, partid, flags, volumeInfo)
-struct rx_call *acid;
-afs_int32 flags, partid;
-volEntries *volumeInfo;
-{   volintInfo *pntr;
-    register struct Volume *tv;
-    struct DiskPartition *partP;
-    struct volser_trans *ttc;
-    afs_int32 allocSize = 1000;/*to be changed to a larger figure */
+static afs_int32
+VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags, 
+                  volEntries *volumeInfo)
+{
+    volintInfo *pntr;
+    struct DiskPartition64 *partP;
+    afs_int32 allocSize = 1000;        /*to be changed to a larger figure */
     char pname[9], volname[20];
-    afs_int32 error = 0;
     DIR *dirp;
-    afs_int32 volid;
-    unsigned int now;
+    afs_uint32 volid;
+    int code;
+    volint_info_handle_t handle;
+
+    volumeInfo->volEntries_val =
+       (volintInfo *) malloc(allocSize * sizeof(volintInfo));
+    if (!volumeInfo->volEntries_val)
+       return ENOMEM;
+    memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
 
-    volumeInfo->volEntries_val = (volintInfo *) malloc(allocSize * sizeof(volintInfo));
     pntr = volumeInfo->volEntries_val;
     volumeInfo->volEntries_len = 0;
-    if(GetPartName(partid, pname)) return VOLSERILLEGAL_PARTITION;
-    if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
+    if (GetPartName(partid, pname))
+       return VOLSERILLEGAL_PARTITION;
+    if (!(partP = VGetPartition(pname, 0)))
+       return VOLSERILLEGAL_PARTITION;
     dirp = opendir(VPartitionPath(partP));
-    if(dirp == NULL) return VOLSERILLEGAL_PARTITION;
-    strcpy(volname,"");
-    while(strcmp(volname,"EOD")){/*while there are more partitions in the partition */
-       ttc = (struct volser_trans *) 0;        /* new one for each pass */
-       tv = (Volume *) 0;                      /* volume not attached */
+    if (dirp == NULL)
+       return VOLSERILLEGAL_PARTITION;
+    strcpy(volname, "");
 
-       if(!strcmp(volname,"")) {/* its not a volume, fetch next file */
+    while (strcmp(volname, "EOD")) {   /*while there are more partitions in the partition */
+
+       if (!strcmp(volname, "")) {     /* its not a volume, fetch next file */
            GetNextVol(dirp, volname, &volid);
-           continue; /*back to while loop */
+           continue;           /*back to while loop */
        }
-       
-       if(flags) { /*copy other things too */
-           IOMGR_Poll(); /*make sure that the client doesnot time out*/
-           ttc = NewTrans(volid,partid);
-           if(!ttc){
-               pntr->status = VBUSY;
-               pntr->volid = volid;
-               goto drop;
-           }
-           tv = VAttachVolumeByName(&error, pname, volname,V_READONLY);
-           if(error) {
-               pntr->status = 0; /*things are messed up */
-               strcpy(pntr->name,volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n",volid,volname,error);
-               goto drop;
-           }
-           if(tv->header->diskstuff.needsSalvaged){
-               /*this volume will be salvaged */
-               pntr->status = 0;
-               strcpy(pntr->name,volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n",volid, volname);
-               goto drop;
-           }
 
-           if(tv->header->diskstuff.destroyMe == DESTROY_ME) {
-               /*this volume will be salvaged */
+       if (flags) {            /*copy other things too */
+#ifndef AFS_PTHREAD_ENV
+           IOMGR_Poll();       /*make sure that the client does not time out */
+#endif
+
+           handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
+           handle.volinfo_ptr.base = pntr;
+
+
+           code = GetVolInfo(partid,
+                             volid,
+                             pname,
+                             volname,
+                             &handle,
+                             VOL_INFO_LIST_MULTIPLE);
+           if (code == -2) { /* DESTROY_ME flag set */
                goto drop2;
            }
-           /*read in the relevant info */
-           pntr->status = VOK ; /*its ok */
-           pntr->volid = tv->header->diskstuff.id;
-           strcpy(pntr->name,tv->header->diskstuff.name);
-           pntr->type = tv->header->diskstuff.type; /*if ro volume*/
-           pntr->cloneID = tv->header->diskstuff.cloneId; /*if rw volume*/
-           pntr->backupID = tv->header->diskstuff.backupId;
-           pntr->parentID = tv->header->diskstuff.parentId;
-           pntr->copyDate = tv->header->diskstuff.copyDate;
-           pntr->inUse = tv->header->diskstuff.inUse;
-           pntr->size = tv->header->diskstuff.diskused;
-           pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
-           pntr->maxquota = tv->header->diskstuff.maxquota;
-           pntr->filecount = tv->header->diskstuff.filecount;
-           now = FT_ApproxTime();
-           if (now - tv->header->diskstuff.dayUseDate > OneDay)
-                pntr->dayUse = 0;
-           else
-                pntr->dayUse = tv->header->diskstuff.dayUse;
-           pntr->creationDate = tv->header->diskstuff.creationDate;
-           pntr->accessDate = tv->header->diskstuff.accessDate;
-           pntr->updateDate = tv->header->diskstuff.updateDate;
-           pntr->backupDate = tv->header->diskstuff.backupDate;
-           pntr->spare0 = tv->header->diskstuff.minquota;
-           pntr->spare1 = (long) tv->header->diskstuff.weekUse[0] + (long) tv->header->diskstuff.weekUse[1] +
-               (long) tv->header->diskstuff.weekUse[2] + (long) tv->header->diskstuff.weekUse[3] +
-               (long) tv->header->diskstuff.weekUse[4] + (long) tv->header->diskstuff.weekUse[5] +
-               (long) tv->header->diskstuff.weekUse[6];
-           pntr->flags = pntr->spare2 = pntr->spare3 = (long) 0;
-           VDetachVolume(&error,tv);/*free the volume */
-           tv = (Volume *) 0;
-           if(error) {
-               pntr->status = 0; /*things are messed up */
-               strcpy(pntr->name,volname);
-               Log("1 Volser: ListVolumes: Could not detach volume %s\n",volname);
-               goto drop;
-           }
-       }else{
+       } else {
            pntr->volid = volid;
-           /*just volids are needed*/
+           /*just volids are needed */
        }
 
-      drop:
-       if(ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *) 0;
-       }
-        pntr++;
+       pntr++;
        volumeInfo->volEntries_len += 1;
-       if((allocSize - volumeInfo->volEntries_len) < 5) {
+       if ((allocSize - volumeInfo->volEntries_len) < 5) {
            /*running out of space, allocate more space */
-           allocSize = (allocSize *3)/2;
-           pntr = (volintInfo *) realloc((char *) volumeInfo->volEntries_val,
-                                         allocSize * sizeof(volintInfo));
-           if(pntr == NULL) {
-               if (tv) {
-                   VDetachVolume(&error, tv);
-                   tv = (Volume *) 0;
-               }
-               if(ttc) {
-                   DeleteTrans(ttc);
-                   ttc = (struct volser_trans *) 0;
-               }
-               closedir(dirp);
+           allocSize = (allocSize * 3) / 2;
+           pntr =
+               (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
+                                      allocSize * sizeof(volintInfo));
+           if (pntr == NULL) {
+               closedir(dirp); 
                return VOLSERNO_MEMORY;
            }
-           volumeInfo->volEntries_val = pntr; /* point to new block */
+           volumeInfo->volEntries_val = pntr;  /* point to new block */
            /* set pntr to the right position */
            pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
-           
+
        }
-       
+
       drop2:
-       if (tv) {
-           VDetachVolume(&error, tv);
-           tv = (Volume *) 0;
-       }
-        if(ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *) 0;
-       }
-        GetNextVol(dirp, volname, &volid);
-       
+       GetNextVol(dirp, volname, &volid);
+
     }
+
     closedir(dirp);
-    if (ttc)
-       DeleteTrans(ttc);
-    
-    return 0 ;
+    return 0;
 }
 
 /*------------------------------------------------------------------------
@@ -2264,39 +2610,30 @@ volEntries *volumeInfo;
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-afs_int32 SAFSVolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
-    struct rx_call *a_rxCidP;
-    afs_int32 a_partID;
-    afs_int32 a_flags;
-    volXEntries *a_volumeXInfoP;
+afs_int32
+SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
+                   afs_int32 a_flags, volXEntries *a_volumeXInfoP)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
-  osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
-  return code;
+    code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
+    osi_auditU(a_rxCidP, VS_XLstVolEvent, code, AUD_END);
+    return code;
 }
 
-afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
-    struct rx_call *a_rxCidP;
-    afs_int32 a_partID;
-    afs_int32 a_flags;
-    volXEntries *a_volumeXInfoP;
-
-{ /*SAFSVolXListVolumes*/
-
-    volintXInfo *xInfoP;                 /*Ptr to the extended vol info*/
-    register struct Volume *tv;                  /*Volume ptr*/
-    struct DiskPartition *partP;         /*Ptr to partition*/
-    struct volser_trans *ttc;            /*Volume transaction ptr*/
-    afs_int32 allocSize = 1000;                  /*To be changed to a larger figure */
-    char pname[9], volname[20];                  /*Partition, volume names*/
-    afs_int32 error = 0;                         /*Return code*/
-    DIR *dirp;                           /*Partition directory ptr*/
-    afs_int32 volid;                             /*Current volume ID*/
-    struct VolumeDiskData *volDiskDataP;  /*Ptr to on-disk volume data*/
-    int numStatBytes;                    /*Num stat bytes to copy per volume*/
-    unsigned int now;
+static afs_int32
+VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
+                   afs_int32 a_flags, volXEntries *a_volumeXInfoP)
+{                              /*SAFSVolXListVolumes */
+
+    volintXInfo *xInfoP;       /*Ptr to the extended vol info */
+    struct DiskPartition64 *partP;     /*Ptr to partition */
+    afs_int32 allocSize = 1000;        /*To be changed to a larger figure */
+    char pname[9], volname[20];        /*Partition, volume names */
+    DIR *dirp;                 /*Partition directory ptr */
+    afs_uint32 volid;          /*Current volume ID */
+    int code;
+    volint_info_handle_t handle;
 
     /*
      * Allocate a large array of extended volume info structures, then
@@ -2304,6 +2641,10 @@ afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
      */
     a_volumeXInfoP->volXEntries_val =
        (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
+    if (!a_volumeXInfoP->volXEntries_val)
+       return ENOMEM;
+    memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
+
     xInfoP = a_volumeXInfoP->volXEntries_val;
     a_volumeXInfoP->volXEntries_len = 0;
 
@@ -2311,33 +2652,30 @@ afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
      * If the partition name we've been given is bad, bogue out.
      */
     if (GetPartName(a_partID, pname))
-       return(VOLSERILLEGAL_PARTITION);
+       return (VOLSERILLEGAL_PARTITION);
 
     /*
      * Open the directory representing the given AFS parttion.  If we can't
      * do that, we lose.
      */
-    if (!(partP = VGetPartition(pname, 0))) return VOLSERILLEGAL_PARTITION;
+    if (!(partP = VGetPartition(pname, 0)))
+       return VOLSERILLEGAL_PARTITION;
     dirp = opendir(VPartitionPath(partP));
     if (dirp == NULL)
        return (VOLSERILLEGAL_PARTITION);
+    strcpy(volname, "");
 
     /*
      * Sweep through the partition directory, acting on each entry.  First,
      * of course, figure out how many stat bytes to copy out of each volume.
      */
-    numStatBytes = 4*((2*VOLINT_STATS_NUM_RWINFO_FIELDS) +
-                     (4*VOLINT_STATS_NUM_TIME_FIELDS));
-    strcpy(volname,"");
     while (strcmp(volname, "EOD")) {
-       ttc = (struct volser_trans *)0; /*New one for each pass*/
-       tv = (Volume *)0;               /*Volume not yet attached*/
 
        /*
         * If this is not a volume, move on to the next entry in the
         * partition's directory.
         */
-       if(!strcmp(volname,"")) {
+       if (!strcmp(volname, "")) {
            GetNextVol(dirp, volname, &volid);
            continue;
        }
@@ -2347,135 +2685,49 @@ afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
             * Full info about the volume desired.  Poll to make sure the
             * client doesn't time out, then start up a new transaction.
             */
+#ifndef AFS_PTHREAD_ENV
            IOMGR_Poll();
-           ttc = NewTrans(volid,a_partID);
-           if (!ttc) {
-               /*
-                * Couldn't get a transaction on this volume; let our caller
-                * know it's busy.
-                */
-               xInfoP->status = VBUSY;
-               xInfoP->volid = volid;
-               goto drop;
-           }
-
-           /*
-            * Attach the volume, give up on this volume if we can't.
-            */
-           tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
-           if (error) {
-               xInfoP->status = 0; /*things are messed up */
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = volid;
-               Log("1 Volser: XListVolumes: Could not attach volume %u\n",
-                   volid);
-               goto drop;
-           }
+#endif
 
-           /*
-            * Also bag out on this volume if it's been marked as needing a
-            * salvage or to-be-destroyed.
-            */
-           volDiskDataP = &(tv->header->diskstuff);
-           if (volDiskDataP->needsSalvaged) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = volid;
-               Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n",
-                   volid);
-               goto drop;
-           }
+           handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
+           handle.volinfo_ptr.ext = xInfoP;
 
-           if (volDiskDataP->destroyMe == DESTROY_ME)
+           code = GetVolInfo(a_partID,
+                             volid,
+                             pname,
+                             volname,
+                             &handle,
+                             VOL_INFO_LIST_MULTIPLE);
+           if (code == -2) { /* DESTROY_ME flag set */
                goto drop2;
-
-           /*
-            * Pull out the desired info and stuff it into the area we'll be
-            * returning to our caller.
-            */
-           strcpy(xInfoP->name,volDiskDataP->name);
-           xInfoP->volid        = volDiskDataP->id;
-           xInfoP->type         = volDiskDataP->type;
-           xInfoP->backupID     = volDiskDataP->backupId;
-           xInfoP->parentID     = volDiskDataP->parentId;
-           xInfoP->cloneID      = volDiskDataP->cloneId;
-           xInfoP->status       = VOK;
-           xInfoP->copyDate     = volDiskDataP->copyDate;
-           xInfoP->inUse        = volDiskDataP->inUse;
-           xInfoP->creationDate = volDiskDataP->creationDate;
-           xInfoP->accessDate   = volDiskDataP->accessDate;
-           xInfoP->updateDate   = volDiskDataP->updateDate;
-           xInfoP->backupDate   = volDiskDataP->backupDate;
-           now = FT_ApproxTime();
-           if (now - volDiskDataP->dayUseDate > OneDay)
-              xInfoP->dayUse    = 0;
-           else
-              xInfoP->dayUse    = volDiskDataP->dayUse;
-           xInfoP->filecount    = volDiskDataP->filecount;
-           xInfoP->maxquota     = volDiskDataP->maxquota;
-           xInfoP->size         = volDiskDataP->diskused;
-
-           /*
-            * Copy out the stat fields in a single operation.
-            */
-           memcpy((char *)&(xInfoP->stat_reads[0]), (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
-
-           /*
-            * We're done copying.  Detach the volume and iterate.
-            */
-           VDetachVolume(&error, tv);
-           tv = (Volume *) 0;
-           if (error) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               Log("1 Volser: XListVolumes: Could not detach volume %s\n",
-                   volname);
-               goto drop;
            }
-       } /*Full contents desired*/
-       else
+       } else {
            /*
             * Just volume IDs are needed.
             */
            xInfoP->volid = volid;
-
-      drop:
-       /*
-        * Drop the transaction we have for this volume.
-        */
-       if(ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *) 0;
        }
 
        /*
         * Bump the pointer in the data area we're building, along with
         * the count of the number of entries it contains.
         */
-        xInfoP++;
+       xInfoP++;
        (a_volumeXInfoP->volXEntries_len)++;
        if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
            /*
             * We're running out of space in the area we've built.  Grow it.
             */
-           allocSize = (allocSize * 3)/2;
+           allocSize = (allocSize * 3) / 2;
            xInfoP = (volintXInfo *)
-               realloc((char *) a_volumeXInfoP->volXEntries_val,
+               realloc((char *)a_volumeXInfoP->volXEntries_val,
                        (allocSize * sizeof(volintXInfo)));
            if (xInfoP == NULL) {
                /*
                 * Bummer, no memory. Bag it, tell our caller what went wrong.
                 */
-               if (tv) {
-                   VDetachVolume(&error, tv);
-                   tv = (Volume *) 0;
-               }
-               if (ttc) {
-                   DeleteTrans(ttc);
-                   ttc = (struct volser_trans *) 0;
-               }
                closedir(dirp);
-               return(VOLSERNO_MEMORY);
+               return (VOLSERNO_MEMORY);
            }
 
            /*
@@ -2484,64 +2736,57 @@ afs_int32 VolXListVolumes (a_rxCidP, a_partID, a_flags, a_volumeXInfoP)
             * the new block.
             */
            a_volumeXInfoP->volXEntries_val = xInfoP;
-           xInfoP = a_volumeXInfoP->volXEntries_val +
-                    a_volumeXInfoP->volXEntries_len;
-       } /*Need more space*/
+           xInfoP =
+               a_volumeXInfoP->volXEntries_val +
+               a_volumeXInfoP->volXEntries_len;
+       }
 
       drop2:
-       /*
-        * Detach our current volume and the transaction on it, then move on
-        * to the next volume in the partition directory.
-        */
-       if (tv) {
-           VDetachVolume(&error, tv);
-           tv = (Volume *) 0;
-       }
-        if (ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *) 0;
-       }
-        GetNextVol(dirp, volname, &volid);
-    } /*Sweep through the partition directory*/
+       GetNextVol(dirp, volname, &volid);
+    }                          /*Sweep through the partition directory */
 
     /*
      * We've examined all entries in the partition directory.  Close it,
      * delete our transaction (if any), and go home happy.
      */
     closedir(dirp);
-    if (ttc)
-       DeleteTrans(ttc);
-    return(0);
+    return (0);
 
-} /*SAFSVolXListVolumes*/
+}                              /*SAFSVolXListVolumes */
 
 /*this call is used to monitor the status of volser for debugging purposes.
  *information about all the active transactions is returned in transInfo*/
-afs_int32 SAFSVolMonitor (acid,transInfo)
-  struct rx_call *acid;
-  transDebugEntries *transInfo;
+afs_int32
+SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolMonitor (acid,transInfo);
-  osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
-  return code;
+    code = VolMonitor(acid, transInfo);
+    osi_auditU(acid, VS_MonitorEvent, code, AUD_END);
+    return code;
 }
 
-afs_int32 VolMonitor (acid,transInfo)
-     struct rx_call *acid;
-     transDebugEntries *transInfo;
+static afs_int32
+VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
 {
     transDebugInfo *pntr;
     afs_int32 allocSize = 50;
-    struct volser_trans *tt, *allTrans;
+    struct volser_trans *tt, *nt, *allTrans;
 
-    transInfo->transDebugEntries_val = (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
+    transInfo->transDebugEntries_val =
+       (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
+    if (!transInfo->transDebugEntries_val)
+       return ENOMEM;
     pntr = transInfo->transDebugEntries_val;
     transInfo->transDebugEntries_len = 0;
+
+    VTRANS_LOCK;
     allTrans = TransList();
-    if(allTrans == (struct volser_trans *)0) return 0;/*no active transactions */
-    for(tt=allTrans;tt;tt=tt->next){/*copy relevant info into pntr */
+    if (allTrans == (struct volser_trans *)0)
+       goto done;              /*no active transactions */
+    for (tt = allTrans; tt; tt = nt) { /*copy relevant info into pntr */
+       nt = tt->next;
+        VTRANS_OBJ_LOCK(tt);
        pntr->tid = tt->tid;
        pntr->time = tt->time;
        pntr->creationTime = tt->creationTime;
@@ -2551,162 +2796,352 @@ afs_int32 VolMonitor (acid,transInfo)
        pntr->iflags = tt->iflags;
        pntr->vflags = tt->vflags;
        pntr->tflags = tt->tflags;
-       strcpy(pntr->lastProcName,tt->lastProcName);
+       strcpy(pntr->lastProcName, tt->lastProcName);
        pntr->callValid = 0;
-       if(tt->rxCallPtr) { /*record call related info */
+       if (tt->rxCallPtr) {    /*record call related info */
            pntr->callValid = 1;
            pntr->readNext = tt->rxCallPtr->rnext;
            pntr->transmitNext = tt->rxCallPtr->tnext;
            pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
            pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
        }
+        VTRANS_OBJ_UNLOCK(tt);
        pntr++;
        transInfo->transDebugEntries_len += 1;
-       if((allocSize - transInfo->transDebugEntries_len) < 5) {/*alloc some more space */
-           allocSize = (allocSize *3)/2;
-           pntr  = (transDebugInfo *) realloc((char *) transInfo->transDebugEntries_val,allocSize * sizeof(transDebugInfo));
+       if ((allocSize - transInfo->transDebugEntries_len) < 5) {       /*alloc some more space */
+           allocSize = (allocSize * 3) / 2;
+           pntr =
+               (transDebugInfo *) realloc((char *)transInfo->
+                                          transDebugEntries_val,
+                                          allocSize *
+                                          sizeof(transDebugInfo));
            transInfo->transDebugEntries_val = pntr;
-           pntr = transInfo->transDebugEntries_val + transInfo->transDebugEntries_len;
-           /*set pntr to right position*/
+           pntr =
+               transInfo->transDebugEntries_val +
+               transInfo->transDebugEntries_len;
+           /*set pntr to right position */
        }
-           
+
     }
-    
+done:
+    VTRANS_UNLOCK;
+
     return 0;
 }
 
-afs_int32 SAFSVolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
-  struct rx_call *acid;
-  afs_int32 type, pId, cloneId, backupId, atid;
-  char name[];
+afs_int32
+SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
+                  afs_int32 type, afs_uint32 pId, afs_uint32 cloneId,
+                  afs_uint32 backupId)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId);
-  osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, 
-                                          AUD_STR,  name,
-                                         AUD_STR,  type,
-                                          AUD_LONG, pId,
-                                         AUD_LONG, cloneId, 
-                                         AUD_LONG, backupId, AUD_END);
-  return code;
+    code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
+    osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
+              AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
+              backupId, AUD_END);
+    return code;
 }
 
-afs_int32 VolSetIdsTypes (acid,atid,name, type, pId, cloneId, backupId)
-     struct rx_call *acid;
-     afs_int32 type, pId, cloneId, backupId, atid;
-     char name[];
+static afs_int32
+VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
+              afs_int32 type, afs_uint32 pId, afs_uint32 cloneId,
+              afs_uint32 backupId)
 {
     struct Volume *tv;
-    afs_int32 error = 0;
-    register struct volser_trans *tt; 
+    Error error = 0;
+    register struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
-    if (strlen(name)>31) return VOLSERBADNAME;
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
+    if (strlen(name) > 31)
+       return VOLSERBADNAME;
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
     /* find the trans */
     tt = FindTrans(atid);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolSetIds: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"SetIdsTypes");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetIdsTypes");
     tv = tt->volume;
-   
+
     V_type(tv) = type;
     V_backupId(tv) = backupId;
     V_cloneId(tv) = cloneId;
     V_parentId(tv) = pId;
-    strcpy((&V_disk(tv))->name,name);
+    strcpy((&V_disk(tv))->name, name);
     VUpdateVolume(&error, tv);
     if (error) {
-        Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
-        LogError(error);
+       Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
+       LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
-    
+    TClearRxCall(tt);
+    if (TRELE(tt) && !error)
+       return VOLSERTRELE_ERROR;
+
     return error;
-fail:
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
+  fail:
+    TClearRxCall(tt);
+    if (TRELE(tt) && !error)
+       return VOLSERTRELE_ERROR;
     return error;
 }
 
-afs_int32 SAFSVolSetDate (acid,atid,cdate)
-     struct rx_call *acid;
-     afs_int32 atid, cdate;
+afs_int32
+SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
 {
-  afs_int32 code;
+    afs_int32 code;
 
-  code = VolSetDate (acid,atid,cdate);
-  osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate, AUD_END);
-  return code;
+    code = VolSetDate(acid, atid, cdate);
+    osi_auditU(acid, VS_SetDateEvent, code, AUD_LONG, atid, AUD_LONG, cdate,
+              AUD_END);
+    return code;
 }
 
-afs_int32 VolSetDate (acid,atid,cdate)
-     struct rx_call *acid;
-     afs_int32 atid, cdate;
+static afs_int32
+VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
 {
     struct Volume *tv;
-    afs_int32 error = 0;
-    register struct volser_trans *tt; 
+    Error error = 0;
+    register struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;/*not a super user*/
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
     /* find the trans */
     tt = FindTrans(atid);
-    if (!tt) return ENOENT;
+    if (!tt)
+       return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: VolSetDate: volume %u has been deleted \n",tt->volid);
+       Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName,"SetDate");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetDate");
     tv = tt->volume;
-   
-    V_creationDate(tv) = cdate;   
+
+    V_creationDate(tv) = cdate;
     VUpdateVolume(&error, tv);
     if (error) {
-        Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
-        LogError(error);
+       Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
+       LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
-    
+    TClearRxCall(tt);
+    if (TRELE(tt) && !error)
+       return VOLSERTRELE_ERROR;
+
     return error;
-fail:
-    tt->rxCallPtr = (struct rx_call *)0;
-    if(TRELE(tt) && !error) return VOLSERTRELE_ERROR;
+  fail:
+    TClearRxCall(tt);
+    if (TRELE(tt) && !error)
+       return VOLSERTRELE_ERROR;
     return error;
 }
 
+afs_int32
+SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
+                          afs_uint32 volumeId)
+{
+#ifdef AFS_NT40_ENV
+    return EXDEV;
+#else
+    char caller[MAXKTCNAMELEN];
+    DIR *dirp;
+    register struct volser_trans *ttc;
+    char pname[16], volname[20];
+    struct DiskPartition64 *partP;
+    afs_int32 ret = ENODEV;
+    afs_uint32 volid;
+
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
+    if (GetPartName(partId, pname))
+        return VOLSERILLEGAL_PARTITION;
+    if (!(partP = VGetPartition(pname, 0)))
+        return VOLSERILLEGAL_PARTITION;
+    dirp = opendir(VPartitionPath(partP));
+    if (dirp == NULL)
+       return VOLSERILLEGAL_PARTITION;
+    strcpy(volname, "");
+    ttc = (struct volser_trans *)0;
+
+    while (strcmp(volname, "EOD")) {
+       if (!strcmp(volname, "")) {     /* its not a volume, fetch next file */
+            GetNextVol(dirp, volname, &volid);
+            continue;           /*back to while loop */
+        }
+       
+       if (volid == volumeId) {        /*copy other things too */
+#ifndef AFS_PTHREAD_ENV
+            IOMGR_Poll();       /*make sure that the client doesnot time out */
+#endif
+            ttc = NewTrans(volumeId, partId);
+            if (!ttc) {
+               return VOLSERVOLBUSY;
+            }
+#ifdef AFS_NAMEI_ENV
+           ret = namei_ConvertROtoRWvolume(pname, volumeId);
+#else
+           ret = inode_ConvertROtoRWvolume(pname, volumeId);
+#endif
+           break;
+       }
+       GetNextVol(dirp, volname, &volid);
+    }
+    
+    if (ttc) {
+        DeleteTrans(ttc, 1);
+        ttc = (struct volser_trans *)0;
+    }
+    
+    closedir(dirp);
+    return ret;
+#endif
+}
+
+afs_int32
+SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
+              register struct volintSize *size)
+{
+    int code = 0;
+    register struct volser_trans *tt;
+    char caller[MAXKTCNAMELEN];
+
+    if (!afsconf_SuperUser(tdir, acid, caller))
+       return VOLSERBAD_ACCESS;        /*not a super user */
+    tt = FindTrans(fromTrans);
+    if (!tt)
+       return ENOENT;
+    if (tt->vflags & VTDeleted) {
+       TRELE(tt);
+       return ENOENT;
+    }
+    TSetRxCall(tt, acid, "GetSize");
+    code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size);        /* measure volume's data */
+    TClearRxCall(tt);
+    if (TRELE(tt))
+       return VOLSERTRELE_ERROR;
+
+/*    osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);  */
+    return code;
+}
+
+afs_int32
+SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
+                  afs_uint32 where, afs_int32 verbose)
+{
+#if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
+    Error code, code2;
+    Volume *vol=0, *newvol=0;
+    struct volser_trans *tt = 0, *tt2 = 0;
+    char caller[MAXKTCNAMELEN];
+    char line[128];
+
+    if (!afsconf_SuperUser(tdir, acall, caller)) 
+        return EPERM;
+
+    vol = VAttachVolume(&code, vid, V_VOLUPD);
+    if (!vol) {
+        if (!code)
+            code = ENOENT;
+        return code;
+    }
+    newvol = VAttachVolume(&code, new, V_VOLUPD);
+    if (!newvol) {
+        VDetachVolume(&code2, vol);
+        if (!code)
+            code = ENOENT;
+        return code;
+    }
+    if (V_device(vol) != V_device(newvol) 
+       || V_uniquifier(newvol) != 2) {
+        if (V_device(vol) != V_device(newvol)) {
+            sprintf(line, "Volumes %u and %u are not in the same partition, aborted.\n",
+                   vid, new);
+            rx_Write(acall, line, strlen(line));
+        }
+        if (V_uniquifier(newvol) != 2) {
+            sprintf(line, "Volume %u is not freshly created, aborted.\n", new);
+            rx_Write(acall, line, strlen(line));
+        }
+        line[0] = 0;
+        rx_Write(acall, line, 1);
+        VDetachVolume(&code2, vol);
+        VDetachVolume(&code2, newvol);
+        return EINVAL;
+    }
+    tt = NewTrans(vid, V_device(vol));
+    if (!tt) {
+        sprintf(line, "Couldn't create transaction for %u, aborted.\n", vid);
+        rx_Write(acall, line, strlen(line));
+        line[0] = 0;
+        rx_Write(acall, line, 1);
+        VDetachVolume(&code2, vol);
+        VDetachVolume(&code2, newvol);
+        return VOLSERVOLBUSY;
+    } 
+    VTRANS_OBJ_LOCK(tt);
+    tt->iflags = ITBusy;
+    tt->vflags = 0;
+    TSetRxCall_r(tt, NULL, "SplitVolume");
+    VTRANS_OBJ_UNLOCK(tt);
+
+    tt2 = NewTrans(new, V_device(newvol));
+    if (!tt2) {
+        sprintf(line, "Couldn't create transaction for %u, aborted.\n", new);
+        rx_Write(acall, line, strlen(line));
+        line[0] = 0;
+        rx_Write(acall, line, 1);
+        DeleteTrans(tt, 1);
+        VDetachVolume(&code2, vol);
+        VDetachVolume(&code2, newvol);
+        return VOLSERVOLBUSY;
+    } 
+    VTRANS_OBJ_LOCK(tt2);
+    tt2->iflags = ITBusy;
+    tt2->vflags = 0;
+    TSetRxCall_r(tt2, NULL, "SplitVolume");
+    VTRANS_OBJ_UNLOCK(tt2);
+
+    code = split_volume(acall, vol, newvol, where, verbose);
+
+    VDetachVolume(&code2, vol);
+    DeleteTrans(tt, 1);
+    VDetachVolume(&code2, newvol);
+    DeleteTrans(tt2, 1);
+    return code;
+#else
+    return VOLSERBADOP;
+#endif
+}
+
 /* GetPartName - map partid (a decimal number) into pname (a string)
  * Since for NT we actually want to return the drive name, we map through the
  * partition struct.
  */
-static int GetPartName(afs_int32 partid, char *pname)
-{   
+static int
+GetPartName(afs_int32 partid, char *pname)
+{
     if (partid < 0)
        return -1;
-    if(partid < 26) {
-        strcpy(pname,"/vicep");
+    if (partid < 26) {
+       strcpy(pname, "/vicep");
        pname[6] = 'a' + partid;
        pname[7] = '\0';
        return 0;
     } else if (partid < VOLMAXPARTS) {
-        strcpy(pname,"/vicep");
+       strcpy(pname, "/vicep");
        partid -= 26;
        pname[6] = 'a' + (partid / 26);
        pname[7] = 'a' + (partid % 26);
        pname[8] = '\0';
        return 0;
-    }
-    else return -1;
+    } else
+       return -1;
 }