volser-retry-transaction-creation-20090526
[openafs.git] / src / volser / volprocs.c
index 15f71ee..f289fa4 100644 (file)
@@ -5,6 +5,8 @@
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * Portions Copyright (c) 2007-2008 Sine Nomine Associates
  */
 
 #include <afsconfig.h>
@@ -15,8 +17,10 @@ RCSID
 
 #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
@@ -25,14 +29,6 @@ RCSID
 #include <unistd.h>
 #endif
 
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
 #include <dirent.h>
 #include <sys/stat.h>
 #include <rx/xdr.h>
@@ -49,7 +45,6 @@ RCSID
 #include <afs/nfs.h>
 #include <lwp.h>
 #include <lock.h>
-#include <afs/auth.h>
 #include <afs/cellconfig.h>
 #include <afs/keys.h>
 #include <ubik.h>
@@ -59,8 +54,10 @@ RCSID
 #endif
 #include <afs/vnode.h>
 #include <afs/volume.h>
+#include <afs/volume_inline.h>
 #include <afs/partition.h>
 #include "vol.h"
+#include <afs/daemon_com.h>
 #include <afs/fssync.h>
 #include <afs/acl.h>
 #include "afs/audit.h"
@@ -69,11 +66,13 @@ RCSID
 #include "volser.h"
 #include "volint.h"
 
-#include <volser_prototypes.h>
+#include "volser_prototypes.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);
@@ -92,10 +91,9 @@ afs_int32 VolPartitionInfo(), VolNukeVolume(), VolCreateVolume(),
 VolDeleteVolume(), VolClone();
 afs_int32 VolReClone(), VolTransCreate(), VolGetNthVolume(), VolGetFlags(),
 VolForward(), VolDump();
-afs_int32 VolForwardMultiple();
 afs_int32 VolRestore(), VolEndTrans(), VolSetForwarding(), VolGetStatus(),
 VolSetInfo(), VolGetName();
-afs_int32 VolSignalRestore(), VolListPartitions(), VolListOneVolume(),
+afs_int32 VolListPartitions(), VolListOneVolume(),
 VolXListOneVolume(), VolXListVolumes();
 afs_int32 VolListVolumes(), XVolListPartitions(), VolMonitor(),
 VolSetIdsTypes(), VolSetDate(), VolSetFlags();
@@ -104,11 +102,11 @@ VolSetIdsTypes(), VolSetDate(), VolSetFlags();
 int 
 VPFullUnlock()
 {
-    register struct DiskPartition *tp;
+    register struct DiskPartition64 *tp;
     for (tp = DiskPartitionList; tp; tp = tp->next) {
-       if (tp->lock_fd != -1) {
+       if (tp->lock_fd != INVALID_FD) {
            close(tp->lock_fd); /* releases flock held on this partition */
-           tp->lock_fd = -1;
+           tp->lock_fd = INVALID_FD;
        }
     }
     return 0;
@@ -153,7 +151,7 @@ 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;
@@ -184,7 +182,7 @@ ConvertPartition(int apartno, char *aname, int asize)
 
 /* 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)
+XAttachVolume(afs_int32 *error, afs_uint32 avolid, afs_int32 apartid, int amode)
 {
     char pbuf[30], vbuf[20];
     register struct Volume *tv;
@@ -197,7 +195,7 @@ XAttachVolume(afs_int32 *error, afs_int32 avolid, afs_int32 apartid, int amode)
        *error = EINVAL;
        return NULL;
     }
-    tv = VAttachVolumeByName(error, pbuf, vbuf, amode);
+    tv = VAttachVolumeByName((Error *)error, pbuf, vbuf, amode);
     return tv;
 }
 
@@ -209,14 +207,16 @@ ViceCreateRoot(Volume *vp)
     struct acl_accessList *ACL;
     ViceFid did;
     Inode inodeNumber, nearInode;
-    char buf[SIZEOF_LARGEDISKVNODE];
-    struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
+    struct VnodeDiskObject *vnode;
     struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
     IHandle_t *h;
     FdHandle_t *fdP;
     int code;
     afs_fsize_t length;
 
+    vnode = (struct VnodeDiskObject *)malloc(SIZEOF_LARGEDISKVNODE);
+    if (!vnode)
+       return ENOMEM;
     memset(vnode, 0, SIZEOF_LARGEDISKVNODE);
 
     V_pref(vp, nearInode);
@@ -231,9 +231,9 @@ ViceCreateRoot(Volume *vp)
     did.Vnode = (VnodeId) 1;
     did.Unique = 1;
 
-    assert(!(MakeDir(&dir, &did, &did)));
+    assert(!(MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
     DFlush();                  /* flush all modified dir buffers out */
-    DZap(&dir);                        /* Remove all buffers for this dir */
+    DZap((afs_int32 *)&dir);                   /* Remove all buffers for this dir */
     length = Length(&dir);     /* Remember size of this directory */
 
     FidZap(&dir);              /* Done with the dir handle obtained via SetSalvageDirHandle() */
@@ -281,6 +281,7 @@ ViceCreateRoot(Volume *vp)
     VNDISK_GET_LEN(length, vnode);
     V_diskused(vp) = nBlocks(length);
 
+    free(vnode);
     return 1;
 }
 
@@ -289,6 +290,27 @@ SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
                     *partition)
 {
     afs_int32 code;
+    struct diskPartition64 *dp = (struct diskPartition64 *)
+       malloc(sizeof(struct diskPartition64));
+
+    code = VolPartitionInfo(acid, pname, dp);
+    if (!code) {
+       strncpy(partition->name, dp->name, 32);
+       strncpy(partition->devName, dp->devName, 32);
+       partition->lock_fd = dp->lock_fd;
+       partition->free=RoundInt64ToInt32(dp->free);
+       partition->minFree=RoundInt64ToInt32(dp->minFree);
+    }
+    free(dp);
+    osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
+    return code;
+}
+
+afs_int32
+SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64 
+                    *partition)
+{
+    afs_int32 code;
 
     code = VolPartitionInfo(acid, pname, partition);
     osi_auditU(acid, VS_ParInfEvent, code, AUD_STR, pname, AUD_END);
@@ -296,10 +318,10 @@ SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
 }
 
 afs_int32
-VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition 
+VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64 
                 *partition)
 {
-    register struct DiskPartition *dp;
+    register struct DiskPartition64 *dp;
 
 /*
     if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
@@ -309,7 +331,7 @@ VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
     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;
@@ -319,7 +341,7 @@ VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
 
 /* 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;
 
@@ -329,9 +351,8 @@ SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
 }
 
 afs_int32
-VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
+VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
 {
-    register char *tp;
     char partName[50];
     afs_int32 error;
     register afs_int32 code;
@@ -344,10 +365,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.
@@ -367,7 +386,7 @@ VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_int32 avolID)
  */
 afs_int32
 SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname, 
-                   afs_int32 atype, afs_int32 aparent, afs_int32 *avolid, 
+                   afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid, 
                    afs_int32 *atrans)
 {
     afs_int32 code;
@@ -382,13 +401,14 @@ SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
 
 afs_int32
 VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname, 
-                   afs_int32 atype, afs_int32 aparent, afs_int32 *avolid, 
+                   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;
+    afs_uint32 volumeID;
+    afs_int32 doCreateRoot = 1;
     register struct volser_trans *tt;
     char ppath[30];
     char caller[MAXKTCNAMELEN];
@@ -424,11 +444,11 @@ VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
     if (error) {
        Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
        LogError(error);
-       DeleteTrans(tt);
+       DeleteTrans(tt, 1);
        return EIO;
     }
     V_uniquifier(vp) = 1;
-    V_creationDate(vp) = V_copyDate(vp);
+    V_updateDate(vp) = V_creationDate(vp) = V_copyDate(vp);
     V_inService(vp) = V_blessed(vp) = 1;
     V_type(vp) = atype;
     AssignVolumeName(&V_disk(vp), aname, 0);
@@ -441,7 +461,7 @@ VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
     if (error) {
        Log("1 Volser: create UpdateVolume failed, code %d\n", error);
        LogError(error);
-       DeleteTrans(tt);
+       DeleteTrans(tt, 1);
        VDetachVolume(&junk, vp);       /* rather return the real error code */
        return error;
     }
@@ -489,6 +509,7 @@ VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
     strcpy(tt->lastProcName, "DeleteVolume");
     tt->rxCallPtr = acid;
     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 */
     tt->vflags |= VTDeleted;   /* so we know not to do anything else to it */
     tt->rxCallPtr = (struct rx_call *)0;
     if (TRELE(tt))
@@ -509,8 +530,8 @@ 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_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;
 
@@ -522,10 +543,10 @@ SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
 }
 
 afs_int32
-VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId, 
-            afs_int32 newType, char *newName, afs_int32 *newNumber)
+VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId, 
+            afs_int32 newType, char *newName, afs_uint32 *newNumber)
 {
-    VolumeId newId;
+    afs_uint32 newId;
     register struct Volume *originalvp, *purgevp, *newvp;
     Error error, code;
     register struct volser_trans *tt, *ttc;
@@ -562,7 +583,7 @@ 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;
@@ -676,7 +697,7 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
        error = VOLSERTRELE_ERROR;
        goto fail;
     }
-    DeleteTrans(ttc);
+    DeleteTrans(ttc, 1);
     return 0;
 
   fail:
@@ -689,13 +710,13 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_int32 purgeId,
        TRELE(tt);
     }
     if (ttc)
-       DeleteTrans(ttc);
+       DeleteTrans(ttc, 1);
     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;
 
@@ -734,7 +755,7 @@ 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;
@@ -824,6 +845,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);
@@ -839,11 +865,11 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
        goto fail;
     }
 
-    DeleteTrans(ttc);
+    DeleteTrans(ttc, 1);
 
     {
-       struct DiskPartition *tpartp = originalvp->partition;
-       FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
+       struct DiskPartition64 *tpartp = originalvp->partition;
+       FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
     }
     return 0;
 
@@ -855,7 +881,7 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
        TRELE(tt);
     }
     if (ttc)
-       DeleteTrans(ttc);
+       DeleteTrans(ttc, 1);
     return error;
 }
 
@@ -864,7 +890,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;
@@ -876,7 +902,7 @@ SAFSVolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
 }
 
 afs_int32
-VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
+VolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
                   afs_int32 iflags, afs_int32 *ttid)
 {
     register struct volser_trans *tt;
@@ -912,7 +938,7 @@ VolTransCreate(struct rx_call *acid, afs_int32 volume, afs_int32 partition,
        /* give up */
        if (tv)
            VDetachVolume(&code, tv);
-       DeleteTrans(tt);
+       DeleteTrans(tt, 1);
        return error;
     }
     tt->volume = tv;
@@ -930,7 +956,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;
@@ -1177,10 +1203,16 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
     struct rx_connection **tcons;
     struct rx_call **tcalls;
     struct Volume *vp;
-    int i, nconns, is_incremental;
+    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 */
@@ -1195,15 +1227,19 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
     vp = tt->volume;
     strcpy(tt->lastProcName, "ForwardMulti");
 
-    /* (fromDate == 0) ==> incremental dump */
+    /* (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);
@@ -1278,13 +1314,23 @@ SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
 {
     afs_int32 code;
 
-    code = VolDump(acid, fromTrans, fromDate);
+    code = VolDump(acid, fromTrans, fromDate, 0);
+    osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
+    return code;
+}
+
+afs_int32
+SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
+{
+    afs_int32 code;
+
+    code = VolDump(acid, fromTrans, fromDate, flags);
     osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END);
     return code;
 }
 
 afs_int32
-VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
+VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate, afs_int32 flags)
 {
     int code = 0;
     register struct volser_trans *tt;
@@ -1302,7 +1348,8 @@ VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
     }
     strcpy(tt->lastProcName, "Dump");
     tt->rxCallPtr = acid;
-    code = DumpVolume(acid, tt->volume, fromDate, 1);  /* squirt out the volume's data, too */
+    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;
        TRELE(tt);
@@ -1354,8 +1401,7 @@ VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
     DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
 
     code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie);      /* last is incrementalp */
-    FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l);     /*break call backs on the
-                                                                * restored volume */
+    FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
     tt->rxCallPtr = (struct rx_call *)0;
     tcode = TRELE(tt);
 
@@ -1386,7 +1432,7 @@ VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
        return ENOENT;
     }
     *rcode = tt->returnCode;
-    DeleteTrans(tt);           /* this does an implicit TRELE */
+    DeleteTrans(tt, 1);                /* this does an implicit TRELE */
 
     return 0;
 }
@@ -1407,6 +1453,7 @@ VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
 {
     register struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
+    char partName[16];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
        return VOLSERBAD_ACCESS;        /*not a super user */
@@ -1421,7 +1468,10 @@ VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
     }
     strcpy(tt->lastProcName, "SetForwarding");
     tt->rxCallPtr = acid;
-    FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
+    if (volutil_PartitionName2_r(tt->partition, partName, sizeof(partName)) != 0) {
+       partName[0] = '\0';
+    }
+    FSYNC_VolOp(tt->volid, partName, FSYNC_VOL_MOVE, anewsite, NULL);
     tt->rxCallPtr = (struct rx_call *)0;
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
@@ -1539,6 +1589,12 @@ VolSetInfo(struct rx_call *acid, afs_int32 atrans,
        td->maxquota = astatus->maxquota;
     if (astatus->dayUse != -1)
        td->dayUse = astatus->dayUse;
+    if (astatus->creationDate != -1)
+       td->creationDate = astatus->creationDate;
+    if (astatus->updateDate != -1)
+       td->updateDate = astatus->updateDate;
+    if (astatus->spare2 != -1)
+       td->volUpdateCounter = (unsigned int)astatus->spare2;
     VUpdateVolume(&error, tv);
     tt->rxCallPtr = (struct rx_call *)0;
     if (TRELE(tt))
@@ -1565,7 +1621,10 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
     struct volser_trans *tt;
     register int len;
 
-    *aname = NULL;
+    /* We need to at least fill it in */
+    *aname = (char *)malloc(1);
+    if (!*aname)
+       return ENOMEM;
     tt = FindTrans(atrans);
     if (!tt)
        return ENOENT;
@@ -1590,7 +1649,7 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
        TRELE(tt);
        return E2BIG;
     }
-    *aname = (char *)malloc(len);
+    *aname = (char *)realloc(*aname, len);
     strcpy(*aname, td->name);
     tt->rxCallPtr = (struct rx_call *)0;
     if (TRELE(tt))
@@ -1603,7 +1662,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_int32 parentId, afs_int32 cloneId)
+                    afs_uint32 parentId, afs_uint32 cloneId)
 {
     return 0;
 }
