volser: flag unused variable
[openafs.git] / src / volser / volprocs.c
index 20e22b2..415530d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * 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
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
+#include <roken.h>
 
-#include <stdio.h>
-#include <sys/types.h>
-#include <string.h>
-#include <errno.h>
-#ifdef AFS_NT40_ENV
-#include <fcntl.h>
-#include <winsock2.h>
-#else
-#include <sys/file.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#endif
-
-#include <dirent.h>
-#include <sys/stat.h>
 #include <rx/xdr.h>
 #include <rx/rx.h>
 #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/afs_assert.h>
 #include <afs/prs_fs.h>
 #include <afs/nfs.h>
 #include <lwp.h>
@@ -61,19 +40,22 @@ RCSID
 #include <afs/acl.h>
 #include "afs/audit.h"
 #include <afs/dir.h>
+#include <afs/afsutil.h>
+#include <afs/com_err.h>
+#include <afs/vol_prototypes.h>
+#include <afs/errors.h>
 
 #include "volser.h"
+#include "voltrans_inline.h"
 #include "volint.h"
 
-#include "volser_prototypes.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;
 
-/* Needed by Irix. Leave, or include a header */
-extern char *volutil_PartitionName();
-
 extern void LogError(afs_int32 errcode);
 
 /* Forward declarations */
@@ -86,37 +68,81 @@ static int GetPartName(afs_int32 partid, char *pname);
 #endif
 
 afs_int32 localTid = 1;
-afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
-VolDeleteVolume(), VolClone();
-afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
-VolForward(), VolDump();
-afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
-VolSetInfo(), VolGetName();
-afs_int32 VolListPartitions(), VolListOneVolume(),
-VolXListOneVolume(), VolXListVolumes();
-afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
-VolSetIdsTypes(), VolSetDate(), VolSetFlags();
+
+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 */
-int 
-VPFullUnlock()
+int
+VPFullUnlock_r(void)
 {
-    register struct DiskPartition64 *tp;
+    struct DiskPartition64 *tp;
     for (tp = DiskPartitionList; tp; tp = tp->next) {
-       if (tp->lock_fd != -1) {
-           close(tp->lock_fd); /* releases flock held on this partition */
-           tp->lock_fd = -1;
+       if (tp->lock_fd != INVALID_FD) {
+            OS_CLOSE(tp->lock_fd);
+           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(char *aname)
 {
-    register char tc;
-    register int code = 0;
+    char tc;
+    int code = 0;
     char ascii[3];
 
     tc = *aname;
@@ -150,12 +176,12 @@ PartitionID(char *aname)
 }
 
 static int
-ConvertVolume(afs_int32 avol, char *aname, afs_int32 asize)
+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 */
-    (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
+    snprintf(aname, asize, VFORMAT, (unsigned long)avol);
     return 0;
 }
 
@@ -179,12 +205,92 @@ ConvertPartition(int apartno, char *aname, int asize)
     return 0;
 }
 
+#ifdef AFS_DEMAND_ATTACH_FS
+/* normally we should use the regular salvaging functions from the volume
+ * package, but this is a special case where we have a volume ID, but no
+ * volume structure to give the volume package */
+static void
+SalvageUnknownVolume(VolumeId volid, char *part)
+{
+    afs_int32 code;
+
+    Log("Scheduling salvage for allegedly nonexistent volume %lu part %s\n",
+        afs_printable_uint32_lu(volid), part);
+
+    code = FSYNC_VolOp(volid, part, FSYNC_VOL_FORCE_ERROR,
+                       FSYNC_SALVAGE, NULL);
+    if (code) {
+       Log("SalvageUnknownVolume: error %ld trying to salvage vol %lu part %s\n",
+           afs_printable_int32_ld(code), afs_printable_uint32_lu(volid),
+           part);
+    }
+}
+#endif /* AFS_DEMAND_ATTACH_FS */
+
+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(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;
@@ -194,26 +300,28 @@ XAttachVolume(afs_int32 *error, afs_int32 avolid, afs_int32 apartid, int amode)
        *error = EINVAL;
        return NULL;
     }
-    tv = VAttachVolumeByName((Error *)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 int
+static Error
 ViceCreateRoot(Volume *vp)
 {
     DirHandle dir;
     struct acl_accessList *ACL;
-    ViceFid did;
-    Inode inodeNumber, nearInode;
+    AFSFid did;
+    Inode inodeNumber, AFS_UNUSED nearInode;
     struct VnodeDiskObject *vnode;
     struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
     IHandle_t *h;
     FdHandle_t *fdP;
-    int code;
     afs_fsize_t length;
+    ssize_t nBytes;
 
     vnode = (struct VnodeDiskObject *)malloc(SIZEOF_LARGEDISKVNODE);
+    if (!vnode)
+       return ENOMEM;
     memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
 
     V_pref(vp, nearInode);
@@ -221,17 +329,21 @@ ViceCreateRoot(Volume *vp)
        IH_CREATE(V_linkHandle(vp), V_device(vp),
                  VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
                  1, 1, 0);
-    assert(VALID_INO(inodeNumber));
+    if (!VALID_INO(inodeNumber)) {
+       Log("ViceCreateRoot: IH_CREATE: %s\n", afs_error_message(errno));
+       free(vnode);
+       return EIO;
+    }
 
     SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
     did.Volume = V_id(vp);
     did.Vnode = (VnodeId) 1;
     did.Unique = 1;
 
-    assert(!(MakeDir(&dir, &did, &did)));
+    osi_Assert(!(afs_dir_MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
     DFlush();                  /* flush all modified dir buffers out */
     DZap(&dir);                        /* Remove all buffers for this dir */
-    length = Length(&dir);     /* Remember size of this directory */
+    length = afs_dir_Length(&dir);     /* Remember size of this directory */
 
     FidZap(&dir);              /* Done with the dir handle obtained via SetSalvageDirHandle() */
 
@@ -268,22 +380,20 @@ ViceCreateRoot(Volume *vp)
     IH_INIT(h, vp->device, V_parentId(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);
+    osi_Assert(fdP != NULL);
+    nBytes = FDH_PWRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE, vnodeIndexOffset(vcp, 1));
+    osi_Assert(nBytes == SIZEOF_LARGEDISKVNODE);
     FDH_REALLYCLOSE(fdP);
     IH_RELEASE(h);
     VNDISK_GET_LEN(length, vnode);
     V_diskused(vp) = nBlocks(length);
 
     free(vnode);
-    return 1;
+    return 0;
 }
 
 afs_int32
-SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition 
+SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
                     *partition)
 {
     afs_int32 code;
@@ -304,7 +414,7 @@ SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
 }
 
 afs_int32
-SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64 
+SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64
                     *partition)
 {
     afs_int32 code;
@@ -315,10 +425,10 @@ SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64
 }
 
 afs_int32
-VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64 
+VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
                 *partition)
 {
-    register struct DiskPartition64 *dp;
+    struct DiskPartition64 *dp;
 
 /*
     if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
@@ -328,7 +438,7 @@ VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
     if (dp) {
        strncpy(partition->name, dp->name, 32);
        strncpy(partition->devName, dp->devName, 32);
-       partition->lock_fd = dp->lock_fd;
+       partition->lock_fd = (int)dp->lock_fd;
        partition->free = dp->free;
        partition->minFree = dp->totalUsable;
        return 0;
@@ -338,7 +448,7 @@ VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
 
 /* obliterate a volume completely, and slowly. */
 afs_int32
-SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
+SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
 {
     afs_int32 code;
 
@@ -347,13 +457,13 @@ SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
     return code;
 }
 
-afs_int32
-VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
+static afs_int32
+VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
 {
-    register char *tp;
     char partName[50];
     afs_int32 error;
-    register afs_int32 code;
+    Error verror;
+    afs_int32 code;
     struct Volume *tvp;
     char caller[MAXKTCNAMELEN];
 
@@ -363,10 +473,8 @@ VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
     if (DoLogging)
        Log("%s is executing VolNukeVolume %u\n", caller, avolID);
 
-    tp = volutil_PartitionName(apartID);
-    if (!tp)
+    if (volutil_PartitionName2_r(apartID, partName, sizeof(partName)) != 0)
        return VOLSERNOVOL;
-    strcpy(partName, tp);      /* remember it for later */
     /* 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.
@@ -374,7 +482,7 @@ VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
     tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD);
     code = nuke(partName, avolID);
     if (tvp)
-       VDetachVolume(&error, tvp);
+       VDetachVolume(&verror, tvp);
     return code;
 }
 
@@ -385,8 +493,8 @@ VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
  * Return the new volume id in *avolid.
  */
 afs_int32
-SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname, 
-                   afs_int32 atype, afs_int32 aparent, afs_int32 *avolid, 
+SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
+                   afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid,
                    afs_int32 *atrans)
 {
     afs_int32 code;
@@ -399,16 +507,17 @@ SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
     return code;
 }
 
-afs_int32
-VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname, 
-                   afs_int32 atype, afs_int32 aparent, afs_int32 *avolid, 
+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)
 {
-    afs_int32 error;
-    register Volume *vp;
-    afs_int32 junk;            /* discardable error code */
-    register afs_int32 volumeID, doCreateRoot = 1;
-    register struct volser_trans *tt;
+    Error error;
+    Volume *vp;
+    Error junk;                /* discardable error code */
+    afs_uint32 volumeID;
+    afs_int32 doCreateRoot = 1;
+    struct volser_trans *tt;
     char ppath[30];
     char caller[MAXKTCNAMELEN];
 
@@ -441,18 +550,32 @@ VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
     }
     vp = VCreateVolume(&error, ppath, volumeID, aparent);
     if (error) {
+#ifdef AFS_DEMAND_ATTACH_FS
+       if (error != VVOLEXISTS && error != EXDEV) {
+           SalvageUnknownVolume(volumeID, ppath);
+       }
+#endif
        Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
        LogError(error);
        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);
-    if (doCreateRoot)
-       ViceCreateRoot(vp);
+    if (doCreateRoot) {
+       error = ViceCreateRoot(vp);
+       if (error) {
+           Log("1 Volser: CreateVolume: Unable to create volume root dir; "
+               "error code %u\n", (unsigned)error);
+           DeleteTrans(tt, 1);
+           V_needsSalvaged(vp) = 1;
+           VDetachVolume(&junk, vp);
+           return EIO;
+       }
+    }
     V_destroyMe(vp) = DESTROY_ME;
     V_inService(vp) = 0;
     V_maxquota(vp) = 5000;     /* set a quota of 5000 at init time */
@@ -464,12 +587,13 @@ VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
        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;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
     return 0;
@@ -486,11 +610,11 @@ SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
     return code;
 }
 
-afs_int32
+static afs_int32
 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
 {
-    register struct volser_trans *tt;
-    afs_int32 error;
+    struct volser_trans *tt;
+    Error error;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -505,12 +629,16 @@ VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
     }
     if (DoLogging)
        Log("%s is executing Delete Volume %u\n", caller, tt->volid);
-    strcpy(tt->lastProcName, "DeleteVolume");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "DeleteVolume");
     VPurgeVolume(&error, tt->volume);  /* don't check error code, it is not set! */
-    V_destroyMe(tt->volume) = DESTROY_ME; /* so endtrans does the right fssync opcode */
+    V_destroyMe(tt->volume) = DESTROY_ME;
+    if (tt->volume->needsPutBack) {
+       tt->volume->needsPutBack = VOL_PUTBACK_DELETE; /* so endtrans does the right fssync opcode */
+    }
+    VTRANS_OBJ_LOCK(tt);
     tt->vflags |= VTDeleted;   /* so we know not to do anything else to it */
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall_r(tt);
+    VTRANS_OBJ_UNLOCK(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -520,17 +648,18 @@ VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
 
 /* 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).
  */
 /* for efficiency reasons, sometimes faster to piggyback a purge here */
 afs_int32
-SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId, 
-            afs_int32 newType, char *newName, afs_int32 *newNumber)
+SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
+            afs_int32 newType, char *newName, afs_uint32 *newNumber)
 {
     afs_int32 code;
 
@@ -541,15 +670,18 @@ SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
     return code;
 }
 
