volser: make splitvol use VolumeId
[openafs.git] / src / volser / volprocs.c
index f212dd9..11b98f7 100644 (file)
 #include <afsconfig.h>
 #include <afs/param.h>
 
+#include <roken.h>
 
-#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
-#include <sys/file.h>
-#include <netinet/in.h>
-#include <unistd.h>
+#include <afs/opr.h>
+#ifdef AFS_PTHREAD_ENV
+# include <opr/lock.h>
 #endif
 
-#include <dirent.h>
-#include <sys/stat.h>
-#include <rx/xdr.h>
 #include <rx/rx.h>
 #include <rx/rxkad.h>
+#include <rx/rx_queue.h>
 #include <afs/afsint.h>
-#include <signal.h>
-#include <afs/afs_assert.h>
 #include <afs/prs_fs.h>
 #include <afs/nfs.h>
 #include <lwp.h>
@@ -57,6 +45,7 @@
 #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>
 
@@ -70,6 +59,8 @@
 
 extern int DoLogging;
 extern struct afsconf_dir *tdir;
+extern int DoPreserveVolumeStats;
+extern int restrictedQueryLevel;
 
 extern void LogError(afs_int32 errcode);
 
@@ -91,10 +82,10 @@ 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,
+static afs_int32 VolClone(struct rx_call *, afs_int32, VolumeId,
+                         afs_int32, char *, VolumeId *);
+static afs_int32 VolReClone(struct rx_call *, afs_int32, VolumeId);
+static afs_int32 VolTransCreate(struct rx_call *, VolumeId, afs_int32,
                                afs_int32, afs_int32 *);
 static afs_int32 VolGetNthVolume(struct rx_call *, afs_int32, afs_uint32 *,
                                 afs_int32 *);
@@ -114,9 +105,9 @@ 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,
+static afs_int32 VolListOneVolume(struct rx_call *, afs_int32, VolumeId,
                                  volEntries *);
-static afs_int32 VolXListOneVolume(struct rx_call *, afs_int32, afs_uint32,
+static afs_int32 VolXListOneVolume(struct rx_call *, afs_int32, VolumeId,
                                   volXEntries *);
 static afs_int32 VolListVolumes(struct rx_call *, afs_int32, afs_int32,
                                volEntries *);
@@ -124,10 +115,25 @@ 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);
+                               afs_int32, VolumeId, VolumeId,
+                               VolumeId);
 static afs_int32 VolSetDate(struct rx_call *, afs_int32, afs_int32);
 
+/**
+ * Return the host address of the caller as a string.
+ *
+ * @param[in]  acid    incoming rx call
+ * @param[out] buffer  buffer to be filled with the addess string
+ *
+ * @return address as formatted by inet_ntoa
+ */
+static_inline char *
+callerAddress(struct rx_call *acid, char *buffer)
+{
+    afs_uint32 ip = rx_HostOf(rx_PeerOf(rx_ConnectionOf(acid)));
+    return afs_inet_ntoa_r(ip, buffer);
+}
+
 /* this call unlocks all of the partition locks we've set */
 int
 VPFullUnlock_r(void)
@@ -135,7 +141,7 @@ VPFullUnlock_r(void)
     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 */
+            OS_CLOSE(tp->lock_fd);
            tp->lock_fd = INVALID_FD;
        }
     }
@@ -191,12 +197,12 @@ PartitionID(char *aname)
 }
 
 static int
-ConvertVolume(afs_uint32 avol, char *aname, afs_int32 asize)
+ConvertVolume(VolumeId 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, afs_printable_VolumeId_lu(avol));
     return 0;
 }
 