@@ -1625,7 +1684,6 @@ afs_int32
 VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
 {
     char namehead[9];
-    int code;
     char i;
 
     strcpy(namehead, "/vicep");        /*7 including null terminator */
@@ -1634,8 +1692,7 @@ VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
     namehead[7] = '\0';
     for (i = 0; i < 26; i++) {
        namehead[6] = i + 'a';
-       if (VGetPartition(namehead, 0))
-           partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
+       partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
     }
 
     return 0;
@@ -1656,16 +1713,18 @@ SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
 afs_int32
 XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
 {
-    struct stat rbuf, pbuf;
     char namehead[9];
     struct partList partList;
-    struct DiskPartition *dp;
+    struct DiskPartition64 *dp;
     int i, j = 0, k;
 
     strcpy(namehead, "/vicep");        /*7 including null terminator */
 
     /* Only report attached partitions */
     for (i = 0; i < VOLMAXPARTS; i++) {
+#ifdef AFS_DEMAND_ATTACH_FS
+       dp = VGetPartitionById(i, 0);
+#else
        if (i < 26) {
            namehead[6] = i + 'a';
            namehead[7] = '\0';
@@ -1676,10 +1735,13 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
            namehead[8] = '\0';
        }
        dp = VGetPartition(namehead, 0);
+#endif
        if (dp)
            partList.partId[j++] = i;
     }
     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;
@@ -1706,7 +1768,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;
 
@@ -1727,10 +1789,383 @@ GetNextVol(DIR * dirp, char *volname, afs_int32 * volid)
 
 }
 
+/**
+ * volint vol info structure type.
+ */
+typedef enum {
+    VOLINT_INFO_TYPE_BASE,  /**< volintInfo type */
+    VOLINT_INFO_TYPE_EXT    /**< volintXInfo type */
+} volint_info_type_t;
+
+/**
+ * handle to various on-wire vol info types.
+ */
+typedef struct {
+    volint_info_type_t volinfo_type;
+    union {
+       void * opaque;
+       volintInfo * base;
+       volintXInfo * ext;
+    } volinfo_ptr;
+} volint_info_handle_t;
+
+/**
+ * store value to a field at the appropriate location in on-wire structure.
+ */
+#define VOLINT_INFO_STORE(handle, name, val) \
+    do { \
+        if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
+            (handle)->volinfo_ptr.base->name = (val); \
+        } else { \
+            (handle)->volinfo_ptr.ext->name = (val); \
+        } \
+    } while(0)
+
+/**
+ * get pointer to appropriate offset of field in on-wire structure.
+ */
+#define VOLINT_INFO_PTR(handle, name) \
+    (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
+     &((handle)->volinfo_ptr.base->name) : \
+     &((handle)->volinfo_ptr.ext->name))
+
+/**
+ * fill in appropriate type of on-wire volume metadata structure.
+ *
+ * @param vp      pointer to volume object
+ * @param handle  pointer to wire format handle object
+ *
+ * @pre vp object must contain header & pending_vol_op structurs (populate if from RPC)
+ * @pre handle object must have a valid pointer and enumeration value
+ *
+ * @note passing a NULL value for vp means that the fileserver doesn't
+ *       know about this particular volume, thus implying it is offline.
+ *
+ * @return operation status
+ *   @retval 0 success
+ *   @retval 1 failure
+ */
+static int
+FillVolInfo(Volume * vp, volint_info_handle_t * handle)
+{
+    unsigned int numStatBytes, now;
+    register struct VolumeDiskData *hdr = &vp->header->diskstuff;
+
+    /*read in the relevant info */
+    strcpy((char *)VOLINT_INFO_PTR(handle, name), hdr->name);
+    VOLINT_INFO_STORE(handle, status, VOK);    /*its ok */
+    VOLINT_INFO_STORE(handle, volid, hdr->id);
+    VOLINT_INFO_STORE(handle, type, hdr->type);        /*if ro volume */
+    VOLINT_INFO_STORE(handle, cloneID, hdr->cloneId);  /*if rw volume */
+    VOLINT_INFO_STORE(handle, backupID, hdr->backupId);
+    VOLINT_INFO_STORE(handle, parentID, hdr->parentId);
+    VOLINT_INFO_STORE(handle, copyDate, hdr->copyDate);
+    VOLINT_INFO_STORE(handle, size, hdr->diskused);
+    VOLINT_INFO_STORE(handle, maxquota, hdr->maxquota);
+    VOLINT_INFO_STORE(handle, filecount, hdr->filecount);
+    now = FT_ApproxTime();
+    if ((now - hdr->dayUseDate) > OneDay) {
+       VOLINT_INFO_STORE(handle, dayUse, 0);
+    } else {
+       VOLINT_INFO_STORE(handle, dayUse, hdr->dayUse);
+    }
+    VOLINT_INFO_STORE(handle, creationDate, hdr->creationDate);
+    VOLINT_INFO_STORE(handle, accessDate, hdr->accessDate);
+    VOLINT_INFO_STORE(handle, updateDate, hdr->updateDate);
+    VOLINT_INFO_STORE(handle, backupDate, hdr->backupDate);
+
+#ifdef AFS_DEMAND_ATTACH_FS
+    /*
+     * for DAFS, we "lie" about volume state --
+     * instead of returning the raw state from the disk header,
+     * we compute state based upon the fileserver's internal
+     * in-core state enumeration value reported to us via fssync,
+     * along with the blessed and inService flags from the header.
+     *   -- tkeiser 11/27/2007
+     */
+
+    /* Conditions that offline status is based on: 
+               volume is unattached state
+               volume state is in (one of several error states)
+               volume not in service
+               volume is not marked as blessed (not on hold)
+               volume in salvage req. state
+               volume needsSalvaged 
+               next op would set volume offline
+               next op would not leave volume online (based on several conditions)
+    */
+    if (!vp ||
+       (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
+       VIsErrorState(V_attachState(vp)) ||
+       !hdr->inService ||
+       !hdr->blessed || 
+       (V_attachState(vp) == VOL_STATE_SALVSYNC_REQ) ||
+       hdr->needsSalvaged ||
+       (vp->pending_vol_op && 
+               (vp->pending_vol_op->com.command == FSYNC_VOL_OFF || 
+               !VVolOpLeaveOnline_r(vp, vp->pending_vol_op) )
+       )
+       ) {
+       VOLINT_INFO_STORE(handle, inUse, 0);
+    } else {
+       VOLINT_INFO_STORE(handle, inUse, 1);
+    }
+#else
+    /* offline status based on program type, where != fileServer enum (1) is offline */
+    if (hdr->inUse == fileServer) {
+       VOLINT_INFO_STORE(handle, inUse, 1);
+    } else {
+       VOLINT_INFO_STORE(handle, inUse, 0);
+    }
+#endif
+
+
+    switch(handle->volinfo_type) {
+       /* NOTE: VOLINT_INFO_STORE not used in this section because values are specific to one volinfo_type */
+    case VOLINT_INFO_TYPE_BASE:
+
+#ifdef AFS_DEMAND_ATTACH_FS
+       /* see comment above where we set inUse bit */
+       if (hdr->needsSalvaged || 
+           (vp && VIsErrorState(V_attachState(vp)))) {
+           handle->volinfo_ptr.base->needsSalvaged = 1;
+       } else {
+           handle->volinfo_ptr.base->needsSalvaged = 0;
+       }
+#else
+       handle->volinfo_ptr.base->needsSalvaged = hdr->needsSalvaged;
+#endif
+       handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
+       handle->volinfo_ptr.base->spare0 = hdr->minquota;
+       handle->volinfo_ptr.base->spare1 = 
+           (long)hdr->weekUse[0] +
+           (long)hdr->weekUse[1] +
+           (long)hdr->weekUse[2] +
+           (long)hdr->weekUse[3] +
+           (long)hdr->weekUse[4] +
+           (long)hdr->weekUse[5] +
+           (long)hdr->weekUse[6];
+       handle->volinfo_ptr.base->flags = 0;
+       handle->volinfo_ptr.base->spare2 = hdr->volUpdateCounter;
+       handle->volinfo_ptr.base->spare3 = 0;
+       break;
+
+
+    case VOLINT_INFO_TYPE_EXT:
+       numStatBytes =
+           4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
+                (4 * VOLINT_STATS_NUM_TIME_FIELDS));
+
+       /*
+        * Copy out the stat fields in a single operation.
+        */
+       if ((now - hdr->dayUseDate) > OneDay) {
+           memset((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
+                  0, numStatBytes);
+       } else {
+           memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
+                  (char *)&(hdr->stat_reads[0]), 
+                  numStatBytes);
+       }
+       break;
+    }
+
+    return 0;
+}
+
+/**
+ * get struct Volume out of the fileserver.
+ *
+ * @param[in] volumeId  volumeId for which we want state information
+ * @param[in] pname     partition name string
+ * @param[inout] vp     pointer to pointer to Volume object which 
+ *                      will be populated (see note)
+ *
+ * @return operation status
+ *   @retval 0         success
+ *   @retval non-zero  failure
+ *
+ * @note if FSYNC_VolOp fails in certain ways, *vp will be set to NULL
+ *
+ * @internal
+ */
+static int
+GetVolObject(afs_uint32 volumeId, char * pname, Volume ** vp)
+{
+    int code;
+    SYNC_response res;
+
+    res.hdr.response_len = sizeof(res.hdr);
+    res.payload.buf = *vp;
+    res.payload.len = sizeof(Volume);
+
+    code = FSYNC_VolOp(volumeId,
+                      pname,
+                      FSYNC_VOL_QUERY,
+                      0,
+                      &res);
+
+    if (code != SYNC_OK) {
+       switch (res.hdr.reason) {
+       case FSYNC_WRONG_PART:
+       case FSYNC_UNKNOWN_VOLID:
+           *vp = NULL;
+           code = SYNC_OK;
+           break;
+       }
+    }
+
+    return code;
+}
+
+/**
+ * mode of volume list operation.
+ */
+typedef enum {
+    VOL_INFO_LIST_SINGLE,   /**< performing a single volume list op */
+    VOL_INFO_LIST_MULTIPLE  /**< performing a multi-volume list op */
+} vol_info_list_mode_t;
+
+/**
+ * abstract interface to populate wire-format volume metadata structures.
+ *
+ * @param[in]  partId    partition id
+ * @param[in]  volumeId  volume id
+ * @param[in]  pname     partition name
+ * @param[in]  volname   volume file name
+ * @param[in]  handle    handle to on-wire volume metadata object
+ * @param[in]  mode      listing mode
+ *
+ * @return operation status
+ *   @retval 0      success
+ *   @retval -2     DESTROY_ME flag is set
+ *   @retval -1     general failure; some data filled in
+ *   @retval -3     couldn't create vtrans; some data filled in
+ */
+static int
+GetVolInfo(afs_uint32 partId,
+          afs_uint32 volumeId,
+          char * pname, 
+          char * volname, 
+          volint_info_handle_t * handle,
+          vol_info_list_mode_t mode)
+{
+    int code = -1;
+    afs_int32 error;
+    struct volser_trans *ttc = NULL;
+    struct Volume *fill_tv, *tv = NULL;
+#ifdef AFS_DEMAND_ATTACH_FS
+    struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf; /* Create a structure, and a pointer to that structure */
+    SYNC_PROTO_BUF_DECL(fs_res_buf); /* Buffer for the pending_vol_op */
+    SYNC_response fs_res; /* Response handle for the pending_vol_op */
+    FSSYNC_VolOp_info pending_vol_op_res; /* Pending vol ops to full in volume */
+
+    /* Set up response handle for pending_vol_op */
+    fs_res.hdr.response_len = sizeof(fs_res.hdr);
+    fs_res.payload.buf = fs_res_buf;
+    fs_res.payload.len = SYNC_PROTO_MAX_LEN;
+#endif
+
+    ttc = NewTrans(volumeId, partId);
+    if (!ttc) {
+       code = -3;
+       VOLINT_INFO_STORE(handle, status, VOLSERVOLBUSY);
+       VOLINT_INFO_STORE(handle, volid, volumeId);
+       goto drop;
+    }
+
+    /* Get volume from volserver */
+    tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
+    if (error) {
+       Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n", 
+           volumeId, pname, volname, error);
+       goto drop;
+    }
+
+    /*
+     * please note that destroyMe and needsSalvaged checks used to be ordered
+     * in the opposite manner for ListVolumes and XListVolumes.  I think it's
+     * more correct to check destroyMe before needsSalvaged.
+     *   -- tkeiser 11/28/2007
+     */
+
+    if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
+       switch (mode) {
+       case VOL_INFO_LIST_MULTIPLE:
+           code = -2;
+           goto drop;
+
+       case VOL_INFO_LIST_SINGLE:
+           Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n", 
+               volumeId, pname, volname);
+
+       default:
+           goto drop;
+       }
+    }
+
+    if (tv->header->diskstuff.needsSalvaged) {
+       /*this volume will be salvaged */
+       Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n", 
+           volumeId, pname, volname);
+    }
+
+#ifdef AFS_DEMAND_ATTACH_FS
+    /* If using DAFS, get volume from fsserver */
+    if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK) {
+       goto drop;
+    }
+
+    /* fs_tv is a shallow copy, must populate certain structures before passing along */
+    if (FSYNC_VolOp(volumeId, pname, FSYNC_VOL_QUERY_VOP, 0, &fs_res) == SYNC_OK) { 
+       /* If we if the pending vol op */
+       memcpy(&pending_vol_op_res, fs_res.payload.buf, sizeof(FSSYNC_VolOp_info));
+       fs_tv->pending_vol_op=&pending_vol_op_res;
+    } else {
+       fs_tv->pending_vol_op=NULL;
+    }
+
+    /* populate the header from the volserver copy */
+    fs_tv->header=tv->header;
+
+    /* When using DAFS, use the fs volume info, populated with required structures */
+    fill_tv = fs_tv;
+#else 
+    /* When not using DAFS, just use the local volume info */
+    fill_tv = tv;
+#endif
+
+    /* ok, we have all the data we need; fill in the on-wire struct */
+    code = FillVolInfo(fill_tv, handle);
+
+ drop:
+    if (code == -1) {
+       VOLINT_INFO_STORE(handle, status, 0);
+       strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
+       VOLINT_INFO_STORE(handle, volid, volumeId);
+    }
+    if (tv) {
+       VDetachVolume(&error, tv);
+       tv = NULL;
+       if (error) {
+           VOLINT_INFO_STORE(handle, status, 0);
+           strcpy((char *)VOLINT_INFO_PTR(handle, name), volname);
+           Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
+               volumeId, pname, volname);
+       }
+    }
+    if (ttc) {
+       DeleteTrans(ttc, 1);
+       ttc = NULL;
+    }
+    return code;
+}
+
+
 /*return the header information about the <volid> */
 afs_int32
