DAFS: Request salvage on detach for volser
[openafs.git] / src / volser / volprocs.c
index 5838008..1ada969 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
+#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>
-#endif
-
-#include <dirent.h>
-#include <sys/stat.h>
 #include <rx/xdr.h>
 #include <rx/rx.h>
 #include <rx/rxkad.h>
 #include <afs/afsint.h>
-#include <signal.h>
-#ifdef AFS_PTHREAD_ENV
-#include <assert.h>
-#else /* AFS_PTHREAD_ENV */
-#include <afs/assert.h>
-#endif /* AFS_PTHREAD_ENV */
+#include <afs/afs_assert.h>
 #include <afs/prs_fs.h>
 #include <afs/nfs.h>
 #include <lwp.h>
@@ -61,6 +41,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>
 
@@ -87,7 +68,7 @@ static int GetPartName(afs_int32 partid, char *pname);
 #endif
 
 afs_int32 localTid = 1;
+
 static afs_int32 VolPartitionInfo(struct rx_call *, char *pname,
                                  struct diskPartition64 *);
 static afs_int32 VolNukeVolume(struct rx_call *, afs_int32, afs_uint32);
@@ -133,25 +114,35 @@ static afs_int32 VolSetIdsTypes(struct rx_call *, afs_int32, char [],
 static afs_int32 VolSetDate(struct rx_call *, afs_int32, afs_int32);
 
 /* this call unlocks all of the partition locks we've set */
-int 
-VPFullUnlock(void)
+int
+VPFullUnlock_r(void)
 {
-    register struct DiskPartition64 *tp;
+    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;
        }
     }
     return 0;
 }
 
+int
+VPFullUnlock(void)
+{
+    int code;
+    VOL_LOCK;
+    code = VPFullUnlock_r();
+    VOL_UNLOCK;
+    return code;
+}
+
 /* get partition id from a name */
 afs_int32
 PartitionID(char *aname)
 {
-    register char tc;
-    register int code = 0;
+    char tc;
+    int code = 0;
     char ascii[3];
 
     tc = *aname;
@@ -190,7 +181,7 @@ ConvertVolume(afs_uint32 avol, char *aname, afs_int32 asize)
     if (asize < 18)
        return -1;
     /* It's better using the Generic VFORMAT since otherwise we have to make changes to too many places... The 14 char limitation in names hits us again in AIX; print in field of 9 digits (still 10 for the rest), right justified with 0 padding */
-    (void)afs_snprintf(aname, asize, VFORMAT, (unsigned long)avol);
+    snprintf(aname, asize, VFORMAT, (unsigned long)avol);
     return 0;
 }
 
@@ -214,6 +205,28 @@ ConvertPartition(int apartno, char *aname, int asize)
     return 0;
 }
 
+#ifdef AFS_DEMAND_ATTACH_FS
+/* normally we should use the regular salvaging functions from the volume
+ * package, but this is a special case where we have a volume ID, but no
+ * volume structure to give the volume package */
+static void
+SalvageUnknownVolume(VolumeId volid, char *part)
+{
+    afs_int32 code;
+
+    Log("Scheduling salvage for allegedly nonexistent volume %lu part %s\n",
+        afs_printable_uint32_lu(volid), part);
+
+    code = FSYNC_VolOp(volid, part, FSYNC_VOL_FORCE_ERROR,
+                       FSYNC_SALVAGE, NULL);
+    if (code) {
+       Log("SalvageUnknownVolume: error %ld trying to salvage vol %lu part %s\n",
+           afs_printable_int32_ld(code), afs_printable_uint32_lu(volid),
+           part);
+    }
+}
+#endif /* AFS_DEMAND_ATTACH_FS */
+
 static struct Volume *
 VAttachVolumeByName_retry(Error *ec, char *partition, char *name, int mode)
 {
@@ -292,7 +305,7 @@ 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;
@@ -303,8 +316,8 @@ ViceCreateRoot(Volume *vp)
     struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
     IHandle_t *h;
     FdHandle_t *fdP;
-    int code;
     afs_fsize_t length;
+    ssize_t nBytes;
 
     vnode = (struct VnodeDiskObject *)malloc(SIZEOF_LARGEDISKVNODE);
     if (!vnode)
@@ -316,14 +329,18 @@ ViceCreateRoot(Volume *vp)
        IH_CREATE(V_linkHandle(vp), V_device(vp),
                  VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),
                  1, 1, 0);
