/*
* 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 "afs/afs_stats.h" /* afs statistics */
#include "afs/afs_dynroot.h"
-#if defined(AFS_SUN56_ENV)
+#if defined(AFS_SUN5_ENV)
#include <inet/led.h>
#include <inet/common.h>
-#if defined(AFS_SUN58_ENV)
#include <netinet/ip6.h>
-#endif
#include <inet/ip.h>
#endif
/**
- * Convert a volume name to a number;
+ * Convert a volume name to a number;
* @param aname Volume name.
* @return return 0 if can't parse as a number.
*/
static int
-afs_vtoi(register char *aname)
+afs_vtoi(char *aname)
{
- register afs_int32 temp;
- register int tc;
+ afs_int32 temp;
+ int tc;
temp = 0;
AFS_STATCNT(afs_vtoi);
while ((tc = *aname++)) {
static struct fvolume staticFVolume;
afs_int32 afs_FVIndex = -1;
-/**
- * UFS specific version of afs_GetVolSlot
+/*!
+ * Initialize a newly gotten volume slot.
+ *
+ * \param tv volume slot to be initialized
+ * \param tf volume item data; null if none
+ * \param volid volume id for this volume slot
+ * \param cell cell for this volume slot
+ * \return none
+ */
+static void
+afs_InitVolSlot(struct volume *tv, struct fvolume *tf, afs_int32 volid,
+ struct cell *tcell)
+{
+ AFS_STATCNT(afs_InitVolSlot);
+ memset(tv, 0, sizeof(struct volume));
+ tv->cell = tcell->cellNum;
+ AFS_RWLOCK_INIT(&tv->lock, "volume lock");
+ tv->volume = volid;
+ if (tf) {
+ tv->vtix = afs_FVIndex;
+ tv->mtpoint = tf->mtpoint;
+ tv->dotdot = tf->dotdot;
+ tv->rootVnode = tf->rootVnode;
+ tv->rootUnique = tf->rootUnique;
+ } else {
+ tv->vtix = -1;
+ tv->rootVnode = tv->rootUnique = 0;
+ afs_GetDynrootMountFid(&tv->dotdot);
+ afs_GetDynrootMountFid(&tv->mtpoint);
+ tv->mtpoint.Fid.Vnode =
+ VNUM_FROM_TYPEID(VN_TYPE_MOUNT, tcell->cellIndex << 2);
+ tv->mtpoint.Fid.Unique = volid;
+ }
+}
+
+/**
+ * UFS specific version of afs_GetVolSlot
* @return
*/
struct volume *
-afs_UFSGetVolSlot(void)
+afs_UFSGetVolSlot(afs_int32 volid, struct cell *tcell)
{
- register struct volume *tv = NULL, **lv;
+ struct volume *tv = NULL, **lv;
struct osi_file *tfile;
- register afs_int32 i = -1, code;
+ afs_int32 i = -1, code;
afs_int32 bestTime;
struct volume *bestVp, *oldLp = NULL, **bestLp = NULL;
char *oldname = NULL;
- afs_int32 oldvtix;
+ afs_int32 oldvtix = -2; /* Initialize to a value that doesn't occur */
+ struct fvolume *tf = NULL;
+ int j = 0;
AFS_STATCNT(afs_UFSGetVolSlot);
if (!afs_freeVolList) {
tv = afs_freeVolList;
afs_freeVolList = tv->next;
}
+
+ /* read volume item data from disk for the gotten slot */
+ for (j = fvTable[FVHash(tcell->cellNum, volid)]; j != 0; j = tf->next) {
+ if (afs_FVIndex != j) {
+ tfile = osi_UFSOpen(&volumeInode);
+ code =
+ afs_osi_Read(tfile, sizeof(struct fvolume) * j,
+ &staticFVolume, sizeof(struct fvolume));
+ osi_UFSClose(tfile);
+ if (code != sizeof(struct fvolume)) {
+ afs_warn("afs_SetupVolume: error %d reading volumeinfo\n",
+ (int)code);
+ /* put tv back on the free list; the data in it is not valid */
+ tv->next = afs_freeVolList;
+ afs_freeVolList = tv;
+ /* staticFVolume contents are not valid */
+ afs_FVIndex = -1;
+ return NULL;
+ }
+ afs_FVIndex = j;
+ }
+ if (j != 0) { /* volume items record 0 is not used */
+ tf = &staticFVolume;
+ if (tf->cell == tcell->cellNum && tf->volume == volid) {
+ break;
+ }
+ }
+ }
+
+ afs_InitVolSlot(tv, tf, volid, tcell);
return tv;
error:
if (tv) {
+ if (oldvtix == -2) {
+ afs_warn("afs_UFSGetVolSlot: oldvtix is uninitialized\n");
+ return NULL;
+ }
if (oldname) {
tv->name = oldname;
oldname = NULL;
/**
- * Get an available volume list slot. If the list does not exist,
+ * Get an available volume list slot. If the list does not exist,
* create one containing a single element.
- * @return
+ * @return
*/
struct volume *
-afs_MemGetVolSlot(void)
+afs_MemGetVolSlot(afs_int32 volid, struct cell *tcell)
{
- register struct volume *tv;
+ struct volume *tv;
AFS_STATCNT(afs_MemGetVolSlot);
if (!afs_freeVolList) {
struct volume *newVp;
- newVp = (struct volume *)afs_osi_Alloc(sizeof(struct volume));
+ newVp = afs_osi_Alloc(sizeof(struct volume));
+ osi_Assert(newVp != NULL);
newVp->next = NULL;
afs_freeVolList = newVp;
}
tv = afs_freeVolList;
afs_freeVolList = tv->next;
+
+ afs_InitVolSlot(tv, NULL, volid, tcell);
return tv;
} /*afs_MemGetVolSlot */
-/**
- * Reset volume information for all volume structs that
- * point to a speicific server.
- * @param srvp
+/*!
+ * Setup a volume slot for cell:volume.
+ *
+ * Find the volume slot for the cell:volume, otherwise get
+ * and initialize a new slot.
+ *
+ * \param volid volume id
+ * \param cell cell
+ * \return volume
+ */
+static struct volume *
+afs_SetupVolSlot(afs_int32 volid, struct cell *tcell)
+{
+ struct volume *tv;
+ int i;
+
+ AFS_STATCNT(afs_SetupVolSlot);
+ ObtainWriteLock(&afs_xvolume, 108);
+ i = VHash(volid);
+ for (tv = afs_volumes[i]; tv; tv = tv->next) {
+ if (tv->volume == volid && tv->cell == tcell->cellNum) {
+ break;
+ }
+ }
+ if (!tv) {
+ tv = afs_GetVolSlot(volid, tcell);
+ if (!tv) {
+ ReleaseWriteLock(&afs_xvolume);
+ return NULL;
+ }
+ tv->next = afs_volumes[i]; /* thread into list */
+ afs_volumes[i] = tv;
+ }
+ tv->refCount++;
+ tv->states &= ~VRecheck; /* just checked it */
+ tv->accessTime = osi_Time();
+ ReleaseWriteLock(&afs_xvolume);
+ return tv;
+}
+
+/*!
+ * Reset volume information for all volume structs that
+ * point to a speicific server, skipping a given volume if provided.
+ *
+ * @param[in] srvp
+ * The server to reset volume info about
+ * @param[in] tv
+ * The volume to skip resetting info about
*/
void
-afs_ResetVolumes(struct server *srvp)
+afs_ResetVolumes(struct server *srvp, struct volume *tv)
{
int j, k;
struct volume *vp;
for (vp = afs_volumes[j]; vp; vp = vp->next) {
for (k = 0; k < AFS_MAXHOSTS; k++) {
if (!srvp || (vp->serverHost[k] == srvp)) {
- vp->serverHost[k] = 0;
- afs_ResetVolumeInfo(vp);
+ if (tv && tv != vp) {
+ vp->serverHost[k] = 0;
+ afs_ResetVolumeInfo(vp);
+ }
break;
}
}
}
}
-
-/**
+/**
* Reset volume name to volume id mapping cache.
* @param flags
*/
for (tv = afs_volumes[i]; tv; tv = tv->next)
++vsize;
- volumeID = (afs_int32 *) afs_osi_Alloc(2 * vsize * sizeof(*volumeID));
+ volumeID = afs_osi_Alloc(2 * vsize * sizeof(*volumeID));
cellID = (volumeID) ? volumeID + vsize : 0;
}
/* afs_PutVolume is now a macro in afs.h */
-/**
+/**
* Return volume struct if we have it cached and it's up-to-date.
* Environment: Must be called with afs_xvolume unlocked.
* @param afid Volume FID.
/**
- *
+ *
* @param volid Volume ID. If it's 0, get it from the name.
* @param aname Volume name.
* @param ve Volume entry.
* @param tcell The cell containing this volume.
- * @param agood
+ * @param agood
* @param type Type of volume.
* @param areq Request.
* @return Volume or NULL if failure.
struct uvldbentry *uve = (struct uvldbentry *)ve;
int whichType; /* which type of volume to look for */
- int i, j, err = 0;
+ int i;
if (!volid) {
int len;
volid = nve->volumeId[whichType];
} else {
volid = ove->volumeId[whichType];
- }
+ }
} /* end of if (volid == 0) */
} /* end of if (!volid) */
-
- ObtainWriteLock(&afs_xvolume, 108);
- i = VHash(volid);
- for (tv = afs_volumes[i]; tv; tv = tv->next) {
- if (tv->volume == volid && tv->cell == tcell->cellNum) {
- break;
- }
- }
+ tv = afs_SetupVolSlot(volid, tcell);
if (!tv) {
- struct fvolume *tf = 0;
-
- tv = afs_GetVolSlot();
- 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 */
- afs_volumes[i] = tv;
- tv->volume = volid;
- for (j = fvTable[FVHash(tv->cell, volid)]; j != 0; j = tf->next) {
- if (afs_FVIndex != j) {
- struct osi_file *tfile;
- tfile = osi_UFSOpen(&volumeInode);
- err =
- afs_osi_Read(tfile, sizeof(struct fvolume) * j,
- &staticFVolume, sizeof(struct fvolume));
- if (err != sizeof(struct fvolume))
- osi_Panic("read volumeinfo2");
- osi_UFSClose(tfile);
- afs_FVIndex = j;
- }
- tf = &staticFVolume;
- if (tf->cell == tv->cell && tf->volume == volid)
- break;
- }
- if (tf && (j != 0)) {
- tv->vtix = afs_FVIndex;
- tv->mtpoint = tf->mtpoint;
- tv->dotdot = tf->dotdot;
- tv->rootVnode = tf->rootVnode;
- tv->rootUnique = tf->rootUnique;
- } else {
- tv->vtix = -1;
- tv->rootVnode = tv->rootUnique = 0;
- afs_GetDynrootMountFid(&tv->dotdot);
- afs_GetDynrootMountFid(&tv->mtpoint);
- tv->mtpoint.Fid.Vnode =
- VNUM_FROM_TYPEID(VN_TYPE_MOUNT, tcell->cellIndex << 2);
- tv->mtpoint.Fid.Unique = volid;
- }
+ return NULL;
}
- tv->refCount++;
- tv->states &= ~VRecheck; /* just checked it */
- tv->accessTime = osi_Time();
- ReleaseWriteLock(&afs_xvolume);
- ObtainWriteLock(&tv->lock, 111);
+
if (type == 2) {
- InstallUVolumeEntry(tv, uve, tcell->cellNum, tcell, areq);
+ LockAndInstallUVolumeEntry(tv, uve, tcell->cellNum, tcell, areq);
} else if (type == 1)
- InstallNVolumeEntry(tv, nve, tcell->cellNum);
+ LockAndInstallNVolumeEntry(tv, nve, tcell->cellNum);
else
- InstallVolumeEntry(tv, ove, tcell->cellNum);
+ LockAndInstallVolumeEntry(tv, ove, tcell->cellNum);
if (agood) {
if (!tv->name) {
tv->name = afs_osi_Alloc(strlen(aname) + 1);
+ osi_Assert(tv->name != NULL);
strcpy(tv->name, aname);
}
}
* Seek volume by it's name and attributes.
* If volume not found, try to add one.
* @param aname Volume name.
- * @param acell Cell
+ * @param acell Cell
* @param agood
* @param areq
* @param locktype Type of lock to be used.
- * @return
+ * @return
*/
struct volume *
-afs_GetVolumeByName(register char *aname, afs_int32 acell, int agood,
+afs_GetVolumeByName(char *aname, afs_int32 acell, int agood,
struct vrequest *areq, afs_int32 locktype)
{
afs_int32 i;
/**
* Init a new dynroot volume.
- * @param Volume FID.
+ * @param Volume FID.
* @return Volume or NULL if not found.
*/
static struct volume *
if (!tcell)
return NULL;
tve = afs_osi_Alloc(sizeof(*tve));
+ osi_Assert(tve != NULL);
if (!(tcell->states & CHasVolRef))
tcell->states |= CHasVolRef;
/**
* @param aname Volume name.
* @param acell Cell id.
- * @param agood
+ * @param agood
* @param areq Request type.
* @param locktype Type of lock to be used.
* @return Volume or NULL if failure.
char *tbuffer, *ve;
struct afs_conn *tconn;
struct vrequest treq;
+ struct rx_connection *rxconn;
if (strlen(aname) > VL_MAXNAMELEN) /* Invalid volume name */
return NULL;
do {
tconn =
afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum,
- &treq, SHARED_LOCK);
+ &treq, SHARED_LOCK, 0, &rxconn);
if (tconn) {
- if (tconn->srvr->server->flags & SNO_LHOSTS) {
+ if (tconn->parent->srvr->server->flags & SNO_LHOSTS) {
type = 0;
RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameO(tconn->id, aname, tve);
+ code = VL_GetEntryByNameO(rxconn, aname, tve);
RX_AFS_GLOCK();
- } else if (tconn->srvr->server->flags & SYES_LHOSTS) {
+ } else if (tconn->parent->srvr->server->flags & SYES_LHOSTS) {
type = 1;
RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameN(tconn->id, aname, ntve);
+ code = VL_GetEntryByNameN(rxconn, aname, ntve);
RX_AFS_GLOCK();
} else {
type = 2;
RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameU(tconn->id, aname, utve);
+ code = VL_GetEntryByNameU(rxconn, aname, utve);
RX_AFS_GLOCK();
- if (!(tconn->srvr->server->flags & SVLSRV_UUID)) {
+ if (!(tconn->parent->srvr->server->flags & SVLSRV_UUID)) {
if (code == RXGEN_OPCODE) {
type = 1;
RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameN(tconn->id, aname, ntve);
+ code = VL_GetEntryByNameN(rxconn, aname, ntve);
RX_AFS_GLOCK();
if (code == RXGEN_OPCODE) {
type = 0;
- tconn->srvr->server->flags |= SNO_LHOSTS;
+ tconn->parent->srvr->server->flags |= SNO_LHOSTS;
RX_AFS_GUNLOCK();
- code = VL_GetEntryByNameO(tconn->id, aname, tve);
+ code = VL_GetEntryByNameO(rxconn, aname, tve);
RX_AFS_GLOCK();
} else if (!code)
- tconn->srvr->server->flags |= SYES_LHOSTS;
+ tconn->parent->srvr->server->flags |= SYES_LHOSTS;
} else if (!code)
- tconn->srvr->server->flags |= SVLSRV_UUID;
+ tconn->parent->srvr->server->flags |= SVLSRV_UUID;
}
lastnvcode = code;
}
} else
code = -1;
- } while (afs_Analyze(tconn, code, NULL, &treq, -1, /* no op code for this */
+ } while (afs_Analyze(tconn, rxconn, code, NULL, &treq, -1, /* no op code for this */
SHARED_LOCK, tcell));
if (code) {
ve = (char *)ntve;
else
ve = (char *)tve;
- tv = afs_SetupVolume(0, aname, ve, tcell, agood, type, areq);
+ tv = afs_SetupVolume(0, aname, ve, tcell, agood, type, &treq);
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);
+ afs_SetupVolume(tv->backVol, (char *)0, ve, tcell, 0, type, &treq);
if (tv1) {
tv1->refCount--;
}
* 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 = afs_SetupVolume(tv->roVol, NULL, ve, tcell, 0, type, &treq);
if (tv1) {
tv1->refCount--;
}
-/**
+/**
* Call this with the volume structure locked; used for new-style vldb requests.
- * @param av Volume
+ * @param av Volume
* @param ve
* @param acell
*/
void
-InstallVolumeEntry(struct volume *av, struct vldbentry *ve, int acell)
+LockAndInstallVolumeEntry(struct volume *av, struct vldbentry *ve, int acell)
{
- register struct server *ts;
+ struct server *ts;
struct cell *cellp;
- register int i, j;
+ int i, j;
afs_int32 mask;
afs_uint32 temp;
+ char types = 0;
+ struct server *serverHost[AFS_MAXHOSTS];
AFS_STATCNT(InstallVolumeEntry);
+ memset(serverHost, 0, sizeof(serverHost));
+
/* Determine the type of volume we want */
if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) {
mask = VLSF_RWVOL;
} else if ((ve->flags & VLF_ROEXISTS)
&& (av->volume == ve->volumeId[ROVOL])) {
mask = VLSF_ROVOL;
- av->states |= VRO;
+ types |= VRO;
} else if ((ve->flags & VLF_BACKEXISTS)
&& (av->volume == ve->volumeId[BACKVOL])) {
/* backup always is on the same volume as parent */
mask = VLSF_RWVOL;
- av->states |= (VRO | VBackup);
+ types |= (VRO | VBackup);
} else {
mask = 0; /* Can't find volume in vldb entry */
}
- /* fill in volume types */
- av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0);
- av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0);
- av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
-
- if (ve->flags & VLF_DFSFILESET)
- av->states |= VForeign;
-
cellp = afs_GetCell(acell, 0);
- /* This volume, av, is locked. Zero out the serverHosts[] array
- * so that if afs_GetServer() decides to replace the server
- * struct, we don't deadlock trying to afs_ResetVolumeInfo()
- * this volume.
- */
- for (j = 0; j < AFS_MAXHOSTS; j++) {
- av->serverHost[j] = 0;
- }
-
/* Step through the VLDB entry making sure each server listed is there */
for (i = 0, j = 0; i < ve->nServers; i++) {
if (((ve->serverFlags[i] & mask) == 0)
temp = htonl(ve->serverNumber[i]);
ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK,
- (afsUUID *) 0, 0);
- av->serverHost[j] = ts;
+ (afsUUID *) 0, 0, av);
+ serverHost[j] = ts;
/*
* The cell field could be 0 if the server entry was created
afs_PutServer(ts, WRITE_LOCK);
j++;
}
- if (j < AFS_MAXHOSTS) {
- av->serverHost[j++] = 0;
- }
+
+ ObtainWriteLock(&av->lock, 109);
+
+ memcpy(av->serverHost, serverHost, sizeof(serverHost));
+
+ /* from above */
+ av->states |= types;
+
+ /* fill in volume types */
+ av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0);
+ av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0);
+ av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
+
+ if (ve->flags & VLF_DFSFILESET)
+ av->states |= VForeign;
+
afs_SortServers(av->serverHost, AFS_MAXHOSTS);
} /*InstallVolumeEntry */
void
-InstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell)
+LockAndInstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell)
{
- register struct server *ts;
+ struct server *ts;
struct cell *cellp;
- register int i, j;
+ int i, j;
afs_int32 mask;
afs_uint32 temp;
+ char types = 0;
+ struct server *serverHost[AFS_MAXHOSTS];
AFS_STATCNT(InstallVolumeEntry);
+ memset(serverHost, 0, sizeof(serverHost));
+
/* Determine type of volume we want */
if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) {
mask = VLSF_RWVOL;
} else if ((ve->flags & VLF_ROEXISTS)
&& (av->volume == ve->volumeId[ROVOL])) {
mask = VLSF_ROVOL;
- av->states |= VRO;
+ types |= VRO;
} else if ((ve->flags & VLF_BACKEXISTS)
&& (av->volume == ve->volumeId[BACKVOL])) {
/* backup always is on the same volume as parent */
mask = VLSF_RWVOL;
- av->states |= (VRO | VBackup);
+ types |= (VRO | VBackup);
} else {
mask = 0; /* Can't find volume in vldb entry */
}
- /* fill in volume types */
- av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0);
- av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0);
- av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
-
- if (ve->flags & VLF_DFSFILESET)
- av->states |= VForeign;
-
cellp = afs_GetCell(acell, 0);
- /* This volume, av, is locked. Zero out the serverHosts[] array
- * so that if afs_GetServer() decides to replace the server
- * struct, we don't deadlock trying to afs_ResetVolumeInfo()
- * this volume.
- */
- for (j = 0; j < AFS_MAXHOSTS; j++) {
- av->serverHost[j] = 0;
- }
-
/* Step through the VLDB entry making sure each server listed is there */
for (i = 0, j = 0; i < ve->nServers; i++) {
if (((ve->serverFlags[i] & mask) == 0)
temp = htonl(ve->serverNumber[i]);
ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK,
- (afsUUID *) 0, 0);
- av->serverHost[j] = ts;
+ (afsUUID *) 0, 0, av);
+ serverHost[j] = ts;
/*
* The cell field could be 0 if the server entry was created
* first with the 'fs setserverprefs' call which doesn't set
afs_PutServer(ts, WRITE_LOCK);
j++;
}
- if (j < AFS_MAXHOSTS) {
- av->serverHost[j++] = 0;
- }
+
+ ObtainWriteLock(&av->lock, 110);
+
+ memcpy(av->serverHost, serverHost, sizeof(serverHost));
+
+ /* from above */
+ av->states |= types;
+
+ /* fill in volume types */
+ av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0);
+ av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0);
+ av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
+
+ if (ve->flags & VLF_DFSFILESET)
+ av->states |= VForeign;
+
afs_SortServers(av->serverHost, AFS_MAXHOSTS);
} /*InstallNVolumeEntry */
void
-InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
- struct cell *tcell, struct vrequest *areq)
+LockAndInstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
+ struct cell *tcell, struct vrequest *areq)
{
- register struct server *ts;
+ struct server *ts;
struct afs_conn *tconn;
struct cell *cellp;
- register int i, j;
+ int i, j;
afs_uint32 serverid;
afs_int32 mask;
int k;
+ char type = 0;
+ struct server *serverHost[AFS_MAXHOSTS];
AFS_STATCNT(InstallVolumeEntry);
+ memset(serverHost, 0, sizeof(serverHost));
+
/* Determine type of volume we want */
if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) {
mask = VLSF_RWVOL;
} else if ((ve->flags & VLF_ROEXISTS)
&& av->volume == ve->volumeId[ROVOL]) {
mask = VLSF_ROVOL;
- av->states |= VRO;
+ type |= VRO;
} else if ((ve->flags & VLF_BACKEXISTS)
&& (av->volume == ve->volumeId[BACKVOL])) {
/* backup always is on the same volume as parent */
mask = VLSF_RWVOL;
- av->states |= (VRO | VBackup);
+ type |= (VRO | VBackup);
} else {
mask = 0; /* Can't find volume in vldb entry */
}
- /* fill in volume types */
- av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0);
- av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0);
- av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
-
- if (ve->flags & VLF_DFSFILESET)
- av->states |= VForeign;
-
cellp = afs_GetCell(acell, 0);
- /* This volume, av, is locked. Zero out the serverHosts[] array
- * so that if afs_GetServer() decides to replace the server
- * struct, we don't deadlock trying to afs_ResetVolumeInfo()
- * this volume.
- */
- for (j = 0; j < AFS_MAXHOSTS; j++) {
- av->serverHost[j] = 0;
- }
-
/* Gather the list of servers the VLDB says the volume is on
* and initialize the ve->serverHost[] array. If a server struct
* is not found, then get the list of addresses for the
continue; /* wrong volume don't use this volume */
}
- if (!(ve->serverFlags[i] & VLSERVER_FLAG_UUID)) {
+ if (!(ve->serverFlags[i] & VLSF_UUID)) {
/* The server has no uuid */
serverid = htonl(ve->serverNumber[i].time_low);
- ts = afs_GetServer(&serverid, 1, acell, cellp->fsport, WRITE_LOCK,
- (afsUUID *) 0, 0);
+ ts = afs_GetServer(&serverid, 1, acell, cellp->fsport,
+ WRITE_LOCK, (afsUUID *) 0, 0, av);
} else {
ts = afs_FindServer(0, cellp->fsport, &ve->serverNumber[i], 0);
if (ts && (ts->sr_addr_uniquifier == ve->serverUnique[i])
bulkaddrs addrs;
ListAddrByAttributes attrs;
afsUUID uuid;
+ struct rx_connection *rxconn;
memset(&attrs, 0, sizeof(attrs));
attrs.Mask = VLADDR_UUID;
do {
tconn =
afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
- tcell->cellNum, areq, SHARED_LOCK);
+ tcell->cellNum, areq, SHARED_LOCK,
+ 0, &rxconn);
if (tconn) {
RX_AFS_GUNLOCK();
code =
- VL_GetAddrsU(tconn->id, &attrs, &uuid, &unique,
+ VL_GetAddrsU(rxconn, &attrs, &uuid, &unique,
&nentries, &addrs);
RX_AFS_GLOCK();
} else {
code = VL_NOENT;
} while (afs_Analyze
- (tconn, code, NULL, areq, -1, SHARED_LOCK, tcell));
+ (tconn, rxconn, code, NULL, areq, -1, SHARED_LOCK, tcell));
if (code) {
/* Better handing of such failures; for now we'll simply retry this call */
areq->volumeError = 1;
for (k = 0; k < nentries; k++) {
addrp[k] = htonl(addrp[k]);
}
- ts = afs_GetServer(addrp, nentries, acell, cellp->fsport,
- WRITE_LOCK, &ve->serverNumber[i],
- ve->serverUnique[i]);
+ ts = afs_GetServer(addrp, nentries, acell,
+ cellp->fsport, WRITE_LOCK,
+ &ve->serverNumber[i],
+ ve->serverUnique[i], av);
xdr_free((xdrproc_t) xdr_bulkaddrs, &addrs);
}
}
- av->serverHost[j] = ts;
+ serverHost[j] = ts;
/* The cell field could be 0 if the server entry was created
* first with the 'fs setserverprefs' call which doesn't set
j++;
}
+ ObtainWriteLock(&av->lock, 111);
+
+ memcpy(av->serverHost, serverHost, sizeof(serverHost));
+
+ /* from above */
+ av->states |= type;
+
+ /* fill in volume types */
+ av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0);
+ av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0);
+ av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
+
+ if (ve->flags & VLF_DFSFILESET)
+ av->states |= VForeign;
+
afs_SortServers(av->serverHost, AFS_MAXHOSTS);
} /*InstallVolumeEntry */
/**
- * Reset volume info for the specified volume strecture. Mark volume
+ * Reset volume info for the specified volume strecture. Mark volume
* to be rechecked next time.
- * @param tv
+ * @param tv
*/
void
afs_ResetVolumeInfo(struct volume *tv)
AFS_STATCNT(afs_ResetVolumeInfo);
ObtainWriteLock(&tv->lock, 117);
tv->states |= VRecheck;
+
+ /* the hard-mount code in afs_Analyze may not be able to reset this flag
+ * when VRecheck is set, so clear it here to ensure it gets cleared. */
+ tv->states &= ~VHardMount;
+
for (i = 0; i < AFS_MAXHOSTS; i++)
tv->status[i] = not_busy;
if (tv->name) {