/*
* 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 <afs/stds.h>
#include <windows.h>
#include <malloc.h>
#include <osi.h>
#include <string.h>
+#define STRSAFE_NO_DEPRECATE
+#include <strsafe.h>
#include "afsd.h"
osi_rwlock_t cm_cellLock;
/* function called as callback proc from cm_SearchCellFile. Return 0 to
- * continue processing.
+ * continue processing.
*
* At the present time the return value is ignored by the caller.
*/
cm_cell_t *cellp;
cm_cell_rock_t *cellrockp = (cm_cell_rock_t *)rockp;
afs_uint32 probe;
-
+
cellp = cellrockp->cellp;
probe = !(cellrockp->flags & CM_FLAG_NOPROBE);
/* if this server was previously created by fs setserverprefs */
- if ( tsp = cm_FindServer(addrp, CM_SERVER_VLDB))
+ if ( tsp = cm_FindServer(addrp, CM_SERVER_VLDB, FALSE))
{
if ( !tsp->cellp )
tsp->cellp = cellp;
else if (tsp->cellp != cellp) {
osi_Log3(afsd_logp, "found a vlserver %s associated with two cells named %s and %s",
osi_LogSaveString(afsd_logp,hostnamep),
- osi_LogSaveString(afsd_logp,tsp->cellp->name),
+ osi_LogSaveString(afsd_logp,tsp->cellp->name),
osi_LogSaveString(afsd_logp,cellp->name));
}
- }
+ }
else
tsp = cm_NewServer(addrp, CM_SERVER_VLDB, cellp, NULL, probe ? 0 : CM_FLAG_NOPROBE);
- tsp->ipRank = ipRank;
+ if (ipRank)
+ tsp->ipRank = ipRank;
/* Insert the vlserver into a sorted list, sorted by server rank */
tsrp = cm_NewServerRef(tsp, 0);
cm_InsertServerList(&cellp->vlServersp, tsrp);
- /* drop the allocation reference */
- lock_ObtainWrite(&cm_serverLock);
- tsrp->refCount--;
- lock_ReleaseWrite(&cm_serverLock);
return 0;
}
-/* if it's from DNS, see if it has expired
+/* if it's from DNS, see if it has expired
* and check to make sure we have a valid set of volume servers
* this function must not be called with a lock on cm_cellLock
*/
{
long code = 0;
cm_cell_rock_t rock;
+ afs_uint32 mxheld = 0;
if (cp == NULL)
return NULL;
lock_ObtainMutex(&cp->mx);
- if ((cp->vlServersp == NULL
+ mxheld = 1;
+
#ifdef AFS_FREELANCE_CLIENT
- && !(cp->flags & CM_CELLFLAG_FREELANCE)
-#endif
- ) || (time(0) > cp->timeout)
-#ifdef AFS_AFSDB_ENV
- || (cm_dnsEnabled && (cp->flags & CM_CELLFLAG_DNS) &&
- ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID)))
+ if (cp->flags & CM_CELLFLAG_FREELANCE) {
+ lock_ReleaseMutex(&cp->mx);
+ return cp;
+ }
#endif
- )
+
+ if ((cp->vlServersp == NULL) ||
+ (time(0) > cp->timeout) ||
+ (cm_dnsEnabled &&
+ (cp->flags & CM_CELLFLAG_DNS) &&
+ ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID))))
{
lock_ReleaseMutex(&cp->mx);
+ mxheld = 0;
/* must empty cp->vlServersp */
- if (cp->vlServersp) {
+ if (cp->vlServersp)
cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
- cp->vlServersp = NULL;
- }
rock.cellp = cp;
rock.flags = flags;
code = cm_SearchCellFileEx(cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock);
if (code == 0) {
lock_ObtainMutex(&cp->mx);
+ mxheld = 1;
cp->timeout = time(0) + 7200;
- lock_ReleaseMutex(&cp->mx);
}
-#ifdef AFS_AFSDB_ENV
else {
if (cm_dnsEnabled) {
int ttl;
code = cm_SearchCellByDNS(cp->name, NULL, &ttl, cm_AddCellProc, &rock);
if (code == 0) { /* got cell from DNS */
lock_ObtainMutex(&cp->mx);
- cp->flags |= CM_CELLFLAG_DNS;
- cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
+ mxheld = 1;
+ _InterlockedOr(&cp->flags, CM_CELLFLAG_DNS);
+ _InterlockedAnd(&cp->flags, ~CM_CELLFLAG_VLSERVER_INVALID);
cp->timeout = time(0) + ttl;
- lock_ReleaseMutex(&cp->mx);
#ifdef DEBUG
fprintf(stderr, "cell %s: ttl=%d\n", cp->name, ttl);
#endif
} else {
/* if we fail to find it this time, we'll just do nothing and leave the
- * current entry alone
+ * current entry alone
*/
lock_ObtainMutex(&cp->mx);
- cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
- lock_ReleaseMutex(&cp->mx);
+ mxheld = 1;
+ _InterlockedOr(&cp->flags, CM_CELLFLAG_VLSERVER_INVALID);
}
}
}
-#endif /* AFS_AFSDB_ENV */
- } else {
- lock_ReleaseMutex(&cp->mx);
}
+
+ if (code == 0)
+ cm_RandomizeServer(&cp->vlServersp);
+
+ if (mxheld)
+ lock_ReleaseMutex(&cp->mx);
+
return code ? NULL : cp;
}
if (cellp->vlServersp)
cm_FreeServerList(&cellp->vlServersp, CM_FREESERVERLIST_DELETE);
- cellp->name[0] = '\0';
+ cellp->name[0] = '\0';
cellp->freeNextp = cm_data.freeCellsp;
cm_data.freeCellsp = cellp;
cm_cell_rock_t rock;
size_t len;
- if (namep == NULL || !namep[0] || !strcmp(namep,SMB_IOCTL_FILENAME_NOSLASH))
+ if (namep == NULL || !namep[0] || !strcmp(namep,CM_IOCTL_FILENAME_NOSLASH))
return NULL;
- /*
+ /*
* Strip off any trailing dots at the end of the cell name.
* Failure to do so results in an undesireable alias as the
* result of DNS AFSDB record lookups where a trailing dot
fullname[CELL_MAXNAMELEN-1] = '\0';
break;
}
- }
+ }
}
if (cp) {
hasWriteLock = 1;
/* when we dropped the lock the cell could have been added
- * to the list so check again while holding the write lock
+ * to the list so check again while holding the write lock
*/
for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) {
if (cm_stricmp_utf8(namep, cp->name) == 0) {
fullname[CELL_MAXNAMELEN-1] = '\0';
break;
}
- }
+ }
if (cp)
goto done;
fullname[CELL_MAXNAMELEN-1] = '\0';
break;
}
- }
+ }
if (cp) {
lock_ReleaseWrite(&cm_cellLock);
lock_ObtainMutex(&cp->mx);
lock_ObtainWrite(&cm_cellLock);
cm_AddCellToNameHashTable(cp);
- cm_AddCellToIDHashTable(cp);
+ cm_AddCellToIDHashTable(cp);
lock_ReleaseMutex(&cp->mx);
goto done;
}
cp = cm_data.freeCellsp;
cm_data.freeCellsp = cp->freeNextp;
- /*
+ /*
* The magic, cellID, and mx fields are already set.
*/
} else {
if ( cm_data.currentCells >= cm_data.maxCells )
osi_panic("Exceeded Max Cells", __FILE__, __LINE__);
- /* don't increment currentCells until we know that we
- * are going to keep this entry
+ /* don't increment currentCells until we know that we
+ * are going to keep this entry
*/
cp = &cm_data.cellBaseAddress[cm_data.currentCells];
memset(cp, 0, sizeof(cm_cell_t));
if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
code = cm_SearchCellFileEx(namep, fullname, linkedName, cm_AddCellProc, &rock);
if (code) {
- osi_Log4(afsd_logp,"in cm_GetCell_gen cm_SearchCellFileEx(%s) returns code= %d fullname= %s linkedName= %s",
+ osi_Log4(afsd_logp,"in cm_GetCell_gen cm_SearchCellFileEx(%s) returns code= %d fullname= %s linkedName= %s",
osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname),
osi_LogSaveString(afsd_logp,linkedName));
-#ifdef AFS_AFSDB_ENV
if (cm_dnsEnabled) {
int ttl;
code = cm_SearchCellByDNS(namep, fullname, &ttl, cm_AddCellProc, &rock);
if ( code ) {
- osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s",
+ osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s",
osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname));
lock_ObtainMutex(&cp->mx);
lock_ObtainWrite(&cm_cellLock);
} else { /* got cell from DNS */
lock_ObtainMutex(&cp->mx);
hasMutex = 1;
- cp->flags |= CM_CELLFLAG_DNS;
- cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
+ _InterlockedOr(&cp->flags, CM_CELLFLAG_DNS);
+ _InterlockedAnd(&cp->flags, ~CM_CELLFLAG_VLSERVER_INVALID);
cp->timeout = time(0) + ttl;
}
- }
- else
-#endif
+ }
+ else
{
lock_ObtainMutex(&cp->mx);
lock_ObtainWrite(&cm_cellLock);
/* we have now been given the fullname of the cell. It may
* be that we already have a cell with that name. If so,
* we should use it instead of completing the allocation
- * of a new cm_cell_t
+ * of a new cm_cell_t
*/
lock_ObtainRead(&cm_cellLock);
hash = CM_CELL_NAME_HASH(fullname);
if (cm_stricmp_utf8(fullname, cp2->name) == 0) {
break;
}
- }
+ }
if (cp2) {
if (!hasMutex) {
}
lock_ReleaseRead(&cm_cellLock);
- /* randomise among those vlservers having the same rank*/
+ /* randomise among those vlservers having the same rank*/
cm_RandomizeServer(&cp->vlServersp);
if (!hasMutex)
lock_ObtainWrite(&cm_cellLock);
hasWriteLock = 1;
cm_AddCellToNameHashTable(cp);
- cm_AddCellToIDHashTable(cp);
+ cm_AddCellToIDHashTable(cp);
lock_ReleaseMutex(&cp->mx);
hasMutex = 0;
lock_ReleaseMutex(&cp->mx);
if (hasWriteLock)
lock_ReleaseWrite(&cm_cellLock);
-
+
/* fullname is not valid if cp == NULL */
if (newnamep) {
if (cp) {
if (cp && cp->linkedName[0]) {
cm_cell_t * linkedCellp = NULL;
-
+
if (!strcmp(cp->name, cp->linkedName)) {
- cp->linkedName[0] = '\0';
+ cp->linkedName[0] = '\0';
} else if (!(flags & CM_FLAG_NOMOUNTCHASE)) {
linkedCellp = cm_GetCell(cp->linkedName, CM_FLAG_CREATE|CM_FLAG_NOPROBE|CM_FLAG_NOMOUNTCHASE);
lock_ObtainWrite(&cm_cellLock);
- if (!linkedCellp ||
+ if (!linkedCellp ||
(linkedCellp->linkedName[0] && strcmp(cp->name, linkedCellp->linkedName))) {
cp->linkedName[0] = '\0';
} else {
hash = CM_CELL_ID_HASH(cellID);
for (cp = cm_data.cellIDHashTablep[hash]; cp; cp=cp->idNextp) {
- if (cellID == cp->cellID)
+ if (cellID == cp->cellID)
break;
}
- lock_ReleaseRead(&cm_cellLock);
+ lock_ReleaseRead(&cm_cellLock);
if (cp)
cm_UpdateCell(cp, flags);
return cp;
}
-long
+long
cm_ValidateCell(void)
{
cm_cell_t * cellp;
fprintf(stderr, "cm_ValidateCell failure: count != cm_data.currentCells\n");
return -4;
}
-
+
return 0;
}
-long
+long
cm_ShutdownCell(void)
{
cm_cell_t * cellp;
void cm_InitCell(int newFile, long maxCells)
{
static osi_once_t once;
-
+
if (osi_Once(&once)) {
cm_cell_t * cellp;
cm_data.maxCells = maxCells;
memset(cm_data.cellNameHashTablep, 0, sizeof(cm_cell_t *) * cm_data.cellHashTableSize);
memset(cm_data.cellIDHashTablep, 0, sizeof(cm_cell_t *) * cm_data.cellHashTableSize);
-
+
#ifdef AFS_FREELANCE_CLIENT
- /* Generate a dummy entry for the Freelance cell whether or not
- * freelance mode is being used in this session
+ /* Generate a dummy entry for the Freelance cell whether or not
+ * freelance mode is being used in this session
*/
cellp = &cm_data.cellBaseAddress[cm_data.currentCells++];
/* thread on global list */
cellp->allNextp = cm_data.allCellsp;
cm_data.allCellsp = cellp;
-
+
cellp->cellID = AFS_FAKE_ROOT_CELL_ID;
cellp->vlServersp = NULL;
- cellp->flags = CM_CELLFLAG_FREELANCE;
+ _InterlockedOr(&cellp->flags, CM_CELLFLAG_FREELANCE);
cm_AddCellToNameHashTable(cellp);
cm_AddCellToIDHashTable(cellp);
lock_ReleaseWrite(&cm_cellLock);
lock_ReleaseMutex(&cellp->mx);
-#endif
+#endif
} else {
lock_ObtainRead(&cm_cellLock);
for (cellp = cm_data.allCellsp; cellp; cellp=cellp->allNextp) {
lock_InitializeMutex(&cellp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL);
cellp->vlServersp = NULL;
- cellp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
+ _InterlockedOr(&cellp->flags, CM_CELLFLAG_VLSERVER_INVALID);
}
lock_ReleaseRead(&cm_cellLock);
}
lock_ReleaseMutex(&cp->mx);
}
-}
+}
int cm_DumpCells(FILE *outputFile, char *cookie, int lock)
{
if (lock)
lock_ObtainRead(&cm_cellLock);
- sprintf(output, "%s - dumping cells - cm_data.currentCells=%d, cm_data.maxCells=%d\r\n",
+ sprintf(output, "%s - dumping cells - cm_data.currentCells=%d, cm_data.maxCells=%d\r\n",
cookie, cm_data.currentCells, cm_data.maxCells);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (cellp = cm_data.allCellsp; cellp; cellp=cellp->allNextp) {
- sprintf(output, "%s cellp=0x%p,name=%s ID=%d flags=0x%x timeout=%I64u\r\n",
+ sprintf(output, "%s cellp=0x%p,name=%s ID=%d flags=0x%x timeout=%I64u\r\n",
cookie, cellp, cellp->name, cellp->cellID, cellp->flags, cellp->timeout);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
void cm_AddCellToNameHashTable(cm_cell_t *cellp)
{
int i;
-
+
lock_AssertWrite(&cm_cellLock);
lock_AssertMutex(&cellp->mx);
cellp->nameNextp = cm_data.cellNameHashTablep[i];
cm_data.cellNameHashTablep[i] = cellp;
- cellp->flags |= CM_CELLFLAG_IN_NAMEHASH;
+ _InterlockedOr(&cellp->flags, CM_CELLFLAG_IN_NAMEHASH);
}
/* call with cell write-locked and mutex held */
cm_cell_t **lcellpp;
cm_cell_t *tcellp;
int i;
-
+
lock_AssertWrite(&cm_cellLock);
lock_AssertMutex(&cellp->mx);
lcellpp = &tcellp->nameNextp, tcellp = tcellp->nameNextp) {
if (tcellp == cellp) {
*lcellpp = cellp->nameNextp;
- cellp->flags &= ~CM_CELLFLAG_IN_NAMEHASH;
+ _InterlockedAnd(&cellp->flags, ~CM_CELLFLAG_IN_NAMEHASH);
cellp->nameNextp = NULL;
break;
}
void cm_AddCellToIDHashTable(cm_cell_t *cellp)
{
int i;
-
+
lock_AssertWrite(&cm_cellLock);
lock_AssertMutex(&cellp->mx);
cellp->idNextp = cm_data.cellIDHashTablep[i];
cm_data.cellIDHashTablep[i] = cellp;
- cellp->flags |= CM_CELLFLAG_IN_IDHASH;
+ _InterlockedOr(&cellp->flags, CM_CELLFLAG_IN_IDHASH);
}
/* call with cell write-locked and mutex held */
cm_cell_t **lcellpp;
cm_cell_t *tcellp;
int i;
-
+
lock_AssertWrite(&cm_cellLock);
lock_AssertMutex(&cellp->mx);
lcellpp = &tcellp->idNextp, tcellp = tcellp->idNextp) {
if (tcellp == cellp) {
*lcellpp = cellp->idNextp;
- cellp->flags &= ~CM_CELLFLAG_IN_IDHASH;
+ _InterlockedAnd(&cellp->flags, ~CM_CELLFLAG_IN_IDHASH);
cellp->idNextp = NULL;
break;
}
}
}
+long
+cm_CreateCellWithInfo( char * cellname,
+ char * linked_cellname,
+ unsigned short vlport,
+ afs_uint32 host_count,
+ char *hostname[],
+ afs_uint32 flags)
+{
+ afs_uint32 code = 0;
+ cm_cell_rock_t rock;
+ struct hostent *thp;
+ struct sockaddr_in vlSockAddr;
+ afs_uint32 i, j;
+
+ rock.cellp = cm_GetCell(cellname, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
+ rock.flags = 0;
+
+ cm_FreeServerList(&rock.cellp->vlServersp, CM_FREESERVERLIST_DELETE);
+
+ if (!(flags & CM_CELLFLAG_DNS)) {
+ for (i = 0; i < host_count; i++) {
+ thp = gethostbyname(hostname[i]);
+ if (thp) {
+ int foundAddr = 0;
+ for (j=0 ; thp->h_addr_list[j]; j++) {
+ if (thp->h_addrtype != AF_INET)
+ continue;
+ memcpy(&vlSockAddr.sin_addr.s_addr,
+ thp->h_addr_list[j],
+ sizeof(long));
+ vlSockAddr.sin_port = htons(vlport ? vlport : 7003);
+ vlSockAddr.sin_family = AF_INET;
+ cm_AddCellProc(&rock, &vlSockAddr, hostname[i], CM_FLAG_NOPROBE);
+ }
+ }
+ }
+ lock_ObtainMutex(&rock.cellp->mx);
+ _InterlockedAnd(&rock.cellp->flags, ~CM_CELLFLAG_DNS);
+ } else if (cm_dnsEnabled) {
+ int ttl;
+
+ code = cm_SearchCellByDNS(rock.cellp->name, NULL, &ttl, cm_AddCellProc, &rock);
+ lock_ObtainMutex(&rock.cellp->mx);
+ if (code == 0) { /* got cell from DNS */
+ _InterlockedOr(&rock.cellp->flags, CM_CELLFLAG_DNS);
+ rock.cellp->timeout = time(0) + ttl;
+#ifdef DEBUG
+ fprintf(stderr, "cell %s: ttl=%d\n", rock.cellp->name, ttl);
+#endif
+ }
+ } else {
+ lock_ObtainMutex(&rock.cellp->mx);
+ rock.cellp->flags &= ~CM_CELLFLAG_DNS;
+ }
+ _InterlockedOr(&rock.cellp->flags, CM_CELLFLAG_VLSERVER_INVALID);
+ StringCbCopy(rock.cellp->linkedName, CELL_MAXNAMELEN, linked_cellname);
+ lock_ReleaseMutex(&rock.cellp->mx);
+
+ if (rock.cellp->vlServersp)
+ cm_RandomizeServer(&rock.cellp->vlServersp);
+
+ return code;
+}