-    assert(VALID_INO(inodeNumber));
+    if (!VALID_INO(inodeNumber)) {
+       Log("ViceCreateRoot: IH_CREATE: %s\n", afs_error_message(errno));
+       free(vnode);
+       return EIO;
+    }
 
     SetSalvageDirHandle(&dir, V_parentId(vp), vp->device, inodeNumber);
     did.Volume = V_id(vp);
     did.Vnode = (VnodeId) 1;
     did.Unique = 1;
 
-    assert(!(MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
+    osi_Assert(!(MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)));
     DFlush();                  /* flush all modified dir buffers out */
     DZap((afs_int32 *)&dir);                   /* Remove all buffers for this dir */
     length = Length(&dir);     /* Remember size of this directory */
@@ -363,22 +380,20 @@ ViceCreateRoot(Volume *vp)
     IH_INIT(h, vp->device, V_parentId(vp),
            vp->vnodeIndex[vLarge].handle->ih_ino);
     fdP = IH_OPEN(h);
-    assert(fdP != NULL);
-    code = FDH_SEEK(fdP, vnodeIndexOffset(vcp, 1), SEEK_SET);
-    assert(code >= 0);
-    code = FDH_WRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE);
-    assert(code == SIZEOF_LARGEDISKVNODE);
+    osi_Assert(fdP != NULL);
+    nBytes = FDH_PWRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE, vnodeIndexOffset(vcp, 1));
+    osi_Assert(nBytes == SIZEOF_LARGEDISKVNODE);
     FDH_REALLYCLOSE(fdP);
     IH_RELEASE(h);
     VNDISK_GET_LEN(length, vnode);
     V_diskused(vp) = nBlocks(length);
 
     free(vnode);
-    return 1;
+    return 0;
 }
 
 afs_int32
-SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition 
+SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
                     *partition)
 {
     afs_int32 code;
@@ -399,7 +414,7 @@ SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
 }
 
 afs_int32
-SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64 
+SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64
                     *partition)
 {
     afs_int32 code;
@@ -410,10 +425,10 @@ SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64
 }
 
 afs_int32
-VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64 
+VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
                 *partition)
 {
-    register struct DiskPartition64 *dp;
+    struct DiskPartition64 *dp;
 
 /*
     if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
@@ -448,7 +463,7 @@ VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
     char partName[50];
     afs_int32 error;
     Error verror;
-    register afs_int32 code;
+    afs_int32 code;
     struct Volume *tvp;
     char caller[MAXKTCNAMELEN];
 
@@ -478,8 +493,8 @@ VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
  * Return the new volume id in *avolid.
  */
 afs_int32
-SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname, 
-                   afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid, 
+SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
+                   afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid,
                    afs_int32 *atrans)
 {
     afs_int32 code;
@@ -493,16 +508,16 @@ SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
 }
 
 static afs_int32
-VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname, 
-                   afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid, 
+VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
+                   afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid,
                    afs_int32 *atrans)
 {
     Error error;
-    register Volume *vp;
+    Volume *vp;
     Error junk;                /* discardable error code */
     afs_uint32 volumeID;
     afs_int32 doCreateRoot = 1;
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char ppath[30];
     char caller[MAXKTCNAMELEN];
 
@@ -535,6 +550,11 @@ VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
     }
     vp = VCreateVolume(&error, ppath, volumeID, aparent);
     if (error) {
+#ifdef AFS_DEMAND_ATTACH_FS
+       if (error != VVOLEXISTS && error != EXDEV) {
+           SalvageUnknownVolume(volumeID, ppath);
+       }
+#endif
        Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
        LogError(error);
        DeleteTrans(tt, 1);
@@ -545,8 +565,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 */
@@ -584,7 +613,7 @@ SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
 static afs_int32
 VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
 {
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     Error error;
     char caller[MAXKTCNAMELEN];
 
@@ -602,7 +631,10 @@ VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
        Log("%s is executing Delete Volume %u\n", caller, tt->volid);
     TSetRxCall(tt, acid, "DeleteVolume");
     VPurgeVolume(&error, tt->volume);  /* don't check error code, it is not set! */
-    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);
@@ -626,7 +658,7 @@ 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, 
+SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
             afs_int32 newType, char *newName, afs_uint32 *newNumber)
 {
     afs_int32 code;
@@ -639,14 +671,17 @@ 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, 
+VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
             afs_int32 newType, char *newName, afs_uint32 *newNumber)
 {
     afs_uint32 newId;
-    register struct Volume *originalvp, *purgevp, *newvp;
+    struct Volume *originalvp, *purgevp, *newvp;
     Error error, code;
-    register struct volser_trans *tt, *ttc;
+    struct volser_trans *tt, *ttc;
     char caller[MAXKTCNAMELEN];
+#ifdef AFS_DEMAND_ATTACH_FS
+    struct Volume *salv_vp = NULL;
+#endif
 
     if (strlen(newName) > 31)
        return VOLSERBADNAME;
@@ -732,6 +767,9 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
     }
 
     error = 0;
+#ifdef AFS_DEMAND_ATTACH_FS
+    salv_vp = originalvp;
+#endif
 
     newvp =
        VCreateVolume(&error, originalvp->partition->name, newId,
@@ -787,6 +825,9 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
        goto fail;
     }
     TClearRxCall(tt);
+#ifdef AFS_DEMAND_ATTACH_FS
+    salv_vp = NULL;
+#endif
     if (TRELE(tt)) {
        tt = (struct volser_trans *)0;
        error = VOLSERTRELE_ERROR;
@@ -806,6 +847,11 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
     }
     if (ttc)
        DeleteTrans(ttc, 1);
+#ifdef AFS_DEMAND_ATTACH_FS
+    if (salv_vp && error != VVOLEXISTS && error != EXDEV) {
+       V_needsSalvaged(salv_vp) = 1;
+    }
+#endif /* AFS_DEMAND_ATTACH_FS */
     return error;
 }
 