-SAFSVolListOneVolume(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;
 
@@ -1740,21 +2175,24 @@ SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
 }
 
 afs_int32
-VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32 
-                    volumeId, volEntries *volumeInfo)
+VolListOneVolume(struct rx_call *acid, afs_int32 partid, 
+                 afs_uint32 volumeId, volEntries *volumeInfo)
 {
     volintInfo *pntr;
-    register struct Volume *tv;
-    struct DiskPartition *partP;
-    struct volser_trans *ttc;
+    struct DiskPartition64 *partP;
     char pname[9], volname[20];
     afs_int32 error = 0;
     DIR *dirp;
-    afs_int32 volid;
+    afs_uint32 volid;
     int found = 0;
-    unsigned int now;
+    int code;
+    volint_info_handle_t handle;
 
     volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
+    if (!volumeInfo->volEntries_val)
+       return ENOMEM;
+    memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
+
     pntr = volumeInfo->volEntries_val;
     volumeInfo->volEntries_len = 1;
     if (GetPartName(partid, pname))
@@ -1764,9 +2202,8 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
     dirp = opendir(VPartitionPath(partP));
     if (dirp == NULL)
        return VOLSERILLEGAL_PARTITION;
+
     strcpy(volname, "");
-    ttc = (struct volser_trans *)0;
-    tv = (Volume *) 0;         /* volume not attached */
 
     while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
 
@@ -1777,102 +2214,30 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
 
        if (volid == volumeId) {        /*copy other things too */
            found = 1;
-#ifndef AFS_PTHREAD_ENV
-           IOMGR_Poll();       /*make sure that the client doesnot time out */
-#endif
-           ttc = NewTrans(volid, partid);
-           if (!ttc) {
-               pntr->status = VBUSY;
-               pntr->volid = volid;
-               goto drop;
-           }
-           tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
-           if (error) {
-               pntr->status = 0;       /*things are messed up */
-               strcpy(pntr->name, volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Could not attach volume %u (%s:%s), error=%d\n", volid, pname, volname, error);
-               goto drop;
-           }
-           if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
-               /*this volume will be salvaged */
-               pntr->status = 0;
-               strcpy(pntr->name, volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Volume %u (%s) will be destroyed on next salvage\n", volid, volname);
-               goto drop;
-           }
-
-           if (tv->header->diskstuff.needsSalvaged) {
-               /*this volume will be salvaged */
-               pntr->status = 0;
-               strcpy(pntr->name, volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
-               goto drop;
-           }
-
-           /*read in the relevant info */
-           pntr->status = VOK; /*its ok */
-           pntr->volid = tv->header->diskstuff.id;
-           strcpy(pntr->name, tv->header->diskstuff.name);
-           pntr->type = tv->header->diskstuff.type;    /*if ro volume */
-           pntr->cloneID = tv->header->diskstuff.cloneId;      /*if rw volume */
-           pntr->backupID = tv->header->diskstuff.backupId;
-           pntr->parentID = tv->header->diskstuff.parentId;
-           pntr->copyDate = tv->header->diskstuff.copyDate;
-           pntr->inUse = tv->header->diskstuff.inUse;
-           pntr->size = tv->header->diskstuff.diskused;
-           pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
-           pntr->destroyMe = tv->header->diskstuff.destroyMe;
-           pntr->maxquota = tv->header->diskstuff.maxquota;
-           pntr->filecount = tv->header->diskstuff.filecount;
-           now = FT_ApproxTime();
-           if (now - tv->header->diskstuff.dayUseDate > OneDay)
-               pntr->dayUse = 0;
-           else
-               pntr->dayUse = tv->header->diskstuff.dayUse;
-           pntr->creationDate = tv->header->diskstuff.creationDate;
-           pntr->accessDate = tv->header->diskstuff.accessDate;
-           pntr->updateDate = tv->header->diskstuff.updateDate;
-           pntr->backupDate = tv->header->diskstuff.backupDate;
-           pntr->spare0 = tv->header->diskstuff.minquota;
-           pntr->spare1 =
-               (long)tv->header->diskstuff.weekUse[0] +
-               (long)tv->header->diskstuff.weekUse[1] +
-               (long)tv->header->diskstuff.weekUse[2] +
-               (long)tv->header->diskstuff.weekUse[3] +
-               (long)tv->header->diskstuff.weekUse[4] +
-               (long)tv->header->diskstuff.weekUse[5] +
-               (long)tv->header->diskstuff.weekUse[6];
-           pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
-           VDetachVolume(&error, tv);  /*free the volume */
-           tv = (Volume *) 0;
-           if (error) {
-               pntr->status = 0;       /*things are messed up */
-               strcpy(pntr->name, volname);
-               Log("1 Volser: ListVolumes: Could not detach volume %s\n",
-                   volname);
-               goto drop;
-           }
+           break;
        }
+
        GetNextVol(dirp, volname, &volid);
     }
-  drop:
-    if (tv) {
-       VDetachVolume(&error, tv);
-       tv = (Volume *) 0;
-    }
-    if (ttc) {
-       DeleteTrans(ttc);
-       ttc = (struct volser_trans *)0;
+
+    if (found) {
+#ifndef AFS_PTHREAD_ENV
+       IOMGR_Poll();   /*make sure that the client does not time out */
+#endif
+
+       handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
+       handle.volinfo_ptr.base = volumeInfo->volEntries_val;
+       
+       code = GetVolInfo(partid, 
+                         volid, 
+                         pname, 
+                         volname,
+                         &handle,
+                         VOL_INFO_LIST_SINGLE);
     }
 
     closedir(dirp);
-    if (found)
-       return 0;
-    else
-       return ENODEV;
+    return (found) ? 0 : ENODEV;
 }
 
 /*------------------------------------------------------------------------
@@ -1900,7 +2265,7 @@ 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)
+                     afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
 {
     afs_int32 code;
 
@@ -1911,22 +2276,17 @@ SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
 
 afs_int32
 VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID, 
-                     afs_int32 a_volID, volXEntries *a_volumeXInfoP)
+                  afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
 {                              /*SAFSVolXListOneVolume */
 
     volintXInfo *xInfoP;       /*Ptr to the extended vol info */
-    register struct Volume *tv;        /*Volume ptr */
-    struct volser_trans *ttc;  /*Volume transaction ptr */
-    struct DiskPartition *partP;       /*Ptr to partition */
+    struct DiskPartition64 *partP;     /*Ptr to partition */
     char pname[9], volname[20];        /*Partition, volume names */
-    afs_int32 error;           /*Error code */
-    afs_int32 code;            /*Return code */
     DIR *dirp;                 /*Partition directory ptr */
-    afs_int32 currVolID;       /*Current volume ID */
+    afs_uint32 currVolID;              /*Current volume ID */
     int found = 0;             /*Did we find the volume we need? */
-    struct VolumeDiskData *volDiskDataP;       /*Ptr to on-disk volume data */
-    int numStatBytes;          /*Num stat bytes to copy per volume */
-    unsigned int now;
+    int code;
+    volint_info_handle_t handle;
 
     /*
      * Set up our pointers for action, marking our structure to hold exactly
@@ -1934,6 +2294,10 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
      */
     a_volumeXInfoP->volXEntries_val =
        (volintXInfo *) malloc(sizeof(volintXInfo));
+    if (!a_volumeXInfoP->volXEntries_val)
+       return ENOMEM;
+    memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
+
     xInfoP = a_volumeXInfoP->volXEntries_val;
     a_volumeXInfoP->volXEntries_len = 1;
     code = ENODEV;
@@ -1954,18 +2318,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.
      */
-    numStatBytes =
-       4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
-            (4 * VOLINT_STATS_NUM_TIME_FIELDS));
-    strcpy(volname, "");
-    ttc = (struct volser_trans *)0;    /*No transaction yet */
-    tv = (Volume *) 0;         /*Volume not yet attached */
-
     while (strcmp(volname, "EOD") && !found) {
        /*
         * If this is not a volume, move on to the next entry in the
@@ -1983,120 +2342,27 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
             * doesn't time out) and to set up a transaction on the volume.
             */
            found = 1;
-#ifndef AFS_PTHREAD_ENV
-           IOMGR_Poll();
-#endif
-           ttc = NewTrans(currVolID, a_partID);
-           if (!ttc) {
-               /*
-                * Couldn't get a transaction on this volume; let our caller
-                * know it's busy.
-                */
-               xInfoP->status = VBUSY;
-               xInfoP->volid = currVolID;
-               goto drop;
-           }
-
-           /*
-            * Attach the volume, give up on the volume if we can't.
-            */
-           tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
-           if (error) {
-               xInfoP->status = 0;     /*things are messed up */
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = currVolID;
-               Log("1 Volser: XListOneVolume: Could not attach volume %u\n",
-                   currVolID);
-               goto drop;
-           }
-
-           /*
-            * Also bag out on this volume if it's been marked as needing a
-            * salvage or to-be-destroyed.
-            */
-           volDiskDataP = &(tv->header->diskstuff);
-           if (volDiskDataP->destroyMe == DESTROY_ME) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = currVolID;
-               Log("1 Volser: XListOneVolume: Volume %u will be destroyed on next salvage\n", currVolID);
-               goto drop;
-           }
-
-           if (volDiskDataP->needsSalvaged) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = currVolID;
-               Log("1 Volser: XListOneVolume: Volume %u needs to be salvaged\n", currVolID);
-               goto drop;
-           }
+           break;
+       }                       /*Found desired volume */
 
