コード例 #1
0
ファイル: afs_volume.c プロジェクト: gsell/openafs-osd
/**
 *   Init a new dynroot volume.
 * @param Volume FID.
 * @return Volume or NULL if not found.
 */
static struct volume *
afs_NewDynrootVolume(struct VenusFid *fid)
{
    struct cell *tcell;
    struct volume *tv;
    struct vldbentry *tve;
    char *bp, tbuf[CVBS];

    tcell = afs_GetCell(fid->Cell, READ_LOCK);
    if (!tcell)
	return NULL;
    tve = afs_osi_Alloc(sizeof(*tve));
    osi_Assert(tve != NULL);
    if (!(tcell->states & CHasVolRef))
	tcell->states |= CHasVolRef;

    bp = afs_cv2string(&tbuf[CVBS], fid->Fid.Volume);
    memset(tve, 0, sizeof(*tve));
    strcpy(tve->name, "local-dynroot");
    tve->volumeId[ROVOL] = fid->Fid.Volume;
    tve->flags = VLF_ROEXISTS;

    tv = afs_SetupVolume(0, bp, tve, tcell, 0, 0, 0);
    afs_PutCell(tcell, READ_LOCK);
    afs_osi_Free(tve, sizeof(*tve));
    return tv;
}
コード例 #2
0
ファイル: afs_volume.c プロジェクト: gsell/openafs-osd
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 */
コード例 #3
0
ファイル: afs_volume.c プロジェクト: gsell/openafs-osd
/**
 * @param aname Volume name.
 * @param acell Cell id.
 * @param agood
 * @param areq Request type.
 * @param locktype Type of lock to be used.
 * @return Volume or NULL if failure.
 */
static struct volume *
afs_NewVolumeByName(char *aname, afs_int32 acell, int agood,
		    struct vrequest *areq, afs_int32 locktype)
{
    afs_int32 code, type = 0;
    struct volume *tv, *tv1;
    struct vldbentry *tve;
    struct nvldbentry *ntve;
    struct uvldbentry *utve;
    struct cell *tcell;
    char *tbuffer, *ve;
    struct afs_conn *tconn;
    struct vrequest treq;
    struct rx_connection *rxconn;

    if (strlen(aname) > VL_MAXNAMELEN)	/* Invalid volume name */
	return NULL;

    tcell = afs_GetCell(acell, READ_LOCK);
    if (!tcell) {
	return NULL;
    }

    /* allow null request if we don't care about ENODEV/ETIMEDOUT distinction */
    if (!areq)
	areq = &treq;