@@ -824,10 +870,10 @@ 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)
 {
-    register struct Volume *originalvp, *clonevp;
+    struct Volume *originalvp, *clonevp;
     Error error, code;
     afs_int32 newType;
-    register struct volser_trans *tt, *ttc;
+    struct volser_trans *tt, *ttc;
     char caller[MAXKTCNAMELEN];
 
     /*not a super user */
@@ -939,9 +985,9 @@ 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  
+    /* 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 */
@@ -999,8 +1045,8 @@ static afs_int32
 VolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
                   afs_int32 iflags, afs_int32 *ttid)
 {
-    register struct volser_trans *tt;
-    register Volume *tv;
+    struct volser_trans *tt;
+    Volume *tv;
     afs_int32 error;
     Error code;
     afs_int32 mode;
@@ -1087,7 +1133,7 @@ SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
 static afs_int32
 VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
 {
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
 
     tt = FindTrans(atid);
     if (!tt)
@@ -1125,8 +1171,8 @@ SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
 static afs_int32
 VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
 {
-    register struct volser_trans *tt;
-    register struct Volume *vp;
+    struct volser_trans *tt;
+    struct Volume *vp;
     Error error;
     char caller[MAXKTCNAMELEN];
 
@@ -1180,7 +1226,7 @@ VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
  */
 afs_int32
 SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
-              struct destServer *destination, afs_int32 destTrans, 
+              struct destServer *destination, afs_int32 destTrans,
               struct restoreCookie *cookie)
 {
     afs_int32 code;
@@ -1188,20 +1234,20 @@ SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
     code =
        VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
     osi_auditU(acid, VS_ForwardEvent, code, AUD_LONG, fromTrans, AUD_HOST,
-              destination->destHost, AUD_LONG, destTrans, AUD_END);
+              htonl(destination->destHost), AUD_LONG, destTrans, AUD_END);
     return code;
 }
 
 static afs_int32
 VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
-              struct destServer *destination, afs_int32 destTrans, 
+              struct destServer *destination, afs_int32 destTrans,
               struct restoreCookie *cookie)
 {
-    register struct volser_trans *tt;
-    register afs_int32 code;
-    register struct rx_connection *tcon;
+    struct volser_trans *tt;
+    afs_int32 code;
+    struct rx_connection *tcon;
     struct rx_call *tcall;
-    register struct Volume *vp;
+    struct Volume *vp;
     struct rx_securityClass *securityObject;
     afs_int32 securityIndex;
     char caller[MAXKTCNAMELEN];
@@ -1279,16 +1325,16 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
 
 /* Start a dump and send it to multiple places simultaneously.
  * If this returns an error (eg, return ENOENT), it means that
- * none of the releases worked.  If this returns 0, that means 
+ * none of the releases worked.  If this returns 0, that means
  * that one or more of the releases worked, and the caller has
  * to examine the results array to see which one(s).
  * This will only do EITHER incremental or full, not both, so it's
  * the caller's responsibility to be sure that all the destinations
- * need just an incremental (and from the same time), if that's 
- * what we're doing. 
+ * need just an incremental (and from the same time), if that's
+ * what we're doing.
  */
 afs_int32
-SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32 
+SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
                       fromDate, manyDests *destinations, afs_int32 spare,
                       struct restoreCookie *cookie, manyResults *results)
 {
@@ -1307,7 +1353,7 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
        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;
 
@@ -1391,7 +1437,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);
@@ -1432,7 +1478,7 @@ VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
        afs_int32 flags)
 {
     int code = 0;
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -1461,7 +1507,7 @@ VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
     return 0;
 }
 
-/* 
+/*
  * Ha!  No more helper process!
  */
 afs_int32
@@ -1479,8 +1525,8 @@ static afs_int32
 VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
           struct restoreCookie *cookie)
 {
-    register struct volser_trans *tt;
-    register afs_int32 code, tcode;
+    struct volser_trans *tt;
+    afs_int32 code, tcode;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -1519,7 +1565,7 @@ SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
 static afs_int32
 VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
 {
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -1541,14 +1587,14 @@ 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;
 }
 
 static afs_int32
 VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
 {
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
     char partName[16];
 
@@ -1577,7 +1623,7 @@ VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
 
 afs_int32
 SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
-                register struct volser_status *astatus)
+                struct volser_status *astatus)
 {
     afs_int32 code;
 
@@ -1588,10 +1634,10 @@ SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
 
 static afs_int32
 VolGetStatus(struct rx_call *acid, afs_int32 atrans,
-            register struct volser_status *astatus)
+            struct volser_status *astatus)
 {
-    register struct Volume *tv;
-    register struct VolumeDiskData *td;
+    struct Volume *tv;
+    struct VolumeDiskData *td;
     struct volser_trans *tt;
 
 
@@ -1638,7 +1684,7 @@ VolGetStatus(struct rx_call *acid, afs_int32 atrans,
 
 afs_int32
 SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
-              register struct volintInfo *astatus)
+              struct volintInfo *astatus)
 {
     afs_int32 code;
 
@@ -1649,10 +1695,10 @@ SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
 
 static afs_int32
 VolSetInfo(struct rx_call *acid, afs_int32 atrans,
-              register struct volintInfo *astatus)
+              struct volintInfo *astatus)
 {
-    register struct Volume *tv;
-    register struct VolumeDiskData *td;
+    struct Volume *tv;
+    struct VolumeDiskData *td;
     struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
     Error error;
@@ -1710,10 +1756,10 @@ SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
 static afs_int32
 VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
 {
-    register struct Volume *tv;
-    register struct VolumeDiskData *td;
+    struct Volume *tv;
+    struct VolumeDiskData *td;
     struct volser_trans *tt;
-    register int len;
+    int len;
 
     /* We need to at least fill it in */
     *aname = (char *)malloc(1);
@@ -1834,12 +1880,17 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
        if (dp)
            partList.partId[j++] = i;
     }
-    pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
-    if (!pEntries->partEntries_val)
-       return ENOMEM;
-    memcpy((char *)pEntries->partEntries_val, (char *)&partList,
-          j * sizeof(int));
-    pEntries->partEntries_len = j;
+    if (j > 0) {
+       pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
+       if (!pEntries->partEntries_val)
+           return ENOMEM;
+       memcpy((char *)pEntries->partEntries_val, (char *)&partList,
+               j * sizeof(int));
+       pEntries->partEntries_len = j;
+    } else {
+       pEntries->partEntries_val = NULL;
+       pEntries->partEntries_len = 0;
+    }
     return 0;
 
 }