-afs_int32
-VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId, 
-            afs_int32 newType, char *newName, afs_int32 *newNumber)
+static afs_int32
+VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
+            afs_int32 newType, char *newName, afs_uint32 *newNumber)
 {
-    VolumeId newId;
-    register struct Volume *originalvp, *purgevp, *newvp;
+    afs_uint32 newId;
+    struct Volume *originalvp, *purgevp, *newvp;
     Error error, code;
-    register struct volser_trans *tt, *ttc;
+    struct volser_trans *tt, *ttc;
     char caller[MAXKTCNAMELEN];
+#ifdef AFS_DEMAND_ATTACH_FS
+    struct Volume *salv_vp = NULL;
+#endif
 
     if (strlen(newName) > 31)
        return VOLSERBADNAME;
@@ -582,14 +714,13 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
     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;
@@ -636,6 +767,9 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
     }
 
     error = 0;
+#ifdef AFS_DEMAND_ATTACH_FS
+    salv_vp = originalvp;
+#endif
 
     newvp =
        VCreateVolume(&error, originalvp->partition->name, newId,
@@ -690,7 +824,10 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
        LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
+#ifdef AFS_DEMAND_ATTACH_FS
+    salv_vp = NULL;
+#endif
     if (TRELE(tt)) {
        tt = (struct volser_trans *)0;
        error = VOLSERTRELE_ERROR;
@@ -705,17 +842,22 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
     if (newvp)
        VDetachVolume(&code, newvp);
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
     }
     if (ttc)
        DeleteTrans(ttc, 1);
+#ifdef AFS_DEMAND_ATTACH_FS
+    if (salv_vp && error != VVOLEXISTS && error != EXDEV) {
+       V_needsSalvaged(salv_vp) = 1;
+    }
+#endif /* AFS_DEMAND_ATTACH_FS */
     return error;
 }
 
 /* reclone this volume into the specified id */
 afs_int32
-SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
+SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 cloneId)
 {
     afs_int32 code;
 
@@ -725,13 +867,13 @@ SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
     return code;
 }
 
-afs_int32
+static afs_int32
 VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
 {
-    register struct Volume *originalvp, *clonevp;
+    struct Volume *originalvp, *clonevp;
     Error error, code;
     afs_int32 newType;
-    register struct volser_trans *tt, *ttc;
+    struct volser_trans *tt, *ttc;
     char caller[MAXKTCNAMELEN];
 
     /*not a super user */
@@ -754,10 +896,9 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
     ttc = NewTrans(cloneId, tt->partition);
     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)
@@ -773,7 +914,7 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
        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;
@@ -844,6 +985,11 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
        LogError(error);
        goto fail;
     }