-           /*
-            * Pull out the desired info and stuff it into the area we'll be
-            * returning to our caller.
-            */
-           strcpy(xInfoP->name, volDiskDataP->name);
-           xInfoP->volid = volDiskDataP->id;
-           xInfoP->type = volDiskDataP->type;
-           xInfoP->backupID = volDiskDataP->backupId;
-           xInfoP->parentID = volDiskDataP->parentId;
-           xInfoP->cloneID = volDiskDataP->cloneId;
-           xInfoP->status = VOK;
-           xInfoP->copyDate = volDiskDataP->copyDate;
-           xInfoP->inUse = volDiskDataP->inUse;
-           xInfoP->creationDate = volDiskDataP->creationDate;
-           xInfoP->accessDate = volDiskDataP->accessDate;
-           xInfoP->updateDate = volDiskDataP->updateDate;
-           xInfoP->backupDate = volDiskDataP->backupDate;
-           now = FT_ApproxTime();
-           if (now - volDiskDataP->dayUseDate > OneDay)
-               xInfoP->dayUse = 0;
-           else
-               xInfoP->dayUse = volDiskDataP->dayUse;
-           xInfoP->filecount = volDiskDataP->filecount;
-           xInfoP->maxquota = volDiskDataP->maxquota;
-           xInfoP->size = volDiskDataP->diskused;
+       GetNextVol(dirp, volname, &currVolID);
+    }
 