    afs_Trace2(afs_iclSetp, CM_TRACE_GETVOL, ICL_TYPE_STRING, aname,
	       ICL_TYPE_POINTER, aname);
    tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
    tve = (struct vldbentry *)(tbuffer + 1024);
    ntve = (struct nvldbentry *)tve;
    utve = (struct uvldbentry *)tve;
    afs_InitReq(&treq, afs_osi_credp);	/* *must* be unauth for vldb */
    do {
	tconn =
	    afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum,
			     &treq, SHARED_LOCK, 0, &rxconn);
	if (tconn) {
	    if (tconn->srvr->server->flags & SNO_LHOSTS) {
		type = 0;
		RX_AFS_GUNLOCK();
		code = VL_GetEntryByNameO(rxconn, aname, tve);
		RX_AFS_GLOCK();
	    } else if (tconn->srvr->server->flags & SYES_LHOSTS) {
		type = 1;
		RX_AFS_GUNLOCK();
		code = VL_GetEntryByNameN(rxconn, aname, ntve);
		RX_AFS_GLOCK();
	    } else {
		type = 2;
		RX_AFS_GUNLOCK();
		code = VL_GetEntryByNameU(rxconn, aname, utve);
		RX_AFS_GLOCK();
		if (!(tconn->srvr->server->flags & SVLSRV_UUID)) {
		    if (code == RXGEN_OPCODE) {
			type = 1;
			RX_AFS_GUNLOCK();
			code = VL_GetEntryByNameN(rxconn, aname, ntve);
			RX_AFS_GLOCK();
			if (code == RXGEN_OPCODE) {
			    type = 0;
			    tconn->srvr->server->flags |= SNO_LHOSTS;
			    RX_AFS_GUNLOCK();
			    code = VL_GetEntryByNameO(rxconn, aname, tve);
			    RX_AFS_GLOCK();
			} else if (!code)
			    tconn->srvr->server->flags |= SYES_LHOSTS;
		    } else if (!code)
			tconn->srvr->server->flags |= SVLSRV_UUID;
		}
		lastnvcode = code;
	    }
	} else
	    code = -1;
    } while (afs_Analyze(tconn, rxconn, code, NULL, &treq, -1,	/* no op code for this */
			 SHARED_LOCK, tcell));

    if (code) {
	/* If the client has yet to contact this cell and contact failed due
	 * to network errors, mark the VLDB servers as back up.
	 * That the client tried and failed can be determined from the
	 * fact that there was a downtime incident, but CHasVolRef is not set.
	 */
    /* RT 48959 - unclear if this should really go */
#if 0
	if (areq->networkError && !(tcell->states & CHasVolRef)) {
	    int i;
	    struct server *sp;
	    struct srvAddr *sap;
	    for (i = 0; i < AFS_MAXCELLHOSTS; i++) {
		if ((sp = tcell->cellHosts[i]) == NULL)
		    break;
		for (sap = sp->addr; sap; sap = sap->next_sa)
		    afs_MarkServerUpOrDown(sap, 0);
	    }
	}
#endif
	afs_CopyError(&treq, areq);
	osi_FreeLargeSpace(tbuffer);
	afs_PutCell(tcell, READ_LOCK);
	return NULL;
    }
    /*
     * Check to see if this cell has not yet referenced a volume.  If
     * it hasn't, it's just about to change its status, and we need to mark
     * this fact down. Note that it is remotely possible that afs_SetupVolume
     * could fail and we would still not have a volume reference.
     */
    if (!(tcell->states & CHasVolRef)) {
	tcell->states |= CHasVolRef;
	afs_stats_cmperf.numCellsContacted++;
    }
    /*First time a volume in this cell has been referenced */
    if (type == 2)
	ve = (char *)utve;
    else if (type == 1)
	ve = (char *)ntve;
    else
	ve = (char *)tve;
    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, &treq);
	if (tv1) {
	    tv1->refCount--;
	}
    }
    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, &treq);
	if (tv1) {
	    tv1->refCount--;
	}
    }
    osi_FreeLargeSpace(tbuffer);
    afs_PutCell(tcell, READ_LOCK);
    return tv;

}				/*afs_NewVolumeByName */
コード例 #4
0
ファイル: afs_vnop_fid.c プロジェクト: snktagarwal/openafs
afs_fid(OSI_VC_DECL(avc), struct fid **fidpp)
#endif				/* AFS_AIX41_ENV */
{
    struct SmallFid Sfid;
    long addr[2];
    register struct cell *tcell;
    extern struct vcache *afs_globalVp;
    int SizeOfSmallFid = SIZEOF_SMALLFID;
    int rootvp = 0;
    OSI_VC_CONVERT(avc);

    AFS_STATCNT(afs_fid);

    if (afs_shuttingdown)
	return EIO;

    if (afs_NFSRootOnly && (avc == afs_globalVp))
	rootvp = 1;
    if (!afs_NFSRootOnly || rootvp
#ifdef AFS_AIX41_ENV
	|| USE_SMALLFID(credp)
#endif
	) {
	tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
	Sfid.Volume = avc->f.fid.Fid.Volume;
	Sfid.Vnode = avc->f.fid.Fid.Vnode;
	Sfid.CellAndUnique =
	    ((tcell->cellIndex << 24) + (avc->f.fid.Fid.Unique & 0xffffff));
	afs_PutCell(tcell, READ_LOCK);
	if (avc->f.fid.Fid.Vnode > 0xffff)
	    afs_fid_vnodeoverflow++;
	if (avc->f.fid.Fid.Unique > 0xffffff)
	    afs_fid_uniqueoverflow++;
    } else {
#if defined(AFS_SUN57_64BIT_ENV) || (defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64))
	addr[1] = (long)AFS_XLATOR_MAGIC << 48;
#else /* defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64) */
	addr[1] = AFS_XLATOR_MAGIC;
	SizeOfSmallFid = sizeof(addr);
#endif /* defined(AFS_SGI61_ENV) && (_MIPS_SZPTR == 64) */
	addr[0] = (long)avc;
#ifndef AFS_AIX41_ENV
	/* No post processing, so don't hold ref count. */
	AFS_FAST_HOLD(avc);
#endif
    }
#if	defined(AFS_AIX_ENV) || defined(AFS_SUN54_ENV)
    /* Use the fid pointer passed to us. */
    fidpp->fid_len = SizeOfSmallFid;

    if (afs_NFSRootOnly) {
	if (rootvp
#ifdef AFS_AIX41_ENV
	    || USE_SMALLFID(credp)
#endif
	    ) {
	    memcpy(fidpp->fid_data, (caddr_t) & Sfid, SizeOfSmallFid);
	} else {
	    memcpy(fidpp->fid_data, (caddr_t) addr, SizeOfSmallFid);
	}
    } else {
	memcpy(fidpp->fid_data, (caddr_t) & Sfid, SizeOfSmallFid);
    }
#else
    /* malloc a fid pointer ourselves. */
    *fidpp = (struct fid *)AFS_KALLOC(SizeOfSmallFid + 2);
    (*fidpp)->fid_len = SizeOfSmallFid;
    if (afs_NFSRootOnly) {
	if (rootvp) {
	    memcpy((*fidpp)->fid_data, (char *)&Sfid, SizeOfSmallFid);
	} else {
	    memcpy((*fidpp)->fid_data, (char *)addr, SizeOfSmallFid);
	}
    } else {
	memcpy((*fidpp)->fid_data, (char *)&Sfid, SizeOfSmallFid);
    }
#endif
    return (0);
}
コード例 #5
0
ファイル: afs_volume.c プロジェクト: gsell/openafs-osd
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 */
コード例 #6
0
ファイル: afs_analyze.c プロジェクト: maxendpoint/openafs_cvs
/*------------------------------------------------------------------------
 * EXPORTED afs_Analyze
 *
 * Description:
 *	Analyze the outcome of an RPC operation, taking whatever support
 *	actions are necessary.
 *
 * Arguments:
 *	aconn : Ptr to the relevant connection on which the call was made.
 *	acode : The return code experienced by the RPC.
 *	afid  : The FID of the file involved in the action.  This argument
 *		may be null if none was involved.
 *	areq  : The request record associated with this operation.
 *      op    : which RPC we are analyzing.
 *      cellp : pointer to a cell struct.  Must provide either fid or cell.
 *
 * Returns:
 *	Non-zero value if the related RPC operation should be retried,
 *	zero otherwise.
 *
 * Environment:
 *	This routine is typically called in a do-while loop, causing the
 *	embedded RPC operation to be called repeatedly if appropriate
 *	until whatever error condition (if any) is intolerable.
 *
 * Side Effects:
 *	As advertised.
 *
 * NOTE:
 *	The retry return value is used by afs_StoreAllSegments to determine
 *	if this is a temporary or permanent error.
 *------------------------------------------------------------------------*/
