Initialize oldvtix
[openafs.git] / src / afs / afs_volume.c
index 6760a70..4548abd 100644 (file)
@@ -18,8 +18,6 @@
 #include <afsconfig.h>
 #include "afs/param.h"
 
-RCSID
-    ("$Header$");
 
 #include "afs/stds.h"
 #include "afs/sysincludes.h"   /* Standard vendor system headers */
@@ -33,7 +31,7 @@ RCSID
 #ifdef AFS_SGI62_ENV
 #include "h/hashing.h"
 #endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
+#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
 #include <netinet/in_var.h>
 #endif /* ! AFS_HPUX110_ENV */
 #endif /* !defined(UKERNEL) */
@@ -58,12 +56,7 @@ RCSID
 #endif /* vlserver error base define */
 
 /* Exported variables */
-#if defined(LINUX_USE_FH)
-struct fid volumeinfo_fh;     /* File handle for VolumeItems file */
-int volumeinfo_fh_type;
-#else
-ino_t volumeInode;            /* Inode for VolumeItems file */
-#endif
+afs_dcache_id_t volumeInode;   /* Inode for VolumeItems file */
 afs_rwlock_t afs_xvolume;      /** allocation lock for volumes */
 struct volume *afs_freeVolList;
 struct volume *afs_volumes[NVOLS];
@@ -120,11 +113,13 @@ afs_int32 afs_FVIndex = -1;
 struct volume *
 afs_UFSGetVolSlot(void)
 {
-    register struct volume *tv, **lv;
+    register struct volume *tv = NULL, **lv;
     struct osi_file *tfile;
-    register afs_int32 i, code;
+    register afs_int32 i = -1, code;
     afs_int32 bestTime;
-    struct volume *bestVp, **bestLp;
+    struct volume *bestVp, *oldLp = NULL, **bestLp = NULL;
+    char *oldname = NULL;
+    afs_int32 oldvtix = -2; /* Initialize to a value that doesn't occur */
 
     AFS_STATCNT(afs_UFSGetVolSlot);
     if (!afs_freeVolList) {
@@ -144,13 +139,19 @@ afs_UFSGetVolSlot(void)
                }
            }
        }
-       if (!bestVp)
-           osi_Panic("getvolslot none");
+       if (!bestVp) {
+           afs_warn("afs_UFSGetVolSlot: no vol slots available\n");
+           goto error;
+       }
        tv = bestVp;
+
+       oldLp = *bestLp;
        *bestLp = tv->next;
-       if (tv->name)
-           afs_osi_Free(tv->name, strlen(tv->name) + 1);
+
+       oldname = tv->name;
        tv->name = NULL;
+
+       oldvtix = tv->vtix;
        /* now write out volume structure to file */
        if (tv->vtix < 0) {
            tv->vtix = afs_volCounter++;
@@ -164,17 +165,16 @@ afs_UFSGetVolSlot(void)
             * next chain
             */
            if (afs_FVIndex != tv->vtix) {
-#if defined(LINUX_USE_FH)
-               tfile = osi_UFSOpen_fh(&volumeinfo_fh, volumeinfo_fh_type);
-#else
-               tfile = osi_UFSOpen(volumeInode);
-#endif
+               tfile = osi_UFSOpen(&volumeInode);
                code =
                    afs_osi_Read(tfile, sizeof(struct fvolume) * tv->vtix,
                                 &staticFVolume, sizeof(struct fvolume));
-               if (code != sizeof(struct fvolume))
-                   osi_Panic("read volumeinfo");
                osi_UFSClose(tfile);
+               if (code != sizeof(struct fvolume)) {
+                   afs_warn("afs_UFSGetVolSlot: error %d reading volumeinfo\n",
+                            (int)code);
+                   goto error;
+               }
                afs_FVIndex = tv->vtix;
            }
        }
@@ -185,23 +185,49 @@ afs_UFSGetVolSlot(void)
        staticFVolume.dotdot = tv->dotdot;
        staticFVolume.rootVnode = tv->rootVnode;
        staticFVolume.rootUnique = tv->rootUnique;