-           /*
-            * Copy out the stat fields in a single operation.
-            */
-           memcpy((char *)&(xInfoP->stat_reads[0]),
-                  (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
+    if (found) {
+#ifndef AFS_PTHREAD_ENV
+       IOMGR_Poll();
+#endif
 
-           /*
-            * We're done copying.  Detach the volume and iterate (at this
-            * point, since we found our volume, we'll then drop out of the
-            * loop).
-            */
-           VDetachVolume(&error, tv);
-           tv = (Volume *) 0;
-           if (error) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               Log("1 Volser: XListOneVolumes Couldn't detach volume %s\n",
-                   volname);
-               goto drop;
-           }
+       handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
+       handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
 
-           /*
-            * At this point, we're golden.
-            */
-           code = 0;
-       }                       /*Found desired volume */
-       GetNextVol(dirp, volname, &currVolID);
-    }
+       code = GetVolInfo(a_partID,
+                         a_volID,
+                         pname,
+                         volname,
+                         &handle,
+                         VOL_INFO_LIST_SINGLE);
 
-    /*
-     * Drop the transaction we have for this volume.
-     */
-  drop:
-    if (tv) {
-       VDetachVolume(&error, tv);
-       tv = (Volume *) 0;
-    }
-    if (ttc) {
-       DeleteTrans(ttc);
-       ttc = (struct volser_trans *)0;
     }
 
     /*
@@ -2104,8 +2370,7 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
      * return the proper value.
      */
     closedir(dirp);
-    return (code);
-
+    return (found) ? 0 : ENODEV;
 }                              /*SAFSVolXListOneVolume */
 
 /*returns all the volumes on partition partid. If flags = 1 then all the 
@@ -2126,18 +2391,21 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
                   volEntries *volumeInfo)
 {
     volintInfo *pntr;
-    register struct Volume *tv;
-    struct DiskPartition *partP;
-    struct volser_trans *ttc;
+    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))
@@ -2148,9 +2416,8 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
     if (dirp == NULL)
        return VOLSERILLEGAL_PARTITION;
     strcpy(volname, "");
+
     while (strcmp(volname, "EOD")) {   /*while there are more partitions in the partition */
-       ttc = (struct volser_trans *)0; /* new one for each pass */
-       tv = (Volume *) 0;      /* volume not attached */
 
        if (!strcmp(volname, "")) {     /* its not a volume, fetch next file */
            GetNextVol(dirp, volname, &volid);
@@ -2159,87 +2426,28 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
 
        if (flags) {            /*copy other things too */
 #ifndef AFS_PTHREAD_ENV
-           IOMGR_Poll();       /*make sure that the client doesnot time out */
+           IOMGR_Poll();       /*make sure that the client does not time out */
 #endif
-           ttc = NewTrans(volid, partid);
-           if (!ttc) {
-               pntr->status = VBUSY;
-               pntr->volid = volid;
-               goto drop;
-           }
-           tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
-           if (error) {
-               pntr->status = 0;       /*things are messed up */
-               strcpy(pntr->name, volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Could not attach volume %u (%s) error=%d\n", volid, volname, error);
-               goto drop;
-           }
-           if (tv->header->diskstuff.needsSalvaged) {
-               /*this volume will be salvaged */
-               pntr->status = 0;
-               strcpy(pntr->name, volname);
-               pntr->volid = volid;
-               Log("1 Volser: ListVolumes: Volume %u (%s) needs to be salvaged\n", volid, volname);
-               goto drop;
-           }
 
-           if (tv->header->diskstuff.destroyMe == DESTROY_ME) {
-               /*this volume will be salvaged */
+           handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
+           handle.volinfo_ptr.base = pntr;
+
+
+           code = GetVolInfo(partid,
+                             volid,
+                             pname,
+                             volname,
+                             &handle,
+                             VOL_INFO_LIST_MULTIPLE);
+           if (code == -2) { /* DESTROY_ME flag set */
                goto drop2;
            }
-           /*read in the relevant info */
-           pntr->status = VOK; /*its ok */
-           pntr->volid = tv->header->diskstuff.id;
-           strcpy(pntr->name, tv->header->diskstuff.name);
-           pntr->type = tv->header->diskstuff.type;    /*if ro volume */
-           pntr->cloneID = tv->header->diskstuff.cloneId;      /*if rw volume */
-           pntr->backupID = tv->header->diskstuff.backupId;
-           pntr->parentID = tv->header->diskstuff.parentId;
-           pntr->copyDate = tv->header->diskstuff.copyDate;
-           pntr->inUse = tv->header->diskstuff.inUse;
-           pntr->size = tv->header->diskstuff.diskused;
-           pntr->needsSalvaged = tv->header->diskstuff.needsSalvaged;
-           pntr->maxquota = tv->header->diskstuff.maxquota;
-           pntr->filecount = tv->header->diskstuff.filecount;
-           now = FT_ApproxTime();
-           if (now - tv->header->diskstuff.dayUseDate > OneDay)
-               pntr->dayUse = 0;
-           else
-               pntr->dayUse = tv->header->diskstuff.dayUse;
-           pntr->creationDate = tv->header->diskstuff.creationDate;
-           pntr->accessDate = tv->header->diskstuff.accessDate;
-           pntr->updateDate = tv->header->diskstuff.updateDate;
-           pntr->backupDate = tv->header->diskstuff.backupDate;
-           pntr->spare0 = tv->header->diskstuff.minquota;
-           pntr->spare1 =
-               (long)tv->header->diskstuff.weekUse[0] +
-               (long)tv->header->diskstuff.weekUse[1] +
-               (long)tv->header->diskstuff.weekUse[2] +
-               (long)tv->header->diskstuff.weekUse[3] +
-               (long)tv->header->diskstuff.weekUse[4] +
-               (long)tv->header->diskstuff.weekUse[5] +
-               (long)tv->header->diskstuff.weekUse[6];
-           pntr->flags = pntr->spare2 = pntr->spare3 = (long)0;
-           VDetachVolume(&error, tv);  /*free the volume */
-           tv = (Volume *) 0;
-           if (error) {
-               pntr->status = 0;       /*things are messed up */
-               strcpy(pntr->name, volname);
-               Log("1 Volser: ListVolumes: Could not detach volume %s\n",
-                   volname);
-               goto drop;
-           }
        } else {
            pntr->volid = volid;
            /*just volids are needed */
        }
 
       drop:
-       if (ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *)0;
-       }
        pntr++;
        volumeInfo->volEntries_len += 1;
        if ((allocSize - volumeInfo->volEntries_len) < 5) {
@@ -2249,15 +2457,7 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
                (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
                                       allocSize * sizeof(volintInfo));
            if (pntr == NULL) {
-               if (tv) {
-                   VDetachVolume(&error, tv);
-                   tv = (Volume *) 0;
-               }
-               if (ttc) {
-                   DeleteTrans(ttc);
-                   ttc = (struct volser_trans *)0;
-               }
-               closedir(dirp);
+               closedir(dirp); 
                return VOLSERNO_MEMORY;
            }
            volumeInfo->volEntries_val = pntr;  /* point to new block */
@@ -2267,21 +2467,11 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
        }
 
       drop2:
-       if (tv) {
-           VDetachVolume(&error, tv);
-           tv = (Volume *) 0;
-       }
-       if (ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *)0;
-       }
        GetNextVol(dirp, volname, &volid);
 
     }