+    /* 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);
@@ -852,7 +998,7 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
        LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt)) {
        tt = (struct volser_trans *)0;
        error = VOLSERTRELE_ERROR;
@@ -871,7 +1017,7 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
     if (clonevp)
        VDetachVolume(&code, clonevp);
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
     }
     if (ttc)
@@ -884,7 +1030,7 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
  * See volser.h for definition of iflags (the constants are named IT*).
  */
 afs_int32
-SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
+SAFSVolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
                   afs_int32 iflags, afs_int32 *ttid)
 {
     afs_int32 code;
@@ -895,13 +1041,14 @@ SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
     return code;
 }
 
-afs_int32
-VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
+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;
+    struct volser_trans *tt;
+    Volume *tv;
+    afs_int32 error;
+    Error code;
     afs_int32 mode;
     char caller[MAXKTCNAMELEN];
 
@@ -935,11 +1082,13 @@ VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
        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");
+    TSetRxCall_r(tt, NULL, "TransCreate");
+    VTRANS_OBJ_UNLOCK(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -950,7 +1099,7 @@ VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
  * Both the volume number and partition number (one-based) are returned.
  */
 afs_int32
-SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
+SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_uint32 *avolume,
                    afs_int32 *apart)
 {
     afs_int32 code;
@@ -960,8 +1109,8 @@ SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
     return code;
 }
 
-afs_int32
-VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_int32 *avolume,
+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");
@@ -981,10 +1130,10 @@ SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
     return code;
 }
 
-afs_int32
+static afs_int32
 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
 {
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
 
     tt = FindTrans(atid);
     if (!tt)
@@ -995,10 +1144,9 @@ VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "GetFlags");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "GetFlags");
     *aflags = tt->vflags;
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -1020,12 +1168,12 @@ SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
     return code;
 }
 
-afs_int32
+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;
+    struct volser_trans *tt;
+    struct Volume *vp;
+    Error error;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -1040,8 +1188,7 @@ VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "SetFlags");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetFlags");
     vp = tt->volume;           /* pull volume out of transaction */
 
     /* check if we're allowed to make any updates */
@@ -1063,7 +1210,10 @@ VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
        V_inService(vp) = 1;
     }
     VUpdateVolume(&error, vp);
+    VTRANS_OBJ_LOCK(tt);
     tt->vflags = aflags;
+    TClearRxCall_r(tt);
+    VTRANS_OBJ_UNLOCK(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
 
@@ -1076,7 +1226,7 @@ VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
  */
 afs_int32
 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
-              struct destServer *destination, afs_int32 destTrans, 
+              struct destServer *destination, afs_int32 destTrans,
               struct restoreCookie *cookie)
 {
     afs_int32 code;
@@ -1084,20 +1234,20 @@ SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
     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);
+              htonl(destination->destHost), AUD_LONG, destTrans, AUD_END);
     return code;
 }
 
-afs_int32
+static afs_int32
 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
-              struct destServer *destination, afs_int32 destTrans, 
+              struct destServer *destination, afs_int32 destTrans,
               struct restoreCookie *cookie)
 {
-    register struct volser_trans *tt;
-    register afs_int32 code;
-    register struct rx_connection *tcon;
+    struct volser_trans *tt;
+    afs_int32 code;
+    struct rx_connection *tcon;
     struct rx_call *tcall;
-    register struct Volume *vp;
+    struct Volume *vp;
     struct rx_securityClass *securityObject;
     afs_int32 securityIndex;
     char caller[MAXKTCNAMELEN];
@@ -1118,7 +1268,7 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
        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);
@@ -1133,12 +1283,12 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
                         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);
     if (code) {
@@ -1150,7 +1300,7 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
     if (code)
        goto fail;
     EndAFSVolRestore(tcall);   /* probably doesn't do much */
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     code = rx_EndCall(tcall, 0);
     rx_DestroyConnection(tcon);        /* done with the connection */
     tcon = NULL;
@@ -1167,7 +1317,7 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
        rx_DestroyConnection(tcon);
     }
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
     }
     return code;
@@ -1175,16 +1325,16 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
 
 /* Start a dump and send it to multiple places simultaneously.
  * If this returns an error (eg, return ENOENT), it means that
- * none of the releases worked.  If this returns 0, that means 
+ * none of the releases worked.  If this returns 0, that means
  * that one or more of the releases worked, and the caller has
  * to examine the results array to see which one(s).
  * This will only do EITHER incremental or full, not both, so it's
  * the caller's responsibility to be sure that all the destinations
- * need just an incremental (and from the same time), if that's 
- * what we're doing. 
+ * need just an incremental (and from the same time), if that's
+ * what we're doing.
  */
 afs_int32
-SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32 
+SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
                       fromDate, manyDests *destinations, afs_int32 spare,
                       struct restoreCookie *cookie, manyResults *results)
 {
@@ -1198,8 +1348,14 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
     struct Volume *vp;
     int i, is_incremental;
 
-    if (results)
+    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 */
@@ -1212,17 +1368,21 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
        return ENOENT;
     }
     vp = tt->volume;