int
afs_Analyze(register struct afs_conn *aconn, afs_int32 acode,
	    struct VenusFid *afid, register struct vrequest *areq, int op,
	    afs_int32 locktype, struct cell *cellp)
{
    afs_int32 i;
    struct srvAddr *sa;
    struct server *tsp;
    struct volume *tvp;
    afs_int32 shouldRetry = 0;
    afs_int32 serversleft = 1;
    struct afs_stats_RPCErrors *aerrP;
    afs_int32 markeddown;

 
 
    if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) {
	/* On reconnection, act as connected. XXX: for now.... */
        /* SXW - This may get very tired after a while. We should try and
	 *       intercept all RPCs before they get here ... */
	/*printf("afs_Analyze: disconnected\n");*/
	afs_FinalizeReq(areq);
	if (aconn) {
	    /* SXW - I suspect that this will _never_ happen - we shouldn't
	     *       get a connection because we're disconnected !!!*/
	    afs_PutConn(aconn, locktype);
	}
	return 0;
    }
    
    AFS_STATCNT(afs_Analyze);
    afs_Trace4(afs_iclSetp, CM_TRACE_ANALYZE, ICL_TYPE_INT32, op,
	       ICL_TYPE_POINTER, aconn, ICL_TYPE_INT32, acode, ICL_TYPE_LONG,
	       areq->uid);

    aerrP = (struct afs_stats_RPCErrors *)0;

    if ((op >= 0) && (op < AFS_STATS_NUM_FS_RPC_OPS))
	aerrP = &(afs_stats_cmfullperf.rpc.fsRPCErrors[op]);

    afs_FinalizeReq(areq);
    if (!aconn && areq->busyCount) {	/* one RPC or more got VBUSY/VRESTARTING */

	tvp = afs_FindVolume(afid, READ_LOCK);
	if (tvp) {
	    afs_warnuser("afs: Waiting for busy volume %u (%s) in cell %s\n",
			 (afid ? afid->Fid.Volume : 0),
			 (tvp->name ? tvp->name : ""),
			 ((tvp->serverHost[0]
			   && tvp->serverHost[0]->cell) ? tvp->serverHost[0]->
			  cell->cellName : ""));

	    for (i = 0; i < MAXHOSTS; i++) {
		if (tvp->status[i] != not_busy && tvp->status[i] != offline) {
		    tvp->status[i] = not_busy;
		}
		if (tvp->status[i] == not_busy)
		    shouldRetry = 1;
	    }
	    afs_PutVolume(tvp, READ_LOCK);
	} else {
	    afs_warnuser("afs: Waiting for busy volume %u\n",
			 (afid ? afid->Fid.Volume : 0));
	}

	if (areq->busyCount > 100) {
	    if (aerrP)
		(aerrP->err_Volume)++;
	    areq->volumeError = VOLBUSY;
	    shouldRetry = 0;
	} else {
	    VSleep(afs_BusyWaitPeriod);	/* poll periodically */
	}
	if (shouldRetry != 0)
	    areq->busyCount++;

	return shouldRetry;	/* should retry */
    }

    if (!aconn || !aconn->srvr) {
	if (!areq->volumeError) {
	    if (aerrP)
		(aerrP->err_Network)++;
	    if (hm_retry_int && !(areq->flags & O_NONBLOCK) &&	/* "hard" mount */
		((afid && afs_IsPrimaryCellNum(afid->Cell))
		 || (cellp && afs_IsPrimaryCell(cellp)))) {
		if (!afid) {
		    afs_warnuser
			("afs: hard-mount waiting for a vlserver to return to service\n");
		    VSleep(hm_retry_int);
		    afs_CheckServers(1, cellp);
		    shouldRetry = 1;
		} else {
		    tvp = afs_FindVolume(afid, READ_LOCK);
		    if (!tvp || (tvp->states & VRO)) {
			shouldRetry = hm_retry_RO;
		    } else {
			shouldRetry = hm_retry_RW;
		    }
		    if (tvp)
			afs_PutVolume(tvp, READ_LOCK);
		    if (shouldRetry) {
			afs_warnuser
			    ("afs: hard-mount waiting for volume %u\n",
			     afid->Fid.Volume);
			VSleep(hm_retry_int);
			afs_CheckServers(1, cellp);
		    }
		}
	    } /* if (hm_retry_int ... */
	    else {
		areq->networkError = 1;
	    }
	}
	return shouldRetry;
    }

    /* Find server associated with this connection. */
    sa = aconn->srvr;
    tsp = sa->server;

    /* Before we do anything with acode, make sure we translate it back to
     * a system error */
    if ((acode & ~0xff) == ERROR_TABLE_BASE_uae)
	acode = et_to_sys_error(acode);

    if (acode == 0) {
	/* If we previously took an error, mark this volume not busy */
	if (areq->volumeError) {
	    tvp = afs_FindVolume(afid, READ_LOCK);
	    if (tvp) {
		for (i = 0; i < MAXHOSTS; i++) {
		    if (tvp->serverHost[i] == tsp) {
			tvp->status[i] = not_busy;
		    }
		}
		afs_PutVolume(tvp, READ_LOCK);
	    }
	}

	afs_PutConn(aconn, locktype);
	return 0;
    }

    /* If network troubles, mark server as having bogued out again. */
    /* VRESTARTING is < 0 because of backward compatibility issues 
     * with 3.4 file servers and older cache managers */