@@ -1944,7 +1995,7 @@ static int
 FillVolInfo(Volume * vp, volint_info_handle_t * handle)
 {
     unsigned int numStatBytes, now;
-    register struct VolumeDiskData *hdr = &vp->header->diskstuff;
+    struct VolumeDiskData *hdr = &vp->header->diskstuff;
 
     /*read in the relevant info */
     strcpy((char *)VOLINT_INFO_PTR(handle, name), hdr->name);
@@ -1979,13 +2030,13 @@ FillVolInfo(Volume * vp, volint_info_handle_t * handle)
      *   -- tkeiser 11/27/2007
      */
 
-    /* Conditions that offline status is based on: 
+    /* 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 
+               volume needsSalvaged
                next op would set volume offline
                next op would not leave volume online (based on several conditions)
     */
@@ -1993,11 +2044,11 @@ FillVolInfo(Volume * vp, volint_info_handle_t * handle)
        (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
        VIsErrorState(V_attachState(vp)) ||
        !hdr->inService ||
-       !hdr->blessed || 
+       !hdr->blessed ||
        (V_attachState(vp) == VOL_STATE_SALVSYNC_REQ) ||
        hdr->needsSalvaged ||
-       (vp->pending_vol_op && 
-               (vp->pending_vol_op->com.command == FSYNC_VOL_OFF || 
+       (vp->pending_vol_op &&
+               (vp->pending_vol_op->com.command == FSYNC_VOL_OFF ||
                !VVolOpLeaveOnline_r(vp, vp->pending_vol_op) )
        )
        ) {
@@ -2021,7 +2072,7 @@ FillVolInfo(Volume * vp, volint_info_handle_t * handle)
 
 #ifdef AFS_DEMAND_ATTACH_FS
        /* see comment above where we set inUse bit */
-       if (hdr->needsSalvaged || 
+       if (hdr->needsSalvaged ||
            (vp && VIsErrorState(V_attachState(vp)))) {
            handle->volinfo_ptr.base->needsSalvaged = 1;
        } else {
@@ -2032,7 +2083,7 @@ FillVolInfo(Volume * vp, volint_info_handle_t * handle)
 #endif
        handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
        handle->volinfo_ptr.base->spare0 = hdr->minquota;
-       handle->volinfo_ptr.base->spare1 = 
+       handle->volinfo_ptr.base->spare1 =
            (long)hdr->weekUse[0] +
            (long)hdr->weekUse[1] +
            (long)hdr->weekUse[2] +
@@ -2059,7 +2110,7 @@ FillVolInfo(Volume * vp, volint_info_handle_t * handle)
                   0, numStatBytes);
        } else {
            memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
-                  (char *)&(hdr->stat_reads[0]), 
+                  (char *)&(hdr->stat_reads[0]),
                   numStatBytes);
        }
        break;
@@ -2075,7 +2126,7 @@ FillVolInfo(Volume * vp, volint_info_handle_t * handle)
  *
  * @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 
+ * @param[inout] vp     pointer to pointer to Volume object which
  *                      will be populated (see note)
  *
  * @return operation status
@@ -2144,8 +2195,8 @@ typedef enum {
 static int
 GetVolInfo(afs_uint32 partId,
           afs_uint32 volumeId,
-          char * pname, 
-          char * volname, 
+          char * pname,
+          char * volname,
           volint_info_handle_t * handle,
           vol_info_list_mode_t mode)
 {
@@ -2174,9 +2225,12 @@ GetVolInfo(afs_uint32 partId,
     }
 
     /* 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
+       tv = VAttachVolumeByName_retry(&error, pname, volname, V_PEEK);
     if (error) {
-       Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n", 
+       Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
            volumeId, pname, volname, error);
        goto drop;
     }
@@ -2195,7 +2249,7 @@ GetVolInfo(afs_uint32 partId,
            goto drop;
 
        case VOL_INFO_LIST_SINGLE:
-           Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n", 
+           Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n",
                volumeId, pname, volname);
 
        default:
@@ -2205,7 +2259,7 @@ GetVolInfo(afs_uint32 partId,
 
     if (tv->header->diskstuff.needsSalvaged) {
        /*this volume will be salvaged */
-       Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n", 
+       Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
            volumeId, pname, volname);
     }
 
@@ -2217,7 +2271,7 @@ GetVolInfo(afs_uint32 partId,
     }
 
     /* 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 (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;
@@ -2230,7 +2284,7 @@ GetVolInfo(afs_uint32 partId,
 
     /* When using DAFS, use the fs volume info, populated with required structures */
     fill_tv = fs_tv;
-#else 
+#else
     /* When not using DAFS, just use the local volume info */
     fill_tv = tv;
 #endif
@@ -2264,7 +2318,7 @@ GetVolInfo(afs_uint32 partId,
 
 /*return the header information about the <volid> */
 afs_int32
-SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,  
+SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,
                      afs_uint32 volumeId, volEntries *volumeInfo)
 {
     afs_int32 code;
@@ -2275,10 +2329,9 @@ SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,
 }
 
 static afs_int32
-VolListOneVolume(struct rx_call *acid, afs_int32 partid, 
+VolListOneVolume(struct rx_call *acid, afs_int32 partid,
                  afs_uint32 volumeId, volEntries *volumeInfo)
 {
-    volintInfo *pntr;
     struct DiskPartition64 *partP;
     char pname[9], volname[20];
     DIR *dirp;
@@ -2292,7 +2345,6 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid,
        return ENOMEM;
     memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
 
-    pntr = volumeInfo->volEntries_val;
     volumeInfo->volEntries_len = 1;
     if (GetPartName(partid, pname))
        return VOLSERILLEGAL_PARTITION;
@@ -2326,10 +2378,10 @@ 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, 
+
+       code = GetVolInfo(partid,
+                         volid,
+                         pname,
                          volname,
                          &handle,
                          VOL_INFO_LIST_SINGLE);
@@ -2363,7 +2415,7 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid,
  *------------------------------------------------------------------------*/
 
 afs_int32
-SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID, 
+SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
                      afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
 {
     afs_int32 code;
@@ -2374,11 +2426,10 @@ SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
 }
 
 static afs_int32
-VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID, 
+VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
                   afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
 {                              /*SAFSVolXListOneVolume */
 
-    volintXInfo *xInfoP;       /*Ptr to the extended vol info */
     struct DiskPartition64 *partP;     /*Ptr to partition */
     char pname[9], volname[20];        /*Partition, volume names */
     DIR *dirp;                 /*Partition directory ptr */
@@ -2397,7 +2448,6 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
        return ENOMEM;
     memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
 
-    xInfoP = a_volumeXInfoP->volXEntries_val;
     a_volumeXInfoP->volXEntries_len = 1;
     code = ENODEV;
 
@@ -2472,10 +2522,10 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
     return (found) ? 0 : ENODEV;
 }                              /*SAFSVolXListOneVolume */
 
-/*returns all the volumes on partition partid. If flags = 1 then all the 
+/*returns all the volumes on partition partid. If flags = 1 then all the
 * relevant info about the volumes  is also returned */
 afs_int32
-SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags, 
+SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
                   volEntries *volumeInfo)
 {
     afs_int32 code;
@@ -2486,7 +2536,7 @@ SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
 }
 
 static afs_int32
-VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags, 
+VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
                   volEntries *volumeInfo)
 {
     volintInfo *pntr;
@@ -2554,7 +2604,7 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
                (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
                                       allocSize * sizeof(volintInfo));
            if (pntr == NULL) {
-               closedir(dirp); 
+               closedir(dirp);
                return VOLSERNO_MEMORY;
            }
            volumeInfo->volEntries_val = pntr;  /* point to new block */
@@ -2839,7 +2889,7 @@ VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
 {
     struct Volume *tv;
     Error error = 0;
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (strlen(name) > 31)
@@ -2897,7 +2947,7 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
 {
     struct Volume *tv;
     Error error = 0;
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -2942,7 +2992,7 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
 #else
     char caller[MAXKTCNAMELEN];
     DIR *dirp;
-    register struct volser_trans *ttc;
+    struct volser_trans *ttc;
     char pname[16], volname[20];
     struct DiskPartition64 *partP;
     afs_int32 ret = ENODEV;
@@ -2965,7 +3015,7 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
             GetNextVol(dirp, volname, &volid);
             continue;           /*back to while loop */
         }
-       
+
        if (volid == volumeId) {        /*copy other things too */
 #ifndef AFS_PTHREAD_ENV
             IOMGR_Poll();       /*make sure that the client doesnot time out */
@@ -2983,12 +3033,12 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
        }
        GetNextVol(dirp, volname, &volid);
     }
-    
+
     if (ttc) {
         DeleteTrans(ttc, 1);
         ttc = (struct volser_trans *)0;
     }
-    
+
     closedir(dirp);
     return ret;
 #endif
@@ -2996,10 +3046,10 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
 
 afs_int32
 SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
-              register struct volintSize *size)
+              struct volintSize *size)
 {
     int code = 0;
-    register struct volser_trans *tt;
+    struct volser_trans *tt;
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(tdir, acid, caller))
@@ -3032,7 +3082,7 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
     char caller[MAXKTCNAMELEN];
     char line[128];
 
-    if (!afsconf_SuperUser(tdir, acall, caller)) 
+    if (!afsconf_SuperUser(tdir, acall, caller))
         return EPERM;
 
     vol = VAttachVolume(&code, vid, V_VOLUPD);
@@ -3048,7 +3098,7 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
             code = ENOENT;
         return code;
     }
-    if (V_device(vol) != V_device(newvol) 
+    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",
@@ -3074,7 +3124,7 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
         VDetachVolume(&code2, vol);
         VDetachVolume(&code2, newvol);
         return VOLSERVOLBUSY;
-    } 
+    }
     VTRANS_OBJ_LOCK(tt);
     tt->iflags = ITBusy;
     tt->vflags = 0;
@@ -3091,7 +3141,7 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
         VDetachVolume(&code2, vol);
         VDetachVolume(&code2, newvol);
         return VOLSERVOLBUSY;
-    } 
+    }
     VTRANS_OBJ_LOCK(tt2);
     tt2->iflags = ITBusy;
     tt2->vflags = 0;