-    strcpy(tt->lastProcName, "ForwardMulti");
+    TSetRxCall(tt, NULL, "ForwardMulti");
 
     /* (fromDate == 0) ==> full 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 *));
+    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);
@@ -1277,14 +1437,14 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
        }
 
        osi_auditU(acid, VS_ForwardEvent, (code ? code : codes[i]), AUD_LONG,
-                  fromTrans, AUD_HOST, dest->server.destHost, AUD_LONG,
+                  fromTrans, AUD_HOST, htonl(dest->server.destHost), AUD_LONG,
                   dest->trans, AUD_END);
     }
     free(tcons);
     free(tcalls);
 
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        if (TRELE(tt) && !code) /* return the first code if it's set */
            return VOLSERTRELE_ERROR;
     }
@@ -1303,7 +1463,8 @@ SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
 }
 
 afs_int32
-SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
+SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
+             afs_int32 flags)
 {
     afs_int32 code;
 
@@ -1312,11 +1473,12 @@ SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs
     return code;
 }
 
-afs_int32
-VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
+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;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -1329,16 +1491,15 @@ VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "Dump");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "Dump");
     code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
                      ? 0 : 1); /* squirt out the volume's data, too */
     if (code) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return code;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
 
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
@@ -1346,11 +1507,11 @@ VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32
     return 0;
 }
 
-/* 
+/*
  * Ha!  No more helper process!
  */
 afs_int32
-SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags, 
+SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
               struct restoreCookie *cookie)
 {
     afs_int32 code;
@@ -1360,12 +1521,12 @@ SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
     return code;
 }
 
-afs_int32
-VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags, 
-              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;
+    struct volser_trans *tt;
+    afs_int32 code, tcode;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -1378,14 +1539,13 @@ VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "Restore");
-    tt->rxCallPtr = acid;
+    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);
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     tcode = TRELE(tt);
 
     return (code ? code : tcode);
@@ -1402,10 +1562,10 @@ SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
     return code;
 }
 
-afs_int32
+static afs_int32
 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
 {
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -1427,15 +1587,16 @@ SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
 
     code = VolSetForwarding(acid, atid, anewsite);
     osi_auditU(acid, VS_SetForwEvent, code, AUD_LONG, atid, AUD_HOST,
-              anewsite, AUD_END);
+              htonl(anewsite), AUD_END);
     return code;
 }
 
-afs_int32
+static afs_int32
 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
 {
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
+    char partName[16];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
        return VOLSERBAD_ACCESS;        /*not a super user */
@@ -1448,10 +1609,12 @@ VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "SetForwarding");
-    tt->rxCallPtr = acid;
-    FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_MOVE, anewsite, NULL);
-    tt->rxCallPtr = (struct rx_call *)0;
+    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;
 
@@ -1459,8 +1622,8 @@ VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
 }
 
 afs_int32
-SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans, 
-                register struct volser_status *astatus)
+SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
+                struct volser_status *astatus)
 {
     afs_int32 code;
 
@@ -1469,12 +1632,12 @@ SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
     return code;
 }
 
-afs_int32
-VolGetStatus(struct rx_call *acid, afs_int32 atrans, 
-                register struct volser_status *astatus)
+static afs_int32
+VolGetStatus(struct rx_call *acid, afs_int32 atrans,
+            struct volser_status *astatus)
 {
-    register struct Volume *tv;
-    register struct VolumeDiskData *td;
+    struct Volume *tv;
+    struct VolumeDiskData *td;
     struct volser_trans *tt;
 
 
@@ -1487,11 +1650,10 @@ VolGetStatus(struct rx_call *acid, afs_int32 atrans,
        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;
     }
@@ -1513,7 +1675,7 @@ VolGetStatus(struct rx_call *acid, afs_int32 atrans,
     astatus->expirationDate = td->expirationDate;
     astatus->backupDate = td->backupDate;
     astatus->copyDate = td->copyDate;
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -1521,8 +1683,8 @@ VolGetStatus(struct rx_call *acid, afs_int32 atrans,
 }
 
 afs_int32
-SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans, 
-              register struct volintInfo *astatus)
+SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
+              struct volintInfo *astatus)
 {
     afs_int32 code;
 
@@ -1531,15 +1693,15 @@ SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
     return code;
 }
 
-afs_int32
-VolSetInfo(struct rx_call *acid, afs_int32 atrans, 
-              register struct volintInfo *astatus)
+static afs_int32
+VolSetInfo(struct rx_call *acid, afs_int32 atrans,
+              struct volintInfo *astatus)
 {
-    register struct Volume *tv;
-    register struct VolumeDiskData *td;
+    struct Volume *tv;
+    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 */
@@ -1551,11 +1713,10 @@ VolSetInfo(struct rx_call *acid, afs_int32 atrans,
        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;
     }
@@ -1575,7 +1736,7 @@ VolSetInfo(struct rx_call *acid, afs_int32 atrans,
     if (astatus->spare2 != -1)
        td->volUpdateCounter = (unsigned int)astatus->spare2;
     VUpdateVolume(&error, tv);
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
     return 0;
@@ -1592,15 +1753,18 @@ SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
     return code;
 }
 
-afs_int32
+static afs_int32
 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
 {
-    register struct Volume *tv;
-    register struct VolumeDiskData *td;
+    struct Volume *tv;
+    struct VolumeDiskData *td;
     struct volser_trans *tt;
-    register int len;
+    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;
@@ -1609,11 +1773,10 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
        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;
     }
@@ -1621,13 +1784,13 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
     td = &tv->header->diskstuff;
     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;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -1637,8 +1800,8 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
 /*this is a handshake to indicate that the next call will be SAFSVolRestore
  * - a noop now !*/
 afs_int32
-SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType, 
-                    afs_int32 parentId, afs_int32 cloneId)
+SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
+                    afs_uint32 parentId, afs_uint32 cloneId)
 {
     return 0;
 }