#ifdef AFS_64BIT_CLIENT
    if (acode == -455)
	acode = 455;
#endif /* AFS_64BIT_CLIENT */
    if ((acode < 0) && (acode != VRESTARTING)) {
	if (acode == RX_CALL_TIMEOUT) {
	    serversleft = afs_BlackListOnce(areq, afid, tsp);
	    areq->idleError++;
	    if (serversleft) {
		shouldRetry = 1;
	    } else {
		shouldRetry = 0;
	    }
	    /* By doing this, we avoid ever marking a server down
	     * in an idle timeout case. That's because the server is 
	     * still responding and may only be letting a single vnode
	     * time out. We otherwise risk having the server continually
	     * be marked down, then up, then down again... 
	     */
	    goto out;
	} 
	markeddown = afs_ServerDown(sa);
	ForceNewConnections(sa); /**multi homed clients lock:afs_xsrvAddr? */
	if (aerrP)
	    (aerrP->err_Server)++;
#if 0
	/* retry *once* when the server is timed out in case of NAT */
	if (markeddown && acode == RX_CALL_DEAD) {
	    aconn->forceConnectFS = 1;
	    shouldRetry = 1;
	}
#endif
    }

    if (acode == VBUSY || acode == VRESTARTING) {
	if (acode == VBUSY) {
	    areq->busyCount++;
	    if (aerrP)
		(aerrP->err_VolumeBusies)++;
	} else
	    areq->busyCount = 1;

	tvp = afs_FindVolume(afid, READ_LOCK);
	if (tvp) {
	    for (i = 0; i < MAXHOSTS; i++) {
		if (tvp->serverHost[i] == tsp) {
		    tvp->status[i] = rdwr_busy;	/* can't tell which yet */
		    /* to tell which, have to look at the op code. */
		}
	    }
	    afs_PutVolume(tvp, READ_LOCK);
	} else {
	    afs_warnuser("afs: Waiting for busy volume %u in cell %s\n",
			 (afid ? afid->Fid.Volume : 0), tsp->cell->cellName);
	    VSleep(afs_BusyWaitPeriod);	/* poll periodically */
	}
	shouldRetry = 1;
	acode = 0;
    } else if (acode == VICETOKENDEAD
	       || (acode & ~0xff) == ERROR_TABLE_BASE_RXK) {
	/* any rxkad error is treated as token expiration */
	struct unixuser *tu;
	/*
	 * I'm calling these errors protection errors, since they involve
	 * faulty authentication.
	 */
	if (aerrP)
	    (aerrP->err_Protection)++;

	tu = afs_FindUser(areq->uid, tsp->cell->cellNum, READ_LOCK);
	if (tu) {
	    if (acode == VICETOKENDEAD) {
		aconn->forceConnectFS = 1;
	    } else if (acode == RXKADEXPIRED) {
		aconn->forceConnectFS = 0;	/* don't check until new tokens set */
		aconn->user->states |= UTokensBad;
		afs_warnuser
		    ("afs: Tokens for user of AFS id %d for cell %s have expired\n",
		     tu->vid, aconn->srvr->server->cell->cellName);
	    } else {
		serversleft = afs_BlackListOnce(areq, afid, tsp);
		areq->tokenError++;

		if (serversleft) {
		    afs_warnuser
			("afs: Tokens for user of AFS id %d for cell %s: rxkad error=%d\n",
			 tu->vid, aconn->srvr->server->cell->cellName, acode);
		    shouldRetry = 1;
		} else {
		    areq->tokenError = 0;
		    aconn->forceConnectFS = 0;	/* don't check until new tokens set */
		    aconn->user->states |= UTokensBad;
		    afs_warnuser
			("afs: Tokens for user of AFS id %d for cell %s are discarded (rxkad error=%d)\n",
			 tu->vid, aconn->srvr->server->cell->cellName, acode);
		}
	    }
	    afs_PutUser(tu, READ_LOCK);
	} else {
	    /* The else case shouldn't be possible and should probably be replaced by a panic? */
	    if (acode == VICETOKENDEAD) {
		aconn->forceConnectFS = 1;
	    } else if (acode == RXKADEXPIRED) {
		aconn->forceConnectFS = 0;	/* don't check until new tokens set */
		aconn->user->states |= UTokensBad;
		afs_warnuser
		    ("afs: Tokens for user %d for cell %s have expired\n",
		     areq->uid, aconn->srvr->server->cell->cellName);
	    } else {
		aconn->forceConnectFS = 0;	/* don't check until new tokens set */
		aconn->user->states |= UTokensBad;
		afs_warnuser
		    ("afs: Tokens for user %d for cell %s are discarded (rxkad error = %d)\n",
		     areq->uid, aconn->srvr->server->cell->cellName, acode);
	    }
	}
	shouldRetry = 1;	/* Try again (as root). */
    }
    /* Check for access violation. */
    else if (acode == EACCES) {
	/* should mark access error in non-existent per-user global structure */
	if (aerrP)
	    (aerrP->err_Protection)++;
	areq->accessError = 1;
	if (op == AFS_STATS_FS_RPCIDX_STOREDATA)
	    areq->permWriteError = 1;
	shouldRetry = 0;
    }
    /* check for ubik errors; treat them like crashed servers */
    else if (acode >= ERROR_TABLE_BASE_U && acode < ERROR_TABLE_BASE_U + 255) {
	afs_ServerDown(sa);
	if (aerrP)
	    (aerrP->err_Server)++;
	shouldRetry = 1;	/* retryable (maybe one is working) */
	VSleep(1);		/* just in case */
    }
    /* Check for bad volume data base / missing volume. */
    else if (acode == VSALVAGE || acode == VOFFLINE || acode == VNOVOL
	     || acode == VNOSERVICE || acode == VMOVED) {
	struct cell *tcell;
	int same;

	shouldRetry = 1;
	areq->volumeError = VOLMISSING;
	if (aerrP)
	    (aerrP->err_Volume)++;
	if (afid && (tcell = afs_GetCell(afid->Cell, 0))) {
	    same = VLDB_Same(afid, areq);
	    tvp = afs_FindVolume(afid, READ_LOCK);
	    if (tvp) {
		for (i = 0; i < MAXHOSTS && tvp->serverHost[i]; i++) {
		    if (tvp->serverHost[i] == tsp) {
			if (tvp->status[i] == end_not_busy)
			    tvp->status[i] = offline;
			else
			    tvp->status[i]++;
		    } else if (!same) {
			tvp->status[i] = not_busy;	/* reset the others */
		    }
		}
		afs_PutVolume(tvp, READ_LOCK);
	    }
	}
    } else if (acode >= ERROR_TABLE_BASE_VL && acode <= ERROR_TABLE_BASE_VL + 255) {	/* vlserver errors */
	shouldRetry = 0;
	areq->volumeError = VOLMISSING;
    } else if (acode >= 0) {
	if (aerrP)
	    (aerrP->err_Other)++;
	if (op == AFS_STATS_FS_RPCIDX_STOREDATA)
	    areq->permWriteError = 1;
	shouldRetry = 0;	/* Other random Vice error. */
    } else if (acode == RX_MSGSIZE) {	/* same meaning as EMSGSIZE... */
	VSleep(1);		/* Just a hack for desperate times. */
	if (aerrP)
	    (aerrP->err_Other)++;
	shouldRetry = 1;	/* packet was too big, please retry call */
    }

    if (acode < 0 && acode != RX_MSGSIZE && acode != VRESTARTING) {
	/* If we get here, code < 0 and we have network/Server troubles.
	 * areq->networkError is not set here, since we always
	 * retry in case there is another server.  However, if we find
	 * no connection (aconn == 0) we set the networkError flag.
	 */
	afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
	if (aerrP)
	    (aerrP->err_Server)++;
	VSleep(1);		/* Just a hack for desperate times. */
	shouldRetry = 1;
    }
