Beispiel #1
0
void
LockAndInstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell)
{
    struct server *ts;
    struct cell *cellp;
    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;
	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;
	types |= (VRO | VBackup);
    } else {
	mask = 0;		/* Can't find volume in vldb entry */
    }

    cellp = afs_GetCell(acell, 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)
	    || (ve->serverFlags[i] & VLSF_DONTUSE)) {
	    continue;		/* wrong volume or don't use this volume */
	}

	temp = htonl(ve->serverNumber[i]);
	ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK,
			   (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
	 * the cell field. Thus if the afs_GetServer call above
	 * follows later on it will find the server entry thus it will
	 * simply return without setting any fields, so we set the
	 * field ourselves below.
	 */
	if (!ts->cell)
	    ts->cell = cellp;
	afs_PutServer(ts, WRITE_LOCK);
	j++;
    }

    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 */
Beispiel #2
0
void
LockAndInstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
			   struct cell *tcell, struct vrequest *areq)
{
    struct server *ts;
    struct afs_conn *tconn;
    struct cell *cellp;
    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;
	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;
	type |= (VRO | VBackup);
    } else {
	mask = 0;		/* Can't find volume in vldb entry */
    }

    cellp = afs_GetCell(acell, 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
     * server, VL_GetAddrsU(), and create a server struct, afs_GetServer().
     */
    for (i = 0, j = 0; i < ve->nServers; i++) {
	if (((ve->serverFlags[i] & mask) == 0)
	    || (ve->serverFlags[i] & VLSF_DONTUSE)) {
	    continue;		/* wrong volume don't use this volume */
	}

	if (!(ve->serverFlags[i] & VLSERVER_FLAG_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, av);
	} else {
	    ts = afs_FindServer(0, cellp->fsport, &ve->serverNumber[i], 0);
	    if (ts && (ts->sr_addr_uniquifier == ve->serverUnique[i])
		&& ts->addr) {
		/* uuid, uniquifier, and portal are the same */
	    } else {
		afs_uint32 *addrp, code;
		afs_int32 nentries, unique;
		bulkaddrs addrs;
		ListAddrByAttributes attrs;
		afsUUID uuid;
		struct rx_connection *rxconn;

		memset(&attrs, 0, sizeof(attrs));
		attrs.Mask = VLADDR_UUID;
		attrs.uuid = ve->serverNumber[i];
		memset(&uuid, 0, sizeof(uuid));
		memset(&addrs, 0, sizeof(addrs));
		do {
		    tconn =
			afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
					 tcell->cellNum, areq, SHARED_LOCK,
					 0, &rxconn);
		    if (tconn) {
			RX_AFS_GUNLOCK();
			code =
			    VL_GetAddrsU(rxconn, &attrs, &uuid, &unique,
					 &nentries, &addrs);
			RX_AFS_GLOCK();
		    } else {
			code = -1;
		    }

		    /* Handle corrupt VLDB (defect 7393) */
		    if (code == 0 && nentries == 0)
			code = VL_NOENT;

		} while (afs_Analyze
			 (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;
		    return;
		}

		addrp = addrs.bulkaddrs_val;
		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], av);
		xdr_free((xdrproc_t) xdr_bulkaddrs, &addrs);
	    }
#if defined(AFS_LINUX26_ENV) && !defined(UKERNEL)
            if (afs_compare_serveruuid(&ve->serverNumber[i]))
                av->states |= VPartVisible;
#endif
	}
	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
	 * the cell field. Thus if the afs_GetServer call above
	 * follows later on it will find the server entry thus it will
	 * simply return without setting any fields, so we set the
	 * field ourselves below.
	 */
	if (!ts->cell)
	    ts->cell = cellp;
	afs_PutServer(ts, WRITE_LOCK);
	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 */