-#if defined(LINUX_USE_FH)
-       tfile = osi_UFSOpen_fh(&volumeinfo_fh, volumeinfo_fh_type);
-#else
-       tfile = osi_UFSOpen(volumeInode);
-#endif
+       tfile = osi_UFSOpen(&volumeInode);
        code =
            afs_osi_Write(tfile, sizeof(struct fvolume) * afs_FVIndex,
                          &staticFVolume, sizeof(struct fvolume));
-       if (code != sizeof(struct fvolume))
-           osi_Panic("write volumeinfo");
        osi_UFSClose(tfile);
+       if (code != sizeof(struct fvolume)) {
+           afs_warn("afs_UFSGetVolSlot: error %d writing volumeinfo\n",
+                    (int)code);
+           goto error;
+       }
+       if (oldname) {
+           afs_osi_Free(oldname, strlen(oldname) + 1);
+           oldname = NULL;
+       }
     } else {
        tv = afs_freeVolList;
        afs_freeVolList = tv->next;
     }
     return tv;
 
+ error:
+    if (tv) {
+       if (oldtvix == -2) {
+           afs_warn("afs_UFSGetVolSlot: oldvtix is uninitialized\n");
+           return NULL;
+       }
+       if (oldname) {
+           tv->name = oldname;
+           oldname = NULL;
+       }
+       if (oldvtix < 0) {
+           afs_volCounter--;
+           fvTable[i] = staticFVolume.next;
+       }
+       if (bestLp) {
+           *bestLp = oldLp;
+       }
+       tv->vtix = oldvtix;
+       /* we messed with staticFVolume, so make sure someone else
+        * doesn't think it's fine to use */
+       afs_FVIndex = -1;
+    }
+    return NULL;
 }                              /*afs_UFSGetVolSlot */
 
 