out:
    /* now unlock the connection and return */
    afs_PutConn(aconn, locktype);
    return (shouldRetry);
}				/*afs_Analyze */
コード例 #7
0
ファイル: afs_analyze.c プロジェクト: maxendpoint/openafs_cvs
static int
VLDB_Same(struct VenusFid *afid, struct vrequest *areq)
{
    struct vrequest treq;
    struct afs_conn *tconn;
    int i, type = 0;
    union {
	struct vldbentry tve;
	struct nvldbentry ntve;
	struct uvldbentry utve;
    } *v;
    struct volume *tvp;
    struct cell *tcell;
    char *bp, tbuf[CVBS];	/* biggest volume id is 2^32, ~ 4*10^9 */
    unsigned int changed;
    struct server *(oldhosts[NMAXNSERVERS]);

    AFS_STATCNT(CheckVLDB);
    afs_FinalizeReq(areq);

    if ((i = afs_InitReq(&treq, afs_osi_credp)))
	return DUNNO;
    v = afs_osi_Alloc(sizeof(*v));
    tcell = afs_GetCell(afid->Cell, READ_LOCK);
    bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume);
    do {
	VSleep(2);		/* Better safe than sorry. */
	tconn =
	    afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum,
			     &treq, SHARED_LOCK);
	if (tconn) {
	    if (tconn->srvr->server->flags & SNO_LHOSTS) {
		type = 0;
		RX_AFS_GUNLOCK();
		i = VL_GetEntryByNameO(tconn->id, bp, &v->tve);
		RX_AFS_GLOCK();
	    } else if (tconn->srvr->server->flags & SYES_LHOSTS) {
		type = 1;
		RX_AFS_GUNLOCK();
		i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve);
		RX_AFS_GLOCK();
	    } else {
		type = 2;
		RX_AFS_GUNLOCK();
		i = VL_GetEntryByNameU(tconn->id, bp, &v->utve);
		RX_AFS_GLOCK();
		if (!(tconn->srvr->server->flags & SVLSRV_UUID)) {
		    if (i == RXGEN_OPCODE) {
			type = 1;
			RX_AFS_GUNLOCK();
			i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve);
			RX_AFS_GLOCK();
			if (i == RXGEN_OPCODE) {
			    type = 0;
			    tconn->srvr->server->flags |= SNO_LHOSTS;
			    RX_AFS_GUNLOCK();
			    i = VL_GetEntryByNameO(tconn->id, bp, &v->tve);
			    RX_AFS_GLOCK();
			} else if (!i)
			    tconn->srvr->server->flags |= SYES_LHOSTS;
		    } else if (!i)
			tconn->srvr->server->flags |= SVLSRV_UUID;
		}
		lastcode = i;
	    }
	} else
	    i = -1;
    } while (afs_Analyze(tconn, i, NULL, &treq, -1,	/* no op code for this */
			 SHARED_LOCK, tcell));

    afs_PutCell(tcell, READ_LOCK);
    afs_Trace2(afs_iclSetp, CM_TRACE_CHECKVLDB, ICL_TYPE_FID, &afid,
	       ICL_TYPE_INT32, i);

    if (i) {
	afs_osi_Free(v, sizeof(*v));
	return DUNNO;
    }
    /* have info, copy into serverHost array */
    changed = 0;
    tvp = afs_FindVolume(afid, WRITE_LOCK);
    if (tvp) {
	ObtainWriteLock(&tvp->lock, 107);
	for (i = 0; i < NMAXNSERVERS && tvp->serverHost[i]; i++) {
	    oldhosts[i] = tvp->serverHost[i];
	}

	if (type == 2) {
	    InstallUVolumeEntry(tvp, &v->utve, afid->Cell, tcell, &treq);
	} else if (type == 1) {
	    InstallNVolumeEntry(tvp, &v->ntve, afid->Cell);
	} else {
	    InstallVolumeEntry(tvp, &v->tve, afid->Cell);
	}

	if (i < NMAXNSERVERS && tvp->serverHost[i]) {
	    changed = 1;
	}
	for (--i; !changed && i >= 0; i--) {
	    if (tvp->serverHost[i] != oldhosts[i]) {
		changed = 1;	/* also happens if prefs change.  big deal. */
	    }
	}

	ReleaseWriteLock(&tvp->lock);
	afs_PutVolume(tvp, WRITE_LOCK);
    } else {			/* can't find volume */
	tvp = afs_GetVolume(afid, &treq, WRITE_LOCK);
	if (tvp) {
	    afs_PutVolume(tvp, WRITE_LOCK);
	    afs_osi_Free(v, sizeof(*v));
	    return DIFFERENT;
	} else {
	    afs_osi_Free(v, sizeof(*v));
	    return DUNNO;
	}
    }

    afs_osi_Free(v, sizeof(*v));
    return (changed ? DIFFERENT : SAME);
}				/*VLDB_Same */
コード例 #8
0
ファイル: osi_export.c プロジェクト: gsell/openafs-osd
static struct dentry *afs_export_get_parent(struct dentry *child)
{
    struct VenusFid tfid;
    struct vrequest treq;
    struct cell *tcell;
    struct vcache *vcp;
    struct dentry *dp = NULL;
    cred_t *credp;
    afs_uint32 cellidx;
    int code;