Beispiel #3
0
void
InstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell)
{
    register struct server *ts;
    struct cell *cellp;
    register int i, j;
    afs_int32 mask;
    afs_uint32 temp;

    AFS_STATCNT(InstallVolumeEntry);

    /* 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;
    } 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);
    } 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 < 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)
	    || (ve->serverFlags[i] & VLSF_DONTUSE)) {
	    continue;		/* wrong volume or don't use this volume */
	}

	temp = htonl(ve->serverNumber[i]);
	ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK,
			   (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
	 * the cell field. Thus if the afs_GetServer call above
	 * follows later on it will find the server entry thus it will
	 * simply return without setting any fields, so we set the
	 * field ourselves below.
	 */
	if (!ts->cell)
	    ts->cell = cellp;
	afs_PutServer(ts, WRITE_LOCK);
	j++;
    }
    if (j < MAXHOSTS) {
	av->serverHost[j++] = 0;
    }
    afs_SortServers(av->serverHost, MAXHOSTS);
}				/*InstallNVolumeEntry */
Beispiel #4
0
/*!
 * Create or update a cell entry.
 * \param acellName Name of cell.
 * \param acellHosts Array of hosts that this cell has.
 * \param aflags Cell flags.
 * \param linkedcname
 * \param fsport File server port.
 * \param vlport Volume server port.
 * \param timeout Cell timeout value, 0 means static AFSDB entry.
 * \return
 */
afs_int32
afs_NewCell(char *acellName, afs_int32 * acellHosts, int aflags,
	    char *linkedcname, u_short fsport, u_short vlport, int timeout)
{
    struct cell *tc, *tcl = 0;
    afs_int32 i, newc = 0, code = 0;

    AFS_STATCNT(afs_NewCell);

    ObtainWriteLock(&afs_xcell, 103);

    tc = afs_FindCellByName_nl(acellName, READ_LOCK);
    if (tc) {
	aflags &= ~CNoSUID;
    } else {
	tc = afs_osi_Alloc(sizeof(struct cell));
	osi_Assert(tc != NULL);
	memset(tc, 0, sizeof(*tc));
	tc->cellName = afs_strdup(acellName);
	tc->fsport = AFS_FSPORT;
	tc->vlport = AFS_VLPORT;
	AFS_MD5_String(tc->cellHandle, tc->cellName, strlen(tc->cellName));
	AFS_RWLOCK_INIT(&tc->lock, "cell lock");
	newc = 1;
	aflags |= CNoSUID;
    }
    ObtainWriteLock(&tc->lock, 688);

    /* If the cell we've found has the correct name but no timeout,
     * and we're called with a non-zero timeout, bail out:  never
     * override static configuration entries with AFSDB ones.
     * One exception: if the original cell entry had no servers,
     * it must get servers from AFSDB.
     */
    if (timeout && !tc->timeout && tc->cellHosts[0]) {
	code = EEXIST;		/* This code is checked for in afs_LookupAFSDB */
	goto bad;
    }

    /* we don't want to keep pinging old vlservers which were down,
     * since they don't matter any more.  It's easier to do this than
     * to remove the server from its various hash tables. */
    for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
	if (!tc->cellHosts[i])
	    break;
	tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
	tc->cellHosts[i]->flags |= SRVR_ISGONE;
    }

    if (fsport)
	tc->fsport = fsport;
    if (vlport)
	tc->vlport = vlport;

    if (aflags & CLinkedCell) {
	if (!linkedcname) {
	    code = EINVAL;
	    goto bad;
	}
	tcl = afs_FindCellByName_nl(linkedcname, READ_LOCK);
	if (!tcl) {
	    code = ENOENT;
	    goto bad;
	}
	if (tcl->lcellp) {	/* XXX Overwriting if one existed before! XXX */
	    tcl->lcellp->lcellp = (struct cell *)0;
	    tcl->lcellp->states &= ~CLinkedCell;
	}
	tc->lcellp = tcl;
	tcl->lcellp = tc;
    }
    tc->states |= aflags;
    tc->timeout = timeout;

    memset(tc->cellHosts, 0, sizeof(tc->cellHosts));
    for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
	/* Get server for each host and link this cell in.*/
	struct server *ts;
	afs_uint32 temp = acellHosts[i];
	if (!temp)
	    break;
	ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0);
	ts->cell = tc;
	ts->flags &= ~SRVR_ISGONE;
	/* Set the server as a host of the new cell. */
	tc->cellHosts[i] = ts;
	afs_PutServer(ts, WRITE_LOCK);
    }
    afs_SortServers(tc->cellHosts, AFS_MAXCELLHOSTS);	/* randomize servers */

    /* New cell: Build and add to LRU cell queue. */
    if (newc) {
	struct cell_name *cn;

	cn = afs_cellname_lookup_name(acellName);
	if (!cn)
	    cn = afs_cellname_new(acellName, 0);

	tc->cnamep = cn;
	tc->cellNum = cn->cellnum;
	tc->cellIndex = afs_cellindex++;
	afs_stats_cmperf.numCellsVisible++;
	QAdd(&CellLRU, &tc->lruq);
    }

    ReleaseWriteLock(&tc->lock);
    ReleaseWriteLock(&afs_xcell);
    afs_PutCell(tc, 0);
    if (!(aflags & CHush))
	afs_DynrootInvalidate();
    return 0;

  bad:
    if (newc) {
	afs_osi_FreeStr(tc->cellName);
	afs_osi_Free(tc, sizeof(struct cell));
    }
    ReleaseWriteLock(&tc->lock);
    ReleaseWriteLock(&afs_xcell);
    return code;
}
Beispiel #5
0
void
InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
		    struct cell *tcell, struct vrequest *areq)
{
    register struct server *ts;
    struct afs_conn *tconn;
    struct cell *cellp;
    register int i, j;
    afs_uint32 serverid;
    afs_int32 mask;
    int k;