-    closedir(dirp);
-    if (ttc)
-       DeleteTrans(ttc);
 
+    closedir(dirp);
     return 0;
 }
 
@@ -2329,17 +2519,14 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
 {                              /*SAFSVolXListVolumes */
 
     volintXInfo *xInfoP;       /*Ptr to the extended vol info */
-    register struct Volume *tv;        /*Volume ptr */
-    struct DiskPartition *partP;       /*Ptr to partition */
-    struct volser_trans *ttc;  /*Volume transaction ptr */
+    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 */
-    struct VolumeDiskData *volDiskDataP;       /*Ptr to on-disk volume data */
-    int numStatBytes;          /*Num stat bytes to copy per volume */
-    unsigned int now;
+    afs_uint32 volid;          /*Current volume ID */
+    int code;
+    volint_info_handle_t handle;
 
     /*
      * Allocate a large array of extended volume info structures, then
@@ -2347,6 +2534,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;
 
@@ -2365,18 +2556,13 @@ 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.
      */
-    numStatBytes =
-       4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS) +
-            (4 * VOLINT_STATS_NUM_TIME_FIELDS));
-    strcpy(volname, "");
     while (strcmp(volname, "EOD")) {
-       ttc = (struct volser_trans *)0; /*New one for each pass */
-       tv = (Volume *) 0;      /*Volume not yet attached */
 
        /*
         * If this is not a volume, move on to the next entry in the
@@ -2395,106 +2581,27 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
 #ifndef AFS_PTHREAD_ENV
            IOMGR_Poll();
 #endif
-           ttc = NewTrans(volid, a_partID);
-           if (!ttc) {
-               /*
-                * Couldn't get a transaction on this volume; let our caller
-                * know it's busy.
-                */
-               xInfoP->status = VBUSY;
-               xInfoP->volid = volid;
-               goto drop;
-           }
 
-           /*
-            * Attach the volume, give up on this volume if we can't.
-            */
-           tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
-           if (error) {
-               xInfoP->status = 0;     /*things are messed up */
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = volid;
-               Log("1 Volser: XListVolumes: Could not attach volume %u\n",
-                   volid);
-               goto drop;
-           }
+           handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
+           handle.volinfo_ptr.ext = xInfoP;
 
-           /*
-            * Also bag out on this volume if it's been marked as needing a
-            * salvage or to-be-destroyed.
-            */
-           volDiskDataP = &(tv->header->diskstuff);
-           if (volDiskDataP->needsSalvaged) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               xInfoP->volid = volid;
-               Log("1 Volser: XListVolumes: Volume %u needs to be salvaged\n", volid);
-               goto drop;
-           }
-
-           if (volDiskDataP->destroyMe == DESTROY_ME)
+           code = GetVolInfo(a_partID,
+                             volid,
+                             pname,
+                             volname,
+                             &handle,
+                             VOL_INFO_LIST_MULTIPLE);
+           if (code == -2) { /* DESTROY_ME flag set */
                goto drop2;
-
-           /*
-            * Pull out the desired info and stuff it into the area we'll be
-            * returning to our caller.
-            */
-           strcpy(xInfoP->name, volDiskDataP->name);
-           xInfoP->volid = volDiskDataP->id;
-           xInfoP->type = volDiskDataP->type;
-           xInfoP->backupID = volDiskDataP->backupId;
-           xInfoP->parentID = volDiskDataP->parentId;
-           xInfoP->cloneID = volDiskDataP->cloneId;
-           xInfoP->status = VOK;
-           xInfoP->copyDate = volDiskDataP->copyDate;
-           xInfoP->inUse = volDiskDataP->inUse;
-           xInfoP->creationDate = volDiskDataP->creationDate;
-           xInfoP->accessDate = volDiskDataP->accessDate;
-           xInfoP->updateDate = volDiskDataP->updateDate;
-           xInfoP->backupDate = volDiskDataP->backupDate;
-           now = FT_ApproxTime();
-           if (now - volDiskDataP->dayUseDate > OneDay)
-               xInfoP->dayUse = 0;
-           else
-               xInfoP->dayUse = volDiskDataP->dayUse;
-           xInfoP->filecount = volDiskDataP->filecount;
-           xInfoP->maxquota = volDiskDataP->maxquota;
-           xInfoP->size = volDiskDataP->diskused;
-
-           /*
-            * Copy out the stat fields in a single operation.
-            */
-           memcpy((char *)&(xInfoP->stat_reads[0]),
-                  (char *)&(volDiskDataP->stat_reads[0]), numStatBytes);
-
-           /*
-            * We're done copying.  Detach the volume and iterate.
-            */
-           VDetachVolume(&error, tv);
-           tv = (Volume *) 0;
-           if (error) {
-               xInfoP->status = 0;
-               strcpy(xInfoP->name, volname);
-               Log("1 Volser: XListVolumes: Could not detach volume %s\n",
-                   volname);
-               goto drop;
            }
-       } /*Full contents desired */
-       else
+       } else {
            /*
             * Just volume IDs are needed.
             */
            xInfoP->volid = volid;
-
-      drop:
-       /*
-        * Drop the transaction we have for this volume.
-        */
-       if (ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *)0;
        }
 
+      drop:
        /*
         * Bump the pointer in the data area we're building, along with
         * the count of the number of entries it contains.
@@ -2513,14 +2620,6 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
                /*
                 * Bummer, no memory. Bag it, tell our caller what went wrong.
                 */
-               if (tv) {
-                   VDetachVolume(&error, tv);
-                   tv = (Volume *) 0;
-               }
-               if (ttc) {
-                   DeleteTrans(ttc);
-                   ttc = (struct volser_trans *)0;
-               }
                closedir(dirp);
                return (VOLSERNO_MEMORY);
            }