@@ -1656,11 +1819,11 @@ SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
     return code;
 }
 
-afs_int32
+static afs_int32
 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
 {
     char namehead[9];
-    char i;
+    int i;
 
     strcpy(namehead, "/vicep");        /*7 including null terminator */
 
@@ -1686,14 +1849,13 @@ SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
     return code;
 }
 
-afs_int32
+static afs_int32
 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
 {
-    struct stat rbuf, pbuf;
     char namehead[9];
     struct partList partList;
     struct DiskPartition64 *dp;
-    int i, j = 0, k;
+    int i, j = 0;
 
     strcpy(namehead, "/vicep");        /*7 including null terminator */
 
@@ -1706,6 +1868,8 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
            namehead[6] = i + 'a';
            namehead[7] = '\0';
        } else {
+           int k;
+
            k = i - 26;
            namehead[6] = 'a' + (k / 26);
            namehead[7] = 'a' + (k % 26);
@@ -1716,10 +1880,17 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
        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));
-    pEntries->partEntries_len = j;
+    if (j > 0) {
+       pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
+       if (!pEntries->partEntries_val)
+           return ENOMEM;
+       memcpy((char *)pEntries->partEntries_val, (char *)&partList,
+               j * sizeof(int));
+       pEntries->partEntries_len = j;
+    } else {
+       pEntries->partEntries_val = NULL;
+       pEntries->partEntries_len = 0;
+    }
     return 0;
 
 }
@@ -1743,7 +1914,7 @@ ExtractVolId(char vname[])
 /*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*/
 int
-GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
+GetNextVol(DIR * dirp, char *volname, afs_uint32 * volid)
 {
     struct dirent *dp;
 
@@ -1808,22 +1979,26 @@ typedef struct {
  * fill in appropriate type of on-wire volume metadata structure.
  *
  * @param vp      pointer to volume object
- * @param hdr     pointer to volume disk data 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, VolumeDiskData * hdr, volint_info_handle_t * handle)
+FillVolInfo(Volume * vp, volint_info_handle_t * handle)
 {
     unsigned int numStatBytes, now;
+    struct VolumeDiskData *hdr = &vp->header->diskstuff;
 
     /*read in the relevant info */
-    strcpy(VOLINT_INFO_PTR(handle, name), hdr->name);
+    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 */
@@ -1854,25 +2029,51 @@ FillVolInfo(Volume * vp, VolumeDiskData * hdr, volint_info_handle_t * handle)
      * along with the blessed and inService flags from the header.
      *   -- tkeiser 11/27/2007
      */
-    if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
+
+    /* 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) {
+       !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
-    VOLINT_INFO_STORE(handle, inUse, hdr->inUse);
+    /* 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 || VIsErrorState(V_attachState(vp))) {
+       if (hdr->needsSalvaged ||
+           (vp && VIsErrorState(V_attachState(vp)))) {
            handle->volinfo_ptr.base->needsSalvaged = 1;
        } else {
            handle->volinfo_ptr.base->needsSalvaged = 0;
@@ -1882,7 +2083,7 @@ FillVolInfo(Volume * vp, VolumeDiskData * hdr, volint_info_handle_t * handle)
 #endif
        handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
        handle->volinfo_ptr.base->spare0 = hdr->minquota;
-       handle->volinfo_ptr.base->spare1 = 
+       handle->volinfo_ptr.base->spare1 =
            (long)hdr->weekUse[0] +
            (long)hdr->weekUse[1] +
            (long)hdr->weekUse[2] +
@@ -1905,11 +2106,11 @@ FillVolInfo(Volume * vp, VolumeDiskData * hdr, volint_info_handle_t * handle)
         * Copy out the stat fields in a single operation.
         */
        if ((now - hdr->dayUseDate) > OneDay) {
-           memset((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
+           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]), 
+                  (char *)&(hdr->stat_reads[0]),
                   numStatBytes);
        }
        break;
@@ -1918,35 +2119,55 @@ FillVolInfo(Volume * vp, VolumeDiskData * hdr, volint_info_handle_t * handle)
     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[out] vp       pointer to Volume object
+ * @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 nonzero failure
+ *   @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, Volume * vp)
+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(*vp);
+    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;
+       }
+    }
+
     return code;
 }
 
+#endif
+
 /**
  * mode of volume list operation.
  */