@@ -244,7 +270,7 @@ afs_ResetVolumes(struct server *srvp)
     /* Find any volumes residing on this server and flush their state */
     for (j = 0; j < NVOLS; j++) {
        for (vp = afs_volumes[j]; vp; vp = vp->next) {
-           for (k = 0; k < MAXHOSTS; k++) {
+           for (k = 0; k < AFS_MAXHOSTS; k++) {
                if (!srvp || (vp->serverHost[k] == srvp)) {
                    vp->serverHost[k] = 0;
                    afs_ResetVolumeInfo(vp);
@@ -307,7 +333,7 @@ afs_CheckVolumeNames(int flags)
            }
            /* ??? */
            if (flags & (AFS_VOLCHECK_BUSY | AFS_VOLCHECK_FORCE)) {
-               for (j = 0; j < MAXHOSTS; j++)
+               for (j = 0; j < AFS_MAXHOSTS; j++)
                    tv->status[j] = not_busy;
            }
 
@@ -331,25 +357,25 @@ loop:
                if ((flags & (AFS_VOLCHECK_FORCE | AFS_VOLCHECK_MTPTS))
                    || (tvc->mvid
                        && inVolList(tvc->mvid, nvols, volumeID, cellID)))
-                   tvc->states &= ~CMValid;
+                   tvc->f.states &= ~CMValid;
 
                /* If the volume that this file belongs to was reset earlier,
                 * then we should remove its callback.
                 * Again, if forced, always do it.
                 */
-               if ((tvc->states & CRO)
-                   && (inVolList(&tvc->fid, nvols, volumeID, cellID)
+               if ((tvc->f.states & CRO)
+                   && (inVolList(&tvc->f.fid, nvols, volumeID, cellID)
                        || (flags & AFS_VOLCHECK_FORCE))) {
 
-                    if (tvc->states & CVInit) {
+                    if (tvc->f.states & CVInit) {
                         ReleaseReadLock(&afs_xvcache);
-                       afs_osi_Sleep(&tvc->states);
+                       afs_osi_Sleep(&tvc->f.states);
                         goto loop;
                     }
 #ifdef AFS_DARWIN80_ENV
-                    if (tvc->states & CDeadVnode) {
+                    if (tvc->f.states & CDeadVnode) {
                         ReleaseReadLock(&afs_xvcache);
-                       afs_osi_Sleep(&tvc->states);
+                       afs_osi_Sleep(&tvc->f.states);
                         goto loop;
                     }
                    tvp = AFSTOV(tvc);
@@ -370,9 +396,9 @@ loop:
                    ObtainWriteLock(&afs_xcbhash, 485);
                    /* LOCKXXX: We aren't holding tvc write lock? */
                    afs_DequeueCallback(tvc);
-                   tvc->states &= ~CStatd;
+                   tvc->f.states &= ~CStatd;
                    ReleaseWriteLock(&afs_xcbhash);
-                   if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
+                   if (tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
                        osi_dnlc_purgedp(tvc);
 
 #ifdef AFS_DARWIN80_ENV
@@ -549,7 +575,11 @@ afs_SetupVolume(afs_int32 volid, char *aname, void *ve, struct cell *tcell,
        struct fvolume *tf = 0;
 
        tv = afs_GetVolSlot();
-       memset((char *)tv, 0, sizeof(struct volume));
+       if (!tv) {
+           ReleaseWriteLock(&afs_xvolume);
+           return NULL;
+       }
+       memset(tv, 0, sizeof(struct volume));
        tv->cell = tcell->cellNum;
        AFS_RWLOCK_INIT(&tv->lock, "volume lock");
        tv->next = afs_volumes[i];      /* thread into list */
@@ -558,11 +588,7 @@ afs_SetupVolume(afs_int32 volid, char *aname, void *ve, struct cell *tcell,
        for (j = fvTable[FVHash(tv->cell, volid)]; j != 0; j = tf->next) {
            if (afs_FVIndex != j) {
                struct osi_file *tfile;
-#if defined(LINUX_USE_FH)
-               tfile = osi_UFSOpen_fh(&volumeinfo_fh, volumeinfo_fh_type);
-#else
-               tfile = osi_UFSOpen(volumeInode);
-#endif
+               tfile = osi_UFSOpen(&volumeInode);
                err =
                    afs_osi_Read(tfile, sizeof(struct fvolume) * j,
                                 &staticFVolume, sizeof(struct fvolume));
@@ -787,7 +813,7 @@ afs_NewVolumeByName(char *aname, afs_int32 acell, int agood,
            int i;
            struct server *sp;
            struct srvAddr *sap;
-           for (i = 0; i < MAXCELLHOSTS; i++) {
+           for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
                if ((sp = tcell->cellHosts[i]) == NULL)
                    break;
                for (sap = sp->addr; sap; sap = sap->next_sa)
@@ -818,22 +844,26 @@ afs_NewVolumeByName(char *aname, afs_int32 acell, int agood,
     else
        ve = (char *)tve;
     tv = afs_SetupVolume(0, aname, ve, tcell, agood, type, areq);
-    if ((agood == 3) && tv->backVol) {
+    if ((agood == 3) && tv && tv->backVol) {
        /*
         * This means that very soon we'll ask for the BK volume so
         * we'll prefetch it (well we did already.)
         */
        tv1 =
            afs_SetupVolume(tv->backVol, (char *)0, ve, tcell, 0, type, areq);
-       tv1->refCount--;
+       if (tv1) {
+           tv1->refCount--;
+       }
     }
-    if ((agood >= 2) && tv->roVol) {
+    if ((agood >= 2) && tv && tv->roVol) {
        /*
         * This means that very soon we'll ask for the RO volume so
         * we'll prefetch it (well we did already.)
         */
        tv1 = afs_SetupVolume(tv->roVol, NULL, ve, tcell, 0, type, areq);
-       tv1->refCount--;
+       if (tv1) {
+           tv1->refCount--;
+       }
     }
     osi_FreeLargeSpace(tbuffer);
     afs_PutCell(tcell, READ_LOCK);
@@ -891,7 +921,7 @@ InstallVolumeEntry(struct volume *av, struct vldbentry *ve, int acell)
      * struct, we don't deadlock trying to afs_ResetVolumeInfo()
      * this volume.
      */
-    for (j = 0; j < MAXHOSTS; j++) {
+    for (j = 0; j < AFS_MAXHOSTS; j++) {
        av->serverHost[j] = 0;
     }
 
@@ -920,10 +950,10 @@ InstallVolumeEntry(struct volume *av, struct vldbentry *ve, int acell)
        afs_PutServer(ts, WRITE_LOCK);
        j++;
     }
-    if (j < MAXHOSTS) {
+    if (j < AFS_MAXHOSTS) {
        av->serverHost[j++] = 0;
     }
-    afs_SortServers(av->serverHost, MAXHOSTS);
+    afs_SortServers(av->serverHost, AFS_MAXHOSTS);
 }                              /*InstallVolumeEntry */
 
 
@@ -969,7 +999,7 @@ InstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell)
      * struct, we don't deadlock trying to afs_ResetVolumeInfo()
      * this volume.
      */
-    for (j = 0; j < MAXHOSTS; j++) {
+    for (j = 0; j < AFS_MAXHOSTS; j++) {
        av->serverHost[j] = 0;
     }
 
@@ -997,10 +1027,10 @@ InstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell)
        afs_PutServer(ts, WRITE_LOCK);
        j++;
     }
-    if (j < MAXHOSTS) {
+    if (j < AFS_MAXHOSTS) {
        av->serverHost[j++] = 0;
     }
-    afs_SortServers(av->serverHost, MAXHOSTS);
+    afs_SortServers(av->serverHost, AFS_MAXHOSTS);
 }                              /*InstallNVolumeEntry */
 
 
@@ -1049,7 +1079,7 @@ InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
      * struct, we don't deadlock trying to afs_ResetVolumeInfo()
      * this volume.
      */
-    for (j = 0; j < MAXHOSTS; j++) {
+    for (j = 0; j < AFS_MAXHOSTS; j++) {
        av->serverHost[j] = 0;
     }
 
@@ -1075,16 +1105,17 @@ InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
                && ts->addr) {
                /* uuid, uniquifier, and portal are the same */
            } else {
-               afs_uint32 *addrp, nentries, code, unique;
+               afs_uint32 *addrp, code;
+               afs_int32 nentries, unique;
                bulkaddrs addrs;
                ListAddrByAttributes attrs;
                afsUUID uuid;
 
-               memset((char *)&attrs, 0, sizeof(attrs));
+               memset(&attrs, 0, sizeof(attrs));
                attrs.Mask = VLADDR_UUID;
                attrs.uuid = ve->serverNumber[i];
-               memset((char *)&uuid, 0, sizeof(uuid));
-               memset((char *)&addrs, 0, sizeof(addrs));
+               memset(&uuid, 0, sizeof(uuid));
+               memset(&addrs, 0, sizeof(addrs));
                do {
                    tconn =
                        afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
@@ -1118,8 +1149,7 @@ InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
                ts = afs_GetServer(addrp, nentries, acell, cellp->fsport,
                                   WRITE_LOCK, &ve->serverNumber[i],
                                   ve->serverUnique[i]);
-               afs_osi_Free(addrs.bulkaddrs_val,
-                            addrs.bulkaddrs_len * sizeof(*addrp));
+               xdr_free((xdrproc_t) xdr_bulkaddrs, &addrs);
            }
        }
        av->serverHost[j] = ts;
@@ -1137,7 +1167,7 @@ InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
        j++;
     }
 
-    afs_SortServers(av->serverHost, MAXHOSTS);
+    afs_SortServers(av->serverHost, AFS_MAXHOSTS);
 }                              /*InstallVolumeEntry */
 
 
@@ -1154,7 +1184,7 @@ afs_ResetVolumeInfo(struct volume *tv)
     AFS_STATCNT(afs_ResetVolumeInfo);
     ObtainWriteLock(&tv->lock, 117);
     tv->states |= VRecheck;
-    for (i = 0; i < MAXHOSTS; i++)
+    for (i = 0; i < AFS_MAXHOSTS; i++)
        tv->status[i] = not_busy;
     if (tv->name) {
        afs_osi_Free(tv->name, strlen(tv->name) + 1);