    AFS_STATCNT(InstallVolumeEntry);

    /* 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;
    } 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);
    } 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 < 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
     * server, VL_GetAddrsU(), and create a server struct, afs_GetServer().
     */
    for (i = 0, j = 0; i < ve->nServers; i++) {
	if (((ve->serverFlags[i] & mask) == 0)
	    || (ve->serverFlags[i] & VLSF_DONTUSE)) {
	    continue;		/* wrong volume don't use this volume */
	}

	if (!(ve->serverFlags[i] & VLSERVER_FLAG_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);
	} else {
	    ts = afs_FindServer(0, cellp->fsport, &ve->serverNumber[i], 0);
	    if (ts && (ts->sr_addr_uniquifier == ve->serverUnique[i])
		&& ts->addr) {
		/* uuid, uniquifier, and portal are the same */
	    } else {
		afs_uint32 *addrp, nentries, code, unique;
		bulkaddrs addrs;
		ListAddrByAttributes attrs;
		afsUUID uuid;

		memset((char *)&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));
		do {
		    tconn =
			afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
					 tcell->cellNum, areq, SHARED_LOCK);
		    if (tconn) {
			RX_AFS_GUNLOCK();
			code =
			    VL_GetAddrsU(tconn->id, &attrs, &uuid, &unique,
					 &nentries, &addrs);
			RX_AFS_GLOCK();
		    } else {
			code = -1;
		    }

		    /* Handle corrupt VLDB (defect 7393) */
		    if (code == 0 && nentries == 0)
			code = VL_NOENT;

		} while (afs_Analyze
			 (tconn, 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;
		    return;
		}

		addrp = addrs.bulkaddrs_val;
		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]);
		afs_osi_Free(addrs.bulkaddrs_val,
			     addrs.bulkaddrs_len * sizeof(*addrp));
	    }
	}
	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
	 * the cell field. Thus if the afs_GetServer call above
	 * follows later on it will find the server entry thus it will
	 * simply return without setting any fields, so we set the
	 * field ourselves below.
	 */
	if (!ts->cell)
	    ts->cell = cellp;
	afs_PutServer(ts, WRITE_LOCK);
	j++;
    }

    afs_SortServers(av->serverHost, MAXHOSTS);
}				/*InstallVolumeEntry */