    if (!child->d_inode) {
	/* can't find the parent of a negative dentry */
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_parent(%s): no inode\n",
	       child->d_name.name ? (char *)child->d_name.name : "?");
#endif
	return ERR_PTR(-EIO);
    }

    credp = crref();
    AFS_GLOCK();

    vcp = VTOAFS(child->d_inode);

    if (afs_IsDynrootMount(vcp)) {
	/* the dynmount directory; parent is always the AFS root */
	tfid = afs_globalVp->f.fid;

    } else if (afs_IsDynrootAny(vcp) &&
	       VNUM_TO_VNTYPE(vcp->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
	/* a mount point in the dynmount directory */
	afs_GetDynrootMountFid(&tfid);

    } else if (vcp->mvstat == 2) {
	/* volume root */
	ObtainReadLock(&vcp->lock);
	if (vcp->mvid && vcp->mvid->Fid.Volume) {
	    tfid = *vcp->mvid;
	    ReleaseReadLock(&vcp->lock);
	} else {
	    ReleaseReadLock(&vcp->lock);
	    tcell = afs_GetCell(vcp->f.fid.Cell, READ_LOCK);
	    if (!tcell) {
#ifdef OSI_EXPORT_DEBUG
		printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n",
		       vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
		       vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
#endif
		dp = ERR_PTR(-ENOENT);
		goto done;
	    }

	    cellidx = tcell->cellIndex;
	    afs_PutCell(tcell, READ_LOCK);

	    afs_GetDynrootMountFid(&tfid);
	    tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
	    tfid.Fid.Unique = vcp->f.fid.Fid.Volume;
	}

    } else {
	/* any other vnode */
	if (vType(vcp) == VDIR && !vcp->f.parent.vnode && vcp->mvstat != 1) {
	    code = afs_InitReq(&treq, credp);
	    if (code) {
#ifdef OSI_EXPORT_DEBUG
		printk("afs: get_parent(0x%08x/%d/%d.%d): InitReq: %d\n",
		       vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
		       vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
#endif
		dp = ERR_PTR(-ENOENT);
		goto done;
	    } else {
		code = update_dir_parent(&treq, vcp);
		if (code) {
#ifdef OSI_EXPORT_DEBUG
		    printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n",
			   vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
			   vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
#endif
		    dp = ERR_PTR(-ENOENT);
		    goto done;
		}
	    }
	}

	tfid.Cell       = vcp->f.fid.Cell;
	tfid.Fid.Volume = vcp->f.fid.Fid.Volume;
	tfid.Fid.Vnode  = vcp->f.parent.vnode;
	tfid.Fid.Unique = vcp->f.parent.unique;
    }

#ifdef OSI_EXPORT_DEBUG
    printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n",
	   vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
	   vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique,
	   tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique);
#endif

    dp = get_dentry_from_fid(credp, &tfid);
    if (!dp) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n",
	       vcp->f.fid.Cell, vcp->f.fid.Fid.Volume,
	       vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
#endif
	dp = ERR_PTR(-ENOENT);
    }