@@ -1974,27 +2195,42 @@ typedef enum {
 static int
 GetVolInfo(afs_uint32 partId,
           afs_uint32 volumeId,
-          char * pname, 
-          char * volname, 
+          char * pname,
+          char * volname,
           volint_info_handle_t * handle,
           vol_info_list_mode_t mode)
 {
     int code = -1;
-    afs_int32 error;
+    Error error;
     struct volser_trans *ttc = NULL;
-    struct Volume fs_tv, *tv = 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, VBUSY);
+       VOLINT_INFO_STORE(handle, status, VOLSERVOLBUSY);
        VOLINT_INFO_STORE(handle, volid, volumeId);
        goto drop;
     }
 
-    tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
+    /* Get volume from volserver */
+    if (mode == VOL_INFO_LIST_MULTIPLE)
+       tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
+    else
+       tv = VAttachVolumeByName_retry(&error, pname, volname, V_PEEK);
     if (error) {
-       Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n", 
+       Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
            volumeId, pname, volname, error);
        goto drop;
     }
@@ -2013,7 +2249,7 @@ GetVolInfo(afs_uint32 partId,
            goto drop;
 
        case VOL_INFO_LIST_SINGLE:
-           Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n", 
+           Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n",
                volumeId, pname, volname);
 
        default:
@@ -2023,25 +2259,43 @@ GetVolInfo(afs_uint32 partId,
 
     if (tv->header->diskstuff.needsSalvaged) {
        /*this volume will be salvaged */
-       Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n", 
+       Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
            volumeId, pname, volname);
-       goto drop;
     }
 
 #ifdef AFS_DEMAND_ATTACH_FS
-    if (GetVolObject(volumeId, &fs_tv)) {
+    /* 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(&fs_tv, &tv->header->diskstuff, handle);
-
+    code = FillVolInfo(fill_tv, handle);
 
  drop:
     if (code == -1) {
        VOLINT_INFO_STORE(handle, status, 0);
-       strcpy(VOLINT_INFO_PTR(handle, name), volname);
+       strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
        VOLINT_INFO_STORE(handle, volid, volumeId);
     }
     if (tv) {
@@ -2049,7 +2303,7 @@ GetVolInfo(afs_uint32 partId,
        tv = NULL;
        if (error) {
            VOLINT_INFO_STORE(handle, status, 0);
-           strcpy(VOLINT_INFO_PTR(handle, name), volname);
+           strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
            Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
                volumeId, pname, volname);
        }
@@ -2064,8 +2318,8 @@ GetVolInfo(afs_uint32 partId,
 
 /*return the header information about the <volid> */
 afs_int32
-SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32 
-                    volumeId, volEntries *volumeInfo)
+SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,
+                     afs_uint32 volumeId, volEntries *volumeInfo)
 {
     afs_int32 code;
 
@@ -2074,23 +2328,23 @@ SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
     return code;
 }
 
-afs_int32
-VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32 
-                    volumeId, volEntries *volumeInfo)
+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));
-    pntr = volumeInfo->volEntries_val;
+    if (!volumeInfo->volEntries_val)
+       return ENOMEM;
+    memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
+
     volumeInfo->volEntries_len = 1;
     if (GetPartName(partid, pname))
        return VOLSERILLEGAL_PARTITION;
@@ -2124,17 +2378,20 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
 
        handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
        handle.volinfo_ptr.base = volumeInfo->volEntries_val;
-       
-       code = GetVolInfo(partid, 
-                         volid, 
-                         pname, 
+
+       code = GetVolInfo(partid,
+                         volid,
+                         pname,
                          volname,
                          &handle,
                          VOL_INFO_LIST_SINGLE);
     }
 
     closedir(dirp);
-    return (found) ? 0 : ENODEV;
+    if (found)
+        return code ? ENODEV: 0;
+    else
+        return ENODEV;
 }
 
 /*------------------------------------------------------------------------
@@ -2161,8 +2418,8 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
  *------------------------------------------------------------------------*/
 
 afs_int32
-SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID, 
-                     afs_int32 a_volID, volXEntries *a_volumeXInfoP)
+SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
+                     afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
 {
     afs_int32 code;
 
@@ -2171,19 +2428,16 @@ SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
     return code;
 }
 
-afs_int32
-VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID, 
-                     afs_int32 a_volID, volXEntries *a_volumeXInfoP)
+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 */
-    afs_int32 error;           /*Error code */
     DIR *dirp;                 /*Partition directory ptr */
-    afs_int32 currVolID;       /*Current volume ID */
+    afs_uint32 currVolID;              /*Current volume ID */
     int found = 0;             /*Did we find the volume we need? */
-    unsigned int now;
     int code;
     volint_info_handle_t handle;
 
@@ -2193,7 +2447,10 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
      */
     a_volumeXInfoP->volXEntries_val =
        (volintXInfo *) malloc(sizeof(volintXInfo));
-    xInfoP = a_volumeXInfoP->volXEntries_val;
+    if (!a_volumeXInfoP->volXEntries_val)
+       return ENOMEM;
+    memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
+
     a_volumeXInfoP->volXEntries_len = 1;
     code = ENODEV;
 