@@ -320,13 +326,13 @@ XAttachVolume(afs_int32 *error, afs_uint32 avolid, afs_int32 apartid, int 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;
     AFSFid did;
-    Inode inodeNumber, nearInode;
+    Inode inodeNumber, AFS_UNUSED nearInode;
     struct VnodeDiskObject *vnode;
     struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
     IHandle_t *h;
@@ -334,27 +340,30 @@ ViceCreateRoot(Volume *vp)
     afs_fsize_t length;
     ssize_t nBytes;
 
-    vnode = (struct VnodeDiskObject *)malloc(SIZEOF_LARGEDISKVNODE);
+    vnode = calloc(1, 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);
-    osi_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;
 
-    osi_Assert(!(MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
+    opr_Verify(!(afs_dir_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 */
+    DZap(&dir);                        /* Remove all buffers for this dir */
+    length = afs_dir_Length(&dir);     /* Remember size of this directory */
 
     FidZap(&dir);              /* Done with the dir handle obtained via SetSalvageDirHandle() */
 
@@ -391,16 +400,16 @@ ViceCreateRoot(Volume *vp)
     IH_INIT(h, vp->device, V_parentId(vp),
            vp->vnodeIndex[vLarge].handle->ih_ino);
     fdP = IH_OPEN(h);
-    osi_Assert(fdP != NULL);
+    opr_Assert(fdP != NULL);
     nBytes = FDH_PWRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE, vnodeIndexOffset(vcp, 1));
-    osi_Assert(nBytes == SIZEOF_LARGEDISKVNODE);
+    opr_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
@@ -408,8 +417,7 @@ SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
                     *partition)
 {
     afs_int32 code;
-    struct diskPartition64 *dp = (struct diskPartition64 *)
-       malloc(sizeof(struct diskPartition64));
+    struct diskPartition64 *dp = malloc(sizeof(struct diskPartition64));
 
     code = VolPartitionInfo(acid, pname, dp);
     if (!code) {
@@ -441,9 +449,9 @@ VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
 {
     struct DiskPartition64 *dp;
 
-/*
-    if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
-*/
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
     VResetDiskUsage();
     dp = VGetPartition(pname, 0);
     if (dp) {
@@ -459,7 +467,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_uint32 avolID)
+SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, VolumeId avolID)
 {
     afs_int32 code;
 
@@ -481,8 +489,11 @@ VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
     /* check for access */
     if (!afsconf_SuperUser(tdir, acid, caller))
        return VOLSERBAD_ACCESS;
-    if (DoLogging)
-       Log("%s is executing VolNukeVolume %u\n", caller, avolID);
+    if (DoLogging) {
+       char buffer[16];
+       Log("%s on %s is executing VolNukeVolume %u\n", caller,
+           callerAddress(acid, buffer), avolID);
+    }
 
     if (volutil_PartitionName2_r(apartID, partName, sizeof(partName)) != 0)
        return VOLSERNOVOL;
@@ -505,7 +516,7 @@ VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
  */
 afs_int32
 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
-                   afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid,
+                   afs_int32 atype, VolumeId aparent, VolumeId *avolid,
                    afs_int32 *atrans)
 {
     afs_int32 code;
@@ -536,8 +547,11 @@ VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
        return VOLSERBADNAME;
     if (!afsconf_SuperUser(tdir, acid, caller))
        return VOLSERBAD_ACCESS;
-    if (DoLogging)
-       Log("%s is executing CreateVolume '%s'\n", caller, aname);
+    if (DoLogging) {
+       char buffer[16];
+       Log("%s on %s is executing CreateVolume '%s'\n", caller,
+           callerAddress(acid, buffer), aname);
+    }
     if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
        return error;           /*a standard unix error */
     if (atype != readwriteVolume && atype != readonlyVolume
@@ -576,8 +590,17 @@ VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
     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 */
@@ -625,15 +648,22 @@ VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
     if (!tt)
        return ENOENT;
     if (tt->vflags & VTDeleted) {
-       Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
+       Log("1 Volser: Delete: volume %" AFS_VOLID_FMT " already deleted \n",
+           afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
-    if (DoLogging)
-       Log("%s is executing Delete Volume %u\n", caller, tt->volid);
+    if (DoLogging) {
+       char buffer[16];
+       Log("%s on %s is executing Delete Volume %" AFS_VOLID_FMT "\n", caller,
+           callerAddress(acid, buffer), afs_printable_VolumeId_lu(tt->volid));
+    }
     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 */
     TClearRxCall_r(tt);
@@ -641,7 +671,8 @@ VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
-    Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
+    Log("1 Volser: Delete: volume %" AFS_VOLID_FMT " deleted \n",
+       afs_printable_VolumeId_lu(tt->volid));
     return 0;                  /* vpurgevolume doesn't set an error code */
 }
 
@@ -657,11 +688,10 @@ VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
  */
 /* 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)
+SAFSVolClone(struct rx_call *acid, afs_int32 atrans, VolumeId purgeId,
+            afs_int32 newType, char *newName, VolumeId *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,
@@ -670,10 +700,10 @@ SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
 }
 
 static afs_int32
-VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
-            afs_int32 newType, char *newName, afs_uint32 *newNumber)
+VolClone(struct rx_call *acid, afs_int32 atrans, VolumeId purgeId,
+            afs_int32 newType, char *newName, VolumeId *newNumber)
 {
-    afs_uint32 newId;
+    VolumeId newId;
     struct Volume *originalvp, *purgevp, *newvp;
     Error error, code;
     struct volser_trans *tt, *ttc;
@@ -686,10 +716,12 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
        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 (DoLogging) {
+       char buffer[16];
+       Log("%s on %s is executing Clone Volume new name=%s\n", caller,
+           callerAddress(acid, buffer), newName);
+    }
     error = 0;
-    originalvp = (Volume *) 0;
     purgevp = (Volume *) 0;
     newvp = (Volume *) 0;
     tt = ttc = (struct volser_trans *)0;
@@ -700,13 +732,11 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
     }
     newId = *newNumber;
 
-    if (newType != readonlyVolume && newType != backupVolume)
-       return EINVAL;
     tt = FindTrans(atrans);
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -721,28 +751,22 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
     if (purgeId) {
        purgevp = VAttachVolume_retry(&error, purgeId, V_VOLUPD);
        if (error) {
-           Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
+           Log("1 Volser: Clone: Could not attach 'purge' volume %" AFS_VOLID_FMT "; clone aborted\n", afs_printable_VolumeId_lu(purgeId));
            goto fail;
        }
     } 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");
-       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));
+       Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT " is offline and cannot be cloned\n",
+           afs_printable_VolumeId_lu(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 %" AFS_VOLID_FMT " and %" AFS_VOLID_FMT " are on different devices\n", afs_printable_VolumeId_lu(tt->volid), afs_printable_VolumeId_lu(purgeId));
            error = EXDEV;
            goto fail;
        }
@@ -751,15 +775,8 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
            error = EINVAL;
            goto fail;
        }
-       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_parentId(originalvp) != V_parentId(purgevp)) {
+           Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT " and volume %" AFS_VOLID_FMT " were not originally cloned from the same parent; aborted\n", afs_printable_VolumeId_lu(purgeId), afs_printable_VolumeId_lu(tt->volid));
            error = EXDEV;
            goto fail;
        }
@@ -770,20 +787,25 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
     salv_vp = originalvp;
 #endif
 
-    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;
-       goto fail;
+    if (purgeId == newId) {
+       newvp = purgevp;
+    } else {
+       newvp =
+           VCreateVolume(&error, originalvp->partition->name, newId,
+                         V_parentId(originalvp));
+       if (error) {
+           Log("1 Volser: Clone: Couldn't create new volume %" AFS_VOLID_FMT " for parent %" AFS_VOLID_FMT "; clone aborted\n",
+               afs_printable_VolumeId_lu(newId), afs_printable_VolumeId_lu(V_parentId(originalvp)));
+           newvp = (Volume *) 0;
+           goto fail;
+       }
     }
     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 %" AFS_VOLID_FMT " to new volume %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(tt->volid),
+       afs_printable_VolumeId_lu(newId));
     if (purgevp)
-       Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
+       Log("1 Volser: Clone: Purging old read only volume %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(purgeId));
     CloneVolume(&error, originalvp, newvp, purgevp);
     purgevp = NULL;            /* clone releases it, maybe even if error */
     if (error) {
@@ -799,7 +821,7 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
        V_type(newvp) = backupVolume;
        V_backupId(originalvp) = newId;
     }
-    strcpy(newvp->header->diskstuff.name, newName);
+    strcpy(V_name(newvp), newName);
     V_creationDate(newvp) = V_copyDate(newvp);
     ClearVolumeStats(&V_disk(newvp));
     V_destroyMe(newvp) = DESTROY_ME;
@@ -848,8 +870,7 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
        DeleteTrans(ttc, 1);
 #ifdef AFS_DEMAND_ATTACH_FS
     if (salv_vp && error != VVOLEXISTS && error != EXDEV) {
-       Error salv_error;
-       VRequestSalvage_r(&salv_error, salv_vp, FSYNC_SALVAGE, 0);
+       V_needsSalvaged(salv_vp) = 1;
     }
 #endif /* AFS_DEMAND_ATTACH_FS */
     return error;
@@ -857,7 +878,7 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
 
 /* reclone this volume into the specified id */
 afs_int32
-SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 cloneId)
+SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, VolumeId cloneId)
 {
     afs_int32 code;
 
@@ -868,28 +889,31 @@ SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 cloneId)
 }
 
 static afs_int32
-VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
+VolReClone(struct rx_call *acid, afs_int32 atrans, VolumeId cloneId)
 {
     struct Volume *originalvp, *clonevp;
     Error error, code;
     afs_int32 newType;
     struct volser_trans *tt, *ttc;
     char caller[MAXKTCNAMELEN];
+    VolumeDiskData saved_header;
 
     /*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);
+    if (DoLogging) {
+       char buffer[16];
+       Log("%s on %s is executing Reclone Volume %" AFS_VOLID_FMT "\n", caller,
+           callerAddress(acid, buffer), afs_printable_VolumeId_lu(cloneId));
+    }
     error = 0;
     clonevp = originalvp = (Volume *) 0;
-    tt = (struct volser_trans *)0;
 
     tt = FindTrans(atrans);
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -901,54 +925,40 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
     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");
-       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));
+       Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT " is offline and cannot be cloned\n",
+           afs_printable_VolumeId_lu(V_id(originalvp)));
        error = VOFFLINE;
        goto fail;
     }
 
     clonevp = VAttachVolume_retry(&error, cloneId, V_VOLUPD);
     if (error) {
-       Log("1 Volser: can't attach clone %d\n", cloneId);
+       Log("1 Volser: can't attach clone %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(cloneId));
        goto fail;
     }
 
     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 %" AFS_VOLID_FMT " and %" AFS_VOLID_FMT " are on different devices\n",
+           afs_printable_VolumeId_lu(tt->volid), afs_printable_VolumeId_lu(cloneId));
        error = EXDEV;
        goto fail;
     }
-    if (V_type(clonevp) != readonlyVolume && V_type(clonevp) != backupVolume) {
-       Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
-       error = EINVAL;
-       goto fail;
-    }
-    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);
+    if (V_parentId(originalvp) != V_parentId(clonevp)) {
+       Log("1 Volser: Clone: Volume %" AFS_VOLID_FMT " was not originally cloned from volume %" AFS_VOLID_FMT "; aborted\n", afs_printable_VolumeId_lu(cloneId), afs_printable_VolumeId_lu(tt->volid));
        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);
-       error = EXDEV;
-       goto fail;
+
+    if (DoPreserveVolumeStats) {
+       CopyVolumeStats(&V_disk(clonevp), &saved_header);
     }
 
     error = 0;
-    Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
-       cloneId);
+    Log("1 Volser: Clone: Recloning volume %" AFS_VOLID_FMT " to volume %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(tt->volid),
+       afs_printable_VolumeId_lu(cloneId));
     CloneVolume(&error, originalvp, clonevp, clonevp);
     if (error) {
        Log("1 Volser: Clone: reclone operation failed with code %d\n",
@@ -968,15 +978,20 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
     }
     /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
 
-    /* pretend recloned volume is a totally new instance */
-    V_copyDate(clonevp) = time(0);
-    V_creationDate(clonevp) = V_copyDate(clonevp);
-    ClearVolumeStats(&V_disk(clonevp));
+    /* update the creationDate, since this represents the last cloning date
+     * for ROs. But do not update copyDate; let it stay so we can identify
+     * when the clone was first created. */
+    V_creationDate(clonevp) = time(0);
+    if (DoPreserveVolumeStats) {
+       CopyVolumeStats(&saved_header, &V_disk(clonevp));
+    } else {
+       ClearVolumeStats(&V_disk(clonevp));
+    }
     V_destroyMe(clonevp) = 0;
     V_inService(clonevp) = 0;
     if (newType == backupVolume) {
-       V_backupDate(originalvp) = V_copyDate(clonevp);
-       V_backupDate(clonevp) = V_copyDate(clonevp);
+       V_backupDate(originalvp) = V_creationDate(clonevp);
+       V_backupDate(clonevp) = V_creationDate(clonevp);
     }
     V_inUse(clonevp) = 0;
     VUpdateVolume(&error, clonevp);
@@ -1030,7 +1045,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_uint32 volume, afs_int32 partition,
+SAFSVolTransCreate(struct rx_call *acid, VolumeId volume, afs_int32 partition,
                   afs_int32 iflags, afs_int32 *ttid)
 {
     afs_int32 code;
@@ -1042,7 +1057,7 @@ SAFSVolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
 }
 
 static afs_int32
-VolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
+VolTransCreate(struct rx_call *acid, VolumeId volume, afs_int32 partition,
                   afs_int32 iflags, afs_int32 *ttid)
 {
     struct volser_trans *tt;
@@ -1099,7 +1114,7 @@ VolTransCreate(struct rx_call *acid, afs_uint32 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_uint32 *avolume,
+SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, VolumeId *avolume,
                    afs_int32 *apart)
 {
     afs_int32 code;
@@ -1113,6 +1128,9 @@ static afs_int32
 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_uint32 *avolume,
                    afs_int32 *apart)
 {
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
     Log("1 Volser: GetNthVolume: Not yet implemented\n");
     return VOLSERNO_OP;
 }
@@ -1135,12 +1153,15 @@ VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
 {
     struct volser_trans *tt;
 
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
     tt = FindTrans(atid);
     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 %" AFS_VOLID_FMT " has been deleted \n",
+           afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -1183,8 +1204,8 @@ VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
     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 %" AFS_VOLID_FMT " has been deleted \n",
+           afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -1234,7 +1255,7 @@ 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;
 }
 
@@ -1254,16 +1275,13 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
 
     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;
 
     /* find the local transaction */
     tt = FindTrans(fromTrans);
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -1351,8 +1369,7 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
     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));
+       results->manyResults_val = codes = malloc(i * sizeof(afs_int32));
     }
     if (!results || !results->manyResults_val)
        return ENOMEM;
@@ -1363,7 +1380,7 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -1373,12 +1390,11 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
     /* (fromDate == 0) ==> full dump */
     is_incremental = (fromDate ? 1 : 0);
 
-    tcons =
-       (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
+    tcons = malloc(i * sizeof(struct rx_connection *));
     if (!tcons) {
        return ENOMEM;
     }
-    tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
+    tcalls = malloc(i * sizeof(struct rx_call *));
     if (!tcalls) {
        free(tcons);
        return ENOMEM;
@@ -1437,7 +1453,7 @@ 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);
@@ -1487,7 +1503,7 @@ VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -1535,10 +1551,15 @@ VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
+    if (DoLogging) {
+       char buffer[16];
+       Log("%s on %s is executing Restore %" AFS_VOLID_FMT "\n", caller,
+           callerAddress(acid, buffer), afs_printable_VolumeId_lu(tt->volid));
+    }
     TSetRxCall(tt, acid, "Restore");
 
     DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
@@ -1587,7 +1608,7 @@ 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;
 }
 
@@ -1604,8 +1625,8 @@ VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
     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 %" AFS_VOLID_FMT " has been deleted \n",
+           afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -1640,13 +1661,15 @@ VolGetStatus(struct rx_call *acid, afs_int32 atrans,
     struct VolumeDiskData *td;
     struct volser_trans *tt;
 
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
 
     tt = FindTrans(atrans);
     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 %" AFS_VOLID_FMT " has been deleted \n",
+           afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -1658,7 +1681,7 @@ VolGetStatus(struct rx_call *acid, afs_int32 atrans,
        return ENOENT;
     }
 
-    td = &tv->header->diskstuff;
+    td = &(V_disk(tv));
     astatus->volID = td->id;
     astatus->nextUnique = td->uniquifier;
     astatus->type = td->type;
@@ -1709,7 +1732,7 @@ VolSetInfo(struct rx_call *acid, afs_int32 atrans,
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -1721,7 +1744,7 @@ VolSetInfo(struct rx_call *acid, afs_int32 atrans,
        return ENOENT;
     }
 
-    td = &tv->header->diskstuff;
+    td = &(V_disk(tv));
     /*
      * Add more fields as necessary
      */
@@ -1761,15 +1784,18 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
     struct volser_trans *tt;
     int len;
 
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
     /* We need to at least fill it in */
-    *aname = (char *)malloc(1);
+    *aname = malloc(1);
     if (!*aname)
        return ENOMEM;
     tt = FindTrans(atrans);
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -1781,14 +1807,14 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
        return ENOENT;
     }
 
-    td = &tv->header->diskstuff;
+    td = &(V_disk(tv));
     len = strlen(td->name) + 1;        /* don't forget the null */
     if (len >= SIZE) {
         TClearRxCall(tt);
        TRELE(tt);
        return E2BIG;
     }
-    *aname = (char *)realloc(*aname, len);
+    *aname = realloc(*aname, len);
     strcpy(*aname, td->name);
     TClearRxCall(tt);
     if (TRELE(tt))
@@ -1801,7 +1827,7 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
  * - a noop now !*/
 afs_int32
 SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
-                    afs_uint32 parentId, afs_uint32 cloneId)
+                    VolumeId parentId, VolumeId cloneId)
 {
     return 0;
 }
@@ -1825,6 +1851,9 @@ VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
     char namehead[9];
     int i;
 
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
     strcpy(namehead, "/vicep");        /*7 including null terminator */
 
     /* Just return attached partitions. */
@@ -1857,6 +1886,9 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
     struct DiskPartition64 *dp;
     int i, j = 0;
 
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
     strcpy(namehead, "/vicep");        /*7 including null terminator */
 
     /* Only report attached partitions */
@@ -1881,10 +1913,10 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
            partList.partId[j++] = i;
     }
     if (j > 0) {
-       pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
+       pEntries->partEntries_val = malloc(j * sizeof(int));
        if (!pEntries->partEntries_val)
            return ENOMEM;
-       memcpy((char *)pEntries->partEntries_val, (char *)&partList,
+       memcpy(pEntries->partEntries_val, partList.partId,
                j * sizeof(int));
        pEntries->partEntries_len = j;
     } else {
@@ -1895,44 +1927,30 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
 
 }
 
-/*extract the volume id from string vname. Its of the form " V0*<id>.vol  "*/
-afs_int32
-ExtractVolId(char vname[])
-{
-    int i;
-    char name[VOLSER_MAXVOLNAME + 1];
-
-    strcpy(name, vname);
-    i = 0;
-    while (name[i] == 'V' || name[i] == '0')
-       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*/
-int
-GetNextVol(DIR * dirp, char *volname, afs_uint32 * volid)
+/*
+ * Scan a directory for possible volume headers.
+ * in: DIR *dirp               -- a directory handle from opendir()
+ * out: char *volname          -- set to name of directory entry
+ *      afs_uint32 *volid      -- set to volume ID parsed from name
+ * returns:
+ *  true if volname and volid have been set to valid values
+ *  false if we got to the end of the directory
+ */
+static int
+GetNextVol(DIR *dirp, char *volname, VolumeId *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)) {
-           *volid = ExtractVolId(dp->d_name);
+    while ((dp = readdir(dirp)) != NULL) {
+       /* could be optimized on platforms with dp->d_namlen */
+       if (dp->d_name[0] == 'V' && strlen(dp->d_name) == VHDRNAMELEN
+               && strcmp(&(dp->d_name[VFORMATDIGITS + 1]), VHDREXT) == 0) {
+           *volid = VolumeNumber(dp->d_name);
            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 */
+           return 1;
        }
-    } else {
-       strcpy(volname, "EOD");
-       return 0;               /*end of directory */
     }
-
+    return 0;
 }
 
 /**
@@ -1995,7 +2013,7 @@ static int
 FillVolInfo(Volume * vp, volint_info_handle_t * handle)
 {
     unsigned int numStatBytes, now;
-    struct VolumeDiskData *hdr = &vp->header->diskstuff;
+    struct VolumeDiskData *hdr = &(V_disk(vp));
 
     /*read in the relevant info */
     strcpy((char *)VOLINT_INFO_PTR(handle, name), hdr->name);
@@ -2138,7 +2156,7 @@ FillVolInfo(Volume * vp, volint_info_handle_t * handle)
  * @internal
  */
 static int
-GetVolObject(afs_uint32 volumeId, char * pname, Volume ** vp)
+GetVolObject(VolumeId volumeId, char * pname, Volume ** vp)
 {
     int code;
     SYNC_response res;
@@ -2194,7 +2212,7 @@ typedef enum {
  */
 static int
 GetVolInfo(afs_uint32 partId,
-          afs_uint32 volumeId,
+          VolumeId volumeId,
           char * pname,
           char * volname,
           volint_info_handle_t * handle,
@@ -2219,16 +2237,26 @@ GetVolInfo(afs_uint32 partId,
     ttc = NewTrans(volumeId, partId);
     if (!ttc) {
        code = -3;
-       VOLINT_INFO_STORE(handle, status, VOLSERVOLBUSY);
+       VOLINT_INFO_STORE(handle, status, VBUSY);
        VOLINT_INFO_STORE(handle, volid, volumeId);
        goto drop;
     }
 
     /* Get volume from volserver */
-    tv = VAttachVolumeByName_retry(&error, pname, volname, V_PEEK);
+    if (mode == VOL_INFO_LIST_MULTIPLE)
+       tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
+    else {
+#ifdef AFS_DEMAND_ATTACH_FS
+       int mode = V_PEEK;
+#else
+       int mode = V_READONLY;   /* informs the fileserver to update the volume headers. */
+#endif
+       tv = VAttachVolumeByName_retry(&error, pname, volname, mode);
+    }
+
     if (error) {
-       Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
-           volumeId, pname, volname, error);
+       Log("1 Volser: GetVolInfo: Could not attach volume %" AFS_VOLID_FMT " (%s:%s) error=%d\n",
+           afs_printable_VolumeId_lu(volumeId), pname, volname, error);
        goto drop;
     }
 
@@ -2239,25 +2267,25 @@ GetVolInfo(afs_uint32 partId,
      *   -- tkeiser 11/28/2007
      */
 
-    if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
+    if (V_destroyMe(tv) == 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);
+           Log("1 Volser: GetVolInfo: Volume %" AFS_VOLID_FMT " (%s:%s) will be destroyed on next salvage\n",
+               afs_printable_VolumeId_lu(volumeId), pname, volname);
 
        default:
            goto drop;
        }
     }
 
-    if (tv->header->diskstuff.needsSalvaged) {
+    if (V_needsSalvaged(tv)) {
        /*this volume will be salvaged */
-       Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
-           volumeId, pname, volname);
+       Log("1 Volser: GetVolInfo: Volume %" AFS_VOLID_FMT " (%s:%s) needs to be salvaged\n",
+           afs_printable_VolumeId_lu(volumeId), pname, volname);
     }
 
 #ifdef AFS_DEMAND_ATTACH_FS
@@ -2301,8 +2329,8 @@ GetVolInfo(afs_uint32 partId,
        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);
+           Log("1 Volser: GetVolInfo: Could not detach volume %" AFS_VOLID_FMT " (%s:%s)\n",
+               afs_printable_VolumeId_lu(volumeId), pname, volname);
        }
     }
     if (ttc) {
@@ -2316,7 +2344,7 @@ GetVolInfo(afs_uint32 partId,
 /*return the header information about the <volid> */
 afs_int32
 SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,
-                     afs_uint32 volumeId, volEntries *volumeInfo)
+                     VolumeId volumeId, volEntries *volumeInfo)
 {
     afs_int32 code;
 
@@ -2327,20 +2355,21 @@ SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,
 
 static afs_int32
 VolListOneVolume(struct rx_call *acid, afs_int32 partid,
-                 afs_uint32 volumeId, volEntries *volumeInfo)
+                 VolumeId volumeId, volEntries *volumeInfo)
 {
     struct DiskPartition64 *partP;
     char pname[9], volname[20];
     DIR *dirp;
-    afs_uint32 volid;
+    VolumeId volid;
     int found = 0;
-    int code;
     volint_info_handle_t handle;
 
-    volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
+    volumeInfo->volEntries_val = calloc(1, sizeof(volintInfo));
     if (!volumeInfo->volEntries_val)
        return ENOMEM;
-    memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
 
     volumeInfo->volEntries_len = 1;
     if (GetPartName(partid, pname))
@@ -2351,21 +2380,11 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid,
     if (dirp == NULL)
        return VOLSERILLEGAL_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 */
-           GetNextVol(dirp, volname, &volid);
-           continue;           /*back to while loop */
-       }
-
+    while (GetNextVol(dirp, volname, &volid)) {
        if (volid == volumeId) {        /*copy other things too */
            found = 1;
            break;
        }
-
-       GetNextVol(dirp, volname, &volid);
     }
 
     if (found) {
@@ -2376,12 +2395,16 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid,
        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);
+       /* The return code from GetVolInfo is ignored; there is no error from
+        * it that results in the whole call being aborted. Any volume
+        * attachment failures are reported in 'status' field in the
+        * volumeInfo payload. */
+       GetVolInfo(partid,
+                  volid,
+                  pname,
+                  volname,
+                  &handle,
+                  VOL_INFO_LIST_SINGLE);
     }
 
     closedir(dirp);
@@ -2413,7 +2436,7 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid,
 
 afs_int32
 SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
-                     afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
+                     VolumeId a_volID, volXEntries *a_volumeXInfoP)
 {
     afs_int32 code;
 
@@ -2424,29 +2447,28 @@ SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
 
 static afs_int32
 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
-                  afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
+                  VolumeId a_volID, volXEntries *a_volumeXInfoP)
 {                              /*SAFSVolXListOneVolume */
 
     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 */
+    VolumeId currVolID;                /*Current volume ID */
     int found = 0;             /*Did we find the volume we need? */
-    int code;
     volint_info_handle_t handle;
 
+    if (!afsconf_CheckRestrictedQuery(tdir, a_rxCidP, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
     /*
      * 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 = calloc(1, sizeof(volintXInfo));
     if (!a_volumeXInfoP->volXEntries_val)
        return ENOMEM;
-    memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
 
     a_volumeXInfoP->volXEntries_len = 1;
-    code = ENODEV;
 
     /*
      * If the partition name we've been given is bad, bogue out.
@@ -2464,23 +2486,13 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
     if (dirp == NULL)
        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.
      */
-    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, "")) {
-           GetNextVol(dirp, volname, &currVolID);
-           continue;
-       }
-
+    while (GetNextVol(dirp, volname, &currVolID)) {
        if (currVolID == a_volID) {
            /*
             * We found the volume entry we're interested.  Pull out the
@@ -2490,8 +2502,6 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
            found = 1;
            break;
        }                       /*Found desired volume */
-
-       GetNextVol(dirp, volname, &currVolID);
     }
 
     if (found) {
@@ -2502,13 +2512,16 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
        handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
        handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
 
-       code = GetVolInfo(a_partID,
-                         a_volID,
-                         pname,
-                         volname,
-                         &handle,
-                         VOL_INFO_LIST_SINGLE);
-
+       /* The return code from GetVolInfo is ignored; there is no error from
+        * it that results in the whole call being aborted. Any volume
+        * attachment failures are reported in 'status' field in the
+        * volumeInfo payload. */
+       GetVolInfo(a_partID,
+                  a_volID,
+                  pname,
+                  volname,
+                  &handle,
+                  VOL_INFO_LIST_SINGLE);
     }
 
     /*
@@ -2541,15 +2554,16 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
     afs_int32 allocSize = 1000;        /*to be changed to a larger figure */
     char pname[9], volname[20];
     DIR *dirp;
-    afs_uint32 volid;
+    VolumeId volid;
     int code;
     volint_info_handle_t handle;
 
-    volumeInfo->volEntries_val =
-       (volintInfo *) malloc(allocSize * sizeof(volintInfo));
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
+    volumeInfo->volEntries_val = calloc(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;
@@ -2560,15 +2574,8 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
     dirp = opendir(VPartitionPath(partP));
     if (dirp == NULL)
        return VOLSERILLEGAL_PARTITION;
-    strcpy(volname, "");
-
-    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 */
-       }
 
+    while (GetNextVol(dirp, volname, &volid)) {
        if (flags) {            /*copy other things too */
 #ifndef AFS_PTHREAD_ENV
            IOMGR_Poll();       /*make sure that the client does not time out */
@@ -2584,9 +2591,8 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
                              volname,
                              &handle,
                              VOL_INFO_LIST_MULTIPLE);
-           if (code == -2) { /* DESTROY_ME flag set */
-               goto drop2;
-           }
+           if (code == -2)     /* DESTROY_ME flag set */
+               continue;
        } else {
            pntr->volid = volid;
            /*just volids are needed */
@@ -2597,9 +2603,8 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
        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));
+           pntr = realloc(volumeInfo->volEntries_val,
+                          allocSize * sizeof(volintInfo));
            if (pntr == NULL) {
                closedir(dirp);
                return VOLSERNO_MEMORY;
@@ -2607,12 +2612,7 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
            volumeInfo->volEntries_val = pntr;  /* point to new block */
            /* set pntr to the right position */
            pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
-
        }
-
-      drop2:
-       GetNextVol(dirp, volname, &volid);
-
     }
 
     closedir(dirp);
@@ -2667,19 +2667,20 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
     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 */
+    VolumeId volid;            /*Current volume ID */
     int code;
     volint_info_handle_t handle;
 
+    if (!afsconf_CheckRestrictedQuery(tdir, a_rxCidP, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
     /*
      * Allocate a large array of extended volume info structures, then
      * set it up for action.
      */
-    a_volumeXInfoP->volXEntries_val =
-       (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
+    a_volumeXInfoP->volXEntries_val = calloc(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;
@@ -2699,23 +2700,7 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
     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.
-     */
-    while (strcmp(volname, "EOD")) {
-
-       /*
-        * If this is not a volume, move on to the next entry in the
-        * partition's directory.
-        */
-       if (!strcmp(volname, "")) {
-           GetNextVol(dirp, volname, &volid);
-           continue;
-       }
-
+    while (GetNextVol(dirp, volname, &volid)) {
        if (a_flags) {
            /*
             * Full info about the volume desired.  Poll to make sure the
@@ -2734,9 +2719,8 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
                              volname,
                              &handle,
                              VOL_INFO_LIST_MULTIPLE);
-           if (code == -2) { /* DESTROY_ME flag set */
-               goto drop2;
-           }
+           if (code == -2)     /* DESTROY_ME flag set */
+               continue;
        } else {
            /*
             * Just volume IDs are needed.
@@ -2776,10 +2760,7 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
                a_volumeXInfoP->volXEntries_val +
                a_volumeXInfoP->volXEntries_len;
        }
-
-      drop2:
-       GetNextVol(dirp, volname, &volid);
-    }                          /*Sweep through the partition directory */
+    }
 
     /*
      * We've examined all entries in the partition directory.  Close it,
@@ -2809,8 +2790,11 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
     afs_int32 allocSize = 50;
     struct volser_trans *tt, *nt, *allTrans;
 
+    if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel))
+        return VOLSERBAD_ACCESS;
+
     transInfo->transDebugEntries_val =
-       (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
+       malloc(allocSize * sizeof(transDebugInfo));
     if (!transInfo->transDebugEntries_val)
        return ENOMEM;
     pntr = transInfo->transDebugEntries_val;
@@ -2836,21 +2820,20 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
        pntr->callValid = 0;
        if (tt->rxCallPtr) {    /*record call related info */
            pntr->callValid = 1;
+#if 0
            pntr->readNext = tt->rxCallPtr->rnext;
            pntr->transmitNext = tt->rxCallPtr->tnext;
            pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
            pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
+#endif
        }
         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));
+           pntr = realloc(transInfo->transDebugEntries_val,
+                          allocSize * sizeof(transDebugInfo));
            transInfo->transDebugEntries_val = pntr;
            pntr =
                transInfo->transDebugEntries_val +
@@ -2867,8 +2850,8 @@ done:
 
 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 type, afs_uint32 pId, VolumeId cloneId,
+                  VolumeId backupId)
 {
     afs_int32 code;
 
@@ -2881,8 +2864,8 @@ SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 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)
+              afs_int32 type, VolumeId pId, VolumeId cloneId,
+              VolumeId backupId)
 {
     struct Volume *tv;
     Error error = 0;
@@ -2898,7 +2881,7 @@ VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -2954,7 +2937,7 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
     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 %" AFS_VOLID_FMT " has been deleted \n", afs_printable_VolumeId_lu(tt->volid));
        TRELE(tt);
        return ENOENT;
     }
@@ -2982,7 +2965,7 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
 
 afs_int32
 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
-                          afs_uint32 volumeId)
+                          VolumeId volumeId)
 {
 #ifdef AFS_NT40_ENV
     return EXDEV;
@@ -2993,7 +2976,7 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
     char pname[16], volname[20];
     struct DiskPartition64 *partP;
     afs_int32 ret = ENODEV;
-    afs_uint32 volid;
+    VolumeId volid;
 
     if (!afsconf_SuperUser(tdir, acid, caller))
        return VOLSERBAD_ACCESS;        /*not a super user */
@@ -3004,15 +2987,9 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
     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 */
-        }
-
+    while (GetNextVol(dirp, volname, &volid)) {
        if (volid == volumeId) {        /*copy other things too */
 #ifndef AFS_PTHREAD_ENV
             IOMGR_Poll();       /*make sure that the client doesnot time out */
@@ -3028,13 +3005,10 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
 #endif
            break;
        }
-       GetNextVol(dirp, volname, &volid);
     }
 