done:
    AFS_GUNLOCK();
    crfree(credp);

    return dp;
}
コード例 #9
0
ファイル: osi_export.c プロジェクト: gsell/openafs-osd
static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
			 int connectable)
{
    struct vcache *tvc;
    struct cell *tc;
    int vntype;

    if (!de->d_inode) /* encode a negative dentry?! */
	return 255;
    if (*max_len < 4)  /* not enough space */
	return 255;

    tvc = VTOAFS(de->d_inode);

#ifdef OSI_EXPORT_DEBUG
    printk("afs: encode_fh(0x%08x/%d/%d.%d)\n",
	   tvc->f.fid.Cell,      tvc->f.fid.Fid.Volume,
	   tvc->f.fid.Fid.Vnode, tvc->f.fid.Fid.Unique);
#endif
    if (afs_IsDynrootAnyFid(&tvc->f.fid)) {
	vntype = VNUM_TO_VNTYPE(tvc->f.fid.Fid.Vnode);
	switch (vntype) {
	    case 0:
		/* encode as a normal filehandle */
		break;

	    case VN_TYPE_MOUNT:
		if (*max_len < 5) {
		    return 255;
		}
		/* fall through */

	    case VN_TYPE_CELL:
	    case VN_TYPE_ALIAS:
		AFS_GLOCK();
		tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->f.fid.Fid.Vnode),
					READ_LOCK);
		if (!tc) {
		    AFS_GUNLOCK();
		    return 255;
		}
		memcpy((void *)fh, tc->cellHandle, 16);
		afs_PutCell(tc, READ_LOCK);
		AFS_GUNLOCK();
		if (vntype == VN_TYPE_MOUNT) {
		    fh[4] = htonl(tvc->f.fid.Fid.Unique);
		    *max_len = 5;
		    return AFSFH_DYN_MOUNT;
		}
		*max_len = 4;
		if (vntype == VN_TYPE_CELL) {
		    return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
		} else {
		    return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
		}

	    case VN_TYPE_SYMLINK:
		/* XXX fill in filehandle for dynroot symlink */
		/* XXX return AFSFH_DYN_SYMLINK; */

	    default:
		return 255;
	}
    }

    if (*max_len < 7) {
	/* not big enough for a migratable filehandle */
	/* always encode in network order */
	fh[0] = htonl(tvc->f.fid.Cell);
	fh[1] = htonl(tvc->f.fid.Fid.Volume);
	fh[2] = htonl(tvc->f.fid.Fid.Vnode);
	fh[3] = htonl(tvc->f.fid.Fid.Unique);
	*max_len = 4;
	return AFSFH_NET_VENUSFID;
    }

    AFS_GLOCK();
    tc = afs_GetCell(tvc->f.fid.Cell, READ_LOCK);
    if (!tc) {
	AFS_GUNLOCK();
	return 255;
    }
    memcpy((void *)fh, tc->cellHandle, 16);
    afs_PutCell(tc, READ_LOCK);
    AFS_GUNLOCK();
    /* always encode in network order */
    fh[4] = htonl(tvc->f.fid.Fid.Volume);
    fh[5] = htonl(tvc->f.fid.Fid.Vnode);
    fh[6] = htonl(tvc->f.fid.Fid.Unique);

    *max_len = 7;
    return AFSFH_NET_CELLFID;
}
コード例 #10
0
ファイル: afs_vnop_attrs.c プロジェクト: bagdxk/openafs
/* copy out attributes from cache entry */
int
afs_CopyOutAttrs(struct vcache *avc, struct vattr *attrs)
{
    struct volume *tvp;
    struct cell *tcell;
#if defined(AFS_FBSD_ENV) || defined(AFS_DFBSD_ENV)
    struct vnode *vp = AFSTOV(avc);
#endif
    int fakedir = 0;

    AFS_STATCNT(afs_CopyOutAttrs);
    if (afs_fakestat_enable && avc->mvstat == AFS_MVSTAT_MTPT)
	fakedir = 1;
    attrs->va_type = fakedir ? VDIR : vType(avc);
#if defined(AFS_SGI_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV)
    attrs->va_mode = fakedir ? S_IFDIR | 0755 : (mode_t) (avc->f.m.Mode & 0xffff);
#else
    attrs->va_mode = fakedir ? VDIR | 0755 : avc->f.m.Mode;
#endif

    if (avc->f.m.Mode & (VSUID | VSGID)) {
	/* setuid or setgid, make sure we're allowed to run them from this cell */
	tcell = afs_GetCell(avc->f.fid.Cell, 0);
	if (tcell && (tcell->states & CNoSUID))
	    attrs->va_mode &= ~(VSUID | VSGID);
    }
#if defined(AFS_DARWIN_ENV)
    {
	if (!afs_darwin_realmodes) {
	    /* Mac OS X uses the mode bits to determine whether a file or
	     * directory is accessible, and believes them, even though under
	     * AFS they're almost assuredly wrong, especially if the local uid
	     * does not match the AFS ID.  So we set the mode bits
	     * conservatively.
	     */
	    if (S_ISDIR(attrs->va_mode)) {
		/* all access bits need to be set for directories, since even
		 * a mode 0 directory can still be used normally.
		 */
		attrs->va_mode |= ACCESSPERMS;
	    } else {
		/* for other files, replicate the user bits to group and other */
		mode_t ubits = (attrs->va_mode & S_IRWXU) >> 6;
		attrs->va_mode |= ubits | (ubits << 3);
	    }
	}
    }
#endif /* AFS_DARWIN_ENV */
    attrs->va_uid = fakedir ? 0 : avc->f.m.Owner;
    attrs->va_gid = fakedir ? 0 : avc->f.m.Group;	/* yeah! */
#if defined(AFS_SUN5_ENV)
    attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0];