@@ -2535,20 +2634,8 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
                a_volumeXInfoP->volXEntries_val +
                a_volumeXInfoP->volXEntries_len;
        }
-       /*Need more space */
+
       drop2:
-       /*
-        * Detach our current volume and the transaction on it, then move on
-        * to the next volume in the partition directory.
-        */
-       if (tv) {
-           VDetachVolume(&error, tv);
-           tv = (Volume *) 0;
-       }
-       if (ttc) {
-           DeleteTrans(ttc);
-           ttc = (struct volser_trans *)0;
-       }
        GetNextVol(dirp, volname, &volid);
     }                          /*Sweep through the partition directory */
 
@@ -2557,8 +2644,6 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
      * delete our transaction (if any), and go home happy.
      */
     closedir(dirp);
-    if (ttc)
-       DeleteTrans(ttc);
     return (0);
 
 }                              /*SAFSVolXListVolumes */
@@ -2584,6 +2669,8 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
 
     transInfo->transDebugEntries_val =
        (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
+    if (!transInfo->transDebugEntries_val)
+       return ENOMEM;
     pntr = transInfo->transDebugEntries_val;
     transInfo->transDebugEntries_len = 0;
     allTrans = TransList();
@@ -2630,19 +2717,19 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
 }
 
 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;
 
     code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
     osi_auditU(acid, VS_SetIdTyEvent, code, AUD_LONG, atid, AUD_STR, name,
-              AUD_STR, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
+              AUD_LONG, type, AUD_LONG, pId, AUD_LONG, cloneId, AUD_LONG,
               backupId, AUD_END);
     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)
+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;
@@ -2742,116 +2829,65 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
     return error;
 }
 
-#ifdef AFS_NAMEI_ENV
-/* 
- * Inode number format  (from namei_ops.c): 
- * low 26 bits - vnode number - all 1's if volume special file.
- * next 3 bits - tag
- * next 3 bits spare (0's)
- * high 32 bits - uniquifier (regular) or type if spare
- */
-#define NAMEI_VNODEMASK    0x003ffffff
-#define NAMEI_TAGMASK      0x7
-#define NAMEI_TAGSHIFT     26
-#define NAMEI_UNIQMASK     0xffffffff
-#define NAMEI_UNIQSHIFT    32
-#define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
-#define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
-#endif /* AFS_NAMEI_ENV */
-
 afs_int32
 SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
-                          afs_int32 volumeId)
+                          afs_uint32 volumeId)
 {
-#if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
-    DIR *dirp;
-    char pname[16];
-    char volname[20];
-    afs_int32 error = 0;
-    afs_int32 volid;
-    int found = 0;
+#ifdef AFS_NT40_ENV
+    return EXDEV;
+#else
     char caller[MAXKTCNAMELEN];
-    char headername[16];
-    char opath[256];
-    char npath[256];
-    struct VolumeDiskHeader h;
-    int fd;
-    IHandle_t *ih;
-    Inode ino;
-    struct DiskPartition *dp;
+    DIR *dirp;
+    register struct volser_trans *ttc;
+    char pname[16], volname[20];
+    struct DiskPartition64 *partP;
+    afs_int32 ret = ENODEV;
+    afs_uint32 volid;
 
     if (!afsconf_SuperUser(tdir, acid, caller))
        return VOLSERBAD_ACCESS;        /*not a super user */
     if (GetPartName(partId, pname))
-       return VOLSERILLEGAL_PARTITION;
-    dirp = opendir(pname);
+        return VOLSERILLEGAL_PARTITION;
+    if (!(partP = VGetPartition(pname, 0)))
+        return VOLSERILLEGAL_PARTITION;
+    dirp = opendir(VPartitionPath(partP));
     if (dirp == NULL)
        return VOLSERILLEGAL_PARTITION;
     strcpy(volname, "");
+    ttc = (struct volser_trans *)0;
 
-    while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
-       GetNextVol(dirp, volname, &volid);
-       if (strcmp(volname, "")) {      /* its a volume */
-           if (volid == volumeId)
-               found = 1;
+    while (strcmp(volname, "EOD")) {
+       if (!strcmp(volname, "")) {     /* its not a volume, fetch next file */
+            GetNextVol(dirp, volname, &volid);
+            continue;           /*back to while loop */
+        }
+       
+       if (volid == volumeId) {        /*copy other things too */
+#ifndef AFS_PTHREAD_ENV
+            IOMGR_Poll();       /*make sure that the client doesnot time out */
+#endif
+            ttc = NewTrans(volumeId, partId);
+            if (!ttc) {
+               return VOLSERVOLBUSY;
+            }
+#ifdef AFS_NAMEI_ENV
+           ret = namei_ConvertROtoRWvolume(pname, volumeId);
+#else
+           ret = inode_ConvertROtoRWvolume(pname, volumeId);
+#endif
+           break;
        }
+       GetNextVol(dirp, volname, &volid);
     }
-    if (!found)
-       return ENOENT;
-    (void)afs_snprintf(headername, sizeof headername, VFORMAT, volumeId);
-    (void)afs_snprintf(opath, sizeof opath, "%s/%s", pname, headername);
-    fd = open(opath, O_RDONLY);
-    if (fd < 0) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't open header for RO-volume %lu.\n", volumeId);
-       return ENOENT;
-    }
-    if (read(fd, &h, sizeof(h)) != sizeof(h)) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't read header for RO-volume %lu.\n", volumeId);
-       close(fd);
-       return EIO;
-    }
-    close(fd);
-    FSYNC_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
-
-    for (dp = DiskPartitionList; dp && strcmp(dp->name, pname);
-        dp = dp->next);
-    if (!dp) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't find DiskPartition for %s\n", pname);
-       return EIO;
-    }
-    ino = namei_MakeSpecIno(h.parent, VI_LINKTABLE);
-    IH_INIT(ih, dp->device, h.parent, ino);
-
-    error = namei_ConvertROtoRWvolume(ih, volumeId);
-    if (error)
-       return error;
-    h.id = h.parent;
-    h.volumeInfo_hi = h.id;
-    h.smallVnodeIndex_hi = h.id;
-    h.largeVnodeIndex_hi = h.id;
-    h.linkTable_hi = h.id;
-    (void)afs_snprintf(headername, sizeof headername, VFORMAT, h.id);
-    (void)afs_snprintf(npath, sizeof npath, "%s/%s", pname, headername);
-    fd = open(npath, O_CREAT | O_EXCL | O_RDWR, 0644);
-    if (fd < 0) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't create header for RW-volume %lu.\n", h.id);
-       return EIO;
-    }
-    if (write(fd, &h, sizeof(h)) != sizeof(h)) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't write header for RW-volume %lu.\n", h.id);
-       close(fd);
-       return EIO;
-    }
-    close(fd);
-    if (unlink(opath) < 0) {
-       Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
+    
+    if (ttc) {
+        DeleteTrans(ttc, 1);
+        ttc = (struct volser_trans *)0;
     }
-    FSYNC_askfs(volumeId, pname, FSYNC_DONE, 0);
-    FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
-    return 0;
-#else /* AFS_NAMEI_ENV */
-    return EINVAL;
-#endif /* AFS_NAMEI_ENV */
+    
+    closedir(dirp);
+    return ret;
+#endif
 }
 
 afs_int32
@@ -2882,6 +2918,91 @@ 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)
+    afs_int32 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;
+    } 
+    tt->iflags = ITBusy;
+    tt->vflags = 0;
+    strcpy(tt->lastProcName, "SplitVolume");
+
+    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;
+    } 
+    tt2->iflags = ITBusy;
+    tt2->vflags = 0;
+    strcpy(tt2->lastProcName, "SplitVolume");
+
+    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.