-    if (ttc) {
+    if (ttc)
         DeleteTrans(ttc, 1);
-        ttc = (struct volser_trans *)0;
-    }
 
     closedir(dirp);
     return ret;
@@ -3069,7 +3043,7 @@ SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
 }
 
 afs_int32
-SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
+SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 ovid, afs_uint32 onew,
                   afs_uint32 where, afs_int32 verbose)
 {
 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
@@ -3078,6 +3052,8 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
     struct volser_trans *tt = 0, *tt2 = 0;
     char caller[MAXKTCNAMELEN];
     char line[128];
+    VolumeId new = onew;
+    VolumeId vid = ovid;
 
     if (!afsconf_SuperUser(tdir, acall, caller))
         return EPERM;
@@ -3098,12 +3074,14 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
     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);
+            sprintf(line, "Volumes %" AFS_VOLID_FMT " and %" AFS_VOLID_FMT " are not in the same partition, aborted.\n",
+                   afs_printable_VolumeId_lu(vid),
+                   afs_printable_VolumeId_lu(new));
             rx_Write(acall, line, strlen(line));
         }
         if (V_uniquifier(newvol) != 2) {
-            sprintf(line, "Volume %u is not freshly created, aborted.\n", new);
+            sprintf(line, "Volume %" AFS_VOLID_FMT " is not freshly created, aborted.\n",
+                   afs_printable_VolumeId_lu(new));
             rx_Write(acall, line, strlen(line));
         }
         line[0] = 0;
@@ -3114,7 +3092,8 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
     }
     tt = NewTrans(vid, V_device(vol));
     if (!tt) {
-        sprintf(line, "Couldn't create transaction for %u, aborted.\n", vid);
+        sprintf(line, "Couldn't create transaction for %" AFS_VOLID_FMT ", aborted.\n",
+               afs_printable_VolumeId_lu(vid));
         rx_Write(acall, line, strlen(line));
         line[0] = 0;
         rx_Write(acall, line, 1);
@@ -3130,7 +3109,8 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
 
     tt2 = NewTrans(new, V_device(newvol));
     if (!tt2) {
-        sprintf(line, "Couldn't create transaction for %u, aborted.\n", new);
+        sprintf(line, "Couldn't create transaction for %" AFS_VOLID_FMT ", aborted.\n",
+               afs_printable_VolumeId_lu(new));
         rx_Write(acall, line, strlen(line));
         line[0] = 0;
         rx_Write(acall, line, 1);