#elif defined(AFS_DARWIN80_ENV)
    VATTR_RETURN(attrs, va_fsid, vfs_statfs(vnode_mount(AFSTOV(avc)))->f_fsid.val[0]);
#elif defined(AFS_DARWIN_ENV)
    attrs->va_fsid = avc->v->v_mount->mnt_stat.f_fsid.val[0];
#else /* ! AFS_DARWIN_ENV */
    attrs->va_fsid = 1;
#endif 
    if (avc->mvstat == AFS_MVSTAT_ROOT) {
	tvp = afs_GetVolume(&avc->f.fid, 0, READ_LOCK);
	/* The mount point's vnode. */
	if (tvp) {
	    attrs->va_nodeid =
	      afs_calc_inum(tvp->mtpoint.Cell,
			    tvp->mtpoint.Fid.Volume,
			    tvp->mtpoint.Fid.Vnode);
	    if (FidCmp(&afs_rootFid, &avc->f.fid) && !attrs->va_nodeid)
		attrs->va_nodeid = 2;
	    afs_PutVolume(tvp, READ_LOCK);
	} else
	    attrs->va_nodeid = 2;
    } else
	attrs->va_nodeid = 
	      afs_calc_inum(avc->f.fid.Cell,
			    avc->f.fid.Fid.Volume,
			    avc->f.fid.Fid.Vnode);
    attrs->va_nodeid &= 0x7fffffff;	/* Saber C hates negative inode #s! */
    attrs->va_nlink = fakedir ? 100 : avc->f.m.LinkCount;
    attrs->va_size = fakedir ? 4096 : avc->f.m.Length;
#if defined(AFS_FBSD_ENV) || defined(AFS_DFBSD_ENV)
        vnode_pager_setsize(vp, (u_long) attrs->va_size);
#endif
    attrs->va_atime.tv_sec = attrs->va_mtime.tv_sec = attrs->va_ctime.tv_sec =
	fakedir ? 0 : (int)avc->f.m.Date;
    /* set microseconds to be dataversion # so that we approximate NFS-style
     * use of mtime as a dataversion #.  We take it mod 512K because
     * microseconds *must* be less than a million, and 512K is the biggest
     * power of 2 less than such.  DataVersions are typically pretty small
     * anyway, so the difference between 512K and 1000000 shouldn't matter
     * much, and "&" is a lot faster than "%".
     */
#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
    /* nfs on these systems puts an 0 in nsec and stores the nfs usec (aka 
     * dataversion) in va_gen */

    attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
	attrs->va_ctime.tv_nsec = 0;
    attrs->va_gen = hgetlo(avc->f.m.DataVersion);
#elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_OBSD_ENV) || defined(AFS_NBSD_ENV)
    attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
	attrs->va_ctime.tv_nsec =
	(hgetlo(avc->f.m.DataVersion) & 0x7ffff) * 1000;
#else
    attrs->va_atime.tv_usec = attrs->va_mtime.tv_usec =
	attrs->va_ctime.tv_usec = (hgetlo(avc->f.m.DataVersion) & 0x7ffff);
#endif
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
    attrs->va_flags = 0;
#endif
#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
    attrs->va_blksize = AFS_BLKSIZE;	/* XXX Was 8192 XXX */
#else
    attrs->va_blocksize = AFS_BLKSIZE;	/* XXX Was 8192 XXX */
#endif
    attrs->va_rdev = 1;
#if defined(AFS_HPUX110_ENV)
    if (afs_globalVFS)
	attrs->va_fstype = afs_globalVFS->vfs_mtype;
#endif

    /*
     * Below return 0 (and not 1) blocks if the file is zero length. This conforms
     * better with the other filesystems that do return 0.      
     */
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
    attrs->va_bytes = (attrs->va_size ? (attrs->va_size + 1023) : 1024);
#ifdef	va_bytes_rsv
    attrs->va_bytes_rsv = -1;
#endif
#elif defined(AFS_HPUX_ENV)
    attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10) : 0);
#elif defined(AFS_SGI_ENV)
    attrs->va_blocks = BTOBB(attrs->va_size);
#elif defined(AFS_SUN5_ENV)
    attrs->va_nblocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
#else /* everything else */
    attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
#endif
    return 0;
}
コード例 #11
0
ファイル: afs_volume.c プロジェクト: maxendpoint/openafs_cvs
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 */
コード例 #12
0
ファイル: afs_volume.c プロジェクト: maxendpoint/openafs_cvs
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 */