@@ -2265,13 +2522,16 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
      * return the proper value.
      */
     closedir(dirp);
-    return (found) ? 0 : ENODEV;
+    if (found)
+        return code ? ENODEV: 0;
+    else
+        return ENODEV;
 }                              /*SAFSVolXListOneVolume */
 
-/*returns all the volumes on partition partid. If flags = 1 then all the 
+/*returns all the volumes on partition partid. If flags = 1 then all the
 * relevant info about the volumes  is also returned */
 afs_int32
-SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags, 
+SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
                   volEntries *volumeInfo)
 {
     afs_int32 code;
@@ -2281,23 +2541,25 @@ SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
     return code;
 }
 
-afs_int32
-VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags, 
+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 */
+
     pntr = volumeInfo->volEntries_val;
     volumeInfo->volEntries_len = 0;
     if (GetPartName(partid, pname))
@@ -2339,7 +2601,6 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
            /*just volids are needed */
        }
 
-      drop:
        pntr++;
        volumeInfo->volEntries_len += 1;
        if ((allocSize - volumeInfo->volEntries_len) < 5) {
@@ -2349,7 +2610,7 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
                (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
                                       allocSize * sizeof(volintInfo));
            if (pntr == NULL) {
-               closedir(dirp); 
+               closedir(dirp);
                return VOLSERNO_MEMORY;
            }
            volumeInfo->volEntries_val = pntr;  /* point to new block */
@@ -2405,7 +2666,7 @@ SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
     return code;
 }
 
-afs_int32
+static afs_int32
 VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
                    afs_int32 a_flags, volXEntries *a_volumeXInfoP)
 {                              /*SAFSVolXListVolumes */
@@ -2414,10 +2675,8 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
     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 */
-    afs_int32 error = 0;       /*Return code */
     DIR *dirp;                 /*Partition directory ptr */
-    afs_int32 volid;           /*Current volume ID */
-    unsigned int now;
+    afs_uint32 volid;          /*Current volume ID */
     int code;
     volint_info_handle_t handle;
 
@@ -2427,6 +2686,10 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
      */
     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;
 
@@ -2490,7 +2753,6 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
            xInfoP->volid = volid;
        }
 
-      drop:
        /*
         * Bump the pointer in the data area we're building, along with
         * the count of the number of entries it contains.
@@ -2549,21 +2811,27 @@ SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
     return code;
 }
 
-afs_int32
+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));
+    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 */
+       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;
@@ -2582,6 +2850,7 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
            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 */
@@ -2599,12 +2868,16 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
        }
 
     }
+done:
+    VTRANS_UNLOCK;
 
     return 0;
 }
 
 afs_int32
-SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
+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;
 
@@ -2615,12 +2888,14 @@ SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32
     return code;
 }
 
-afs_int32
-VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type, afs_int32 pId, afs_int32 cloneId, afs_int32 backupId)
+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;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (strlen(name) > 31)
@@ -2636,8 +2911,7 @@ VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "SetIdsTypes");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetIdsTypes");
     tv = tt->volume;
 
     V_type(tv) = type;
@@ -2651,13 +2925,13 @@ VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[], afs_int32 type
        LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
 
     return error;
   fail:
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
     return error;
@@ -2674,12 +2948,12 @@ SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
     return code;
 }
 
-afs_int32
+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;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -2693,8 +2967,7 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "SetDate");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetDate");
     tv = tt->volume;
 
     V_creationDate(tv) = cdate;
@@ -2704,13 +2977,13 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
        LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
 
     return error;
   fail:
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
     return error;
@@ -2718,18 +2991,18 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
 
 afs_int32
 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
-                          afs_int32 volumeId)
+                          afs_uint32 volumeId)
 {
 #ifdef AFS_NT40_ENV
     return EXDEV;
 #else
     char caller[MAXKTCNAMELEN];
     DIR *dirp;
-    register struct volser_trans *ttc;
+    struct volser_trans *ttc;
     char pname[16], volname[20];
     struct DiskPartition64 *partP;
     afs_int32 ret = ENODEV;
-    afs_int32 volid;
+    afs_uint32 volid;
 
     if (!afsconf_SuperUser(tdir, acid, caller))
        return VOLSERBAD_ACCESS;        /*not a super user */
@@ -2748,14 +3021,14 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
             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 VBUSY;
+               return VOLSERVOLBUSY;
             }
 #ifdef AFS_NAMEI_ENV
            ret = namei_ConvertROtoRWvolume(pname, volumeId);
@@ -2766,12 +3039,12 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
        }
        GetNextVol(dirp, volname, &volid);
     }
-    
+
     if (ttc) {
         DeleteTrans(ttc, 1);
         ttc = (struct volser_trans *)0;
     }
-    
+
     closedir(dirp);
     return ret;
 #endif
@@ -2779,10 +3052,10 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
 
 afs_int32
 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
-              register struct volintSize *size)
+              struct volintSize *size)
 {
     int code = 0;
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -2794,10 +3067,9 @@ SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "GetSize");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "GetSize");
     code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size);        /* measure volume's data */
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -2805,6 +3077,95 @@ SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
     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.