Esempio n. 1
0
static void
cm_MarkServerDown(cm_server_t *tsp, afs_int32 code, int wasDown)
{

    /* mark server as down */
    if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
	_InterlockedOr(&tsp->flags, CM_SERVERFLAG_DOWN);
	tsp->downTime = time(NULL);
    }
    if (code != VRESTARTING) {
	lock_ReleaseMutex(&tsp->mx);
	cm_ForceNewConnections(tsp);
	lock_ObtainMutex(&tsp->mx);
    }
    /* Now update the volume status if necessary */
    if (!wasDown) {
	if (tsp->type == CM_SERVER_FILE) {
	    cm_server_vols_t * tsrvp;
	    cm_volume_t * volp;
	    int i;
	    cm_req_t req;

	    for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
		for (i=0; i<NUM_SERVER_VOLS; i++) {
		    if (tsrvp->ids[i] != 0) {
			cm_InitReq(&req);

			lock_ReleaseMutex(&tsp->mx);
			code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i],
						 cm_rootUserp, &req,
						 CM_GETVOL_FLAG_NO_LRU_UPDATE,
						 &volp);
			lock_ObtainMutex(&tsp->mx);
			if (code == 0) {
			    cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
			    cm_PutVolume(volp);
			}
		    }
		}
	    }
	}
	cm_RankServer(tsp);
    }
}
Esempio n. 2
0
/* periodic check daemon */
void * cm_Daemon(void *vparm)
{
    time_t now;
    time_t lastVolCheck;
    time_t lastCBExpirationCheck;
    time_t lastVolCBRenewalCheck;
    time_t lastDownServerCheck;
    time_t lastUpServerCheck;
    time_t lastTokenCacheCheck;
    time_t lastBusyVolCheck;
    time_t lastPerformanceCheck;
    time_t lastServerRankCheck;
    time_t lastRDRShakeExtents;
    time_t lastAfsdHookReload;
    time_t lastEAccesCheck;
    char thostName[200];
    unsigned long code;
    struct hostent *thp;
    HMODULE hHookDll = NULL;
    AfsdDaemonHook daemonHook = NULL;
    char * name = "cm_Daemon_ShutdownEvent";
    int configureFirewall = IsWindowsFirewallPresent();
    int bAddrChangeCheck = 0;

    cm_Daemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
    if ( GetLastError() == ERROR_ALREADY_EXISTS )
        afsi_log("Event Object Already Exists: %s", name);

    if (!configureFirewall) {
	afsi_log("No Windows Firewall detected");
    }

    if (cm_freelanceEnabled && cm_freelanceImportCellServDB)
        cm_FreelanceImportCellServDB();

    /* ping all file servers, up or down, with unauthenticated connection,
     * to find out whether we have all our callbacks from the server still.
     * Also, ping down VLDBs.
     */
    /*
     * Seed the random number generator with our own address, so that
     * clients starting at the same time don't all do vol checks at the
     * same time.
     */
    gethostname(thostName, sizeof(thostName));
    thp = gethostbyname(thostName);
    if (thp == NULL)    /* In djgpp, gethostname returns the netbios
                           name of the machine.  gethostbyname will fail
                           looking this up if it differs from DNS name. */
        code = 0;
    else
        memcpy(&code, thp->h_addr_list[0], 4);

    srand(ntohl(code));

    cm_DaemonCheckInit();

    now = osi_Time();
    lastVolCheck = now - cm_daemonCheckVolInterval/2 + (rand() % cm_daemonCheckVolInterval);
    lastCBExpirationCheck = now - cm_daemonCheckCBInterval/2 + (rand() % cm_daemonCheckCBInterval);
    if (cm_daemonCheckVolCBInterval)
        lastVolCBRenewalCheck = now - cm_daemonCheckVolCBInterval/2 + (rand() % cm_daemonCheckVolCBInterval);
    lastDownServerCheck = now - cm_daemonCheckDownInterval/2 + (rand() % cm_daemonCheckDownInterval);
    lastUpServerCheck = now - cm_daemonCheckUpInterval/2 + (rand() % cm_daemonCheckUpInterval);
    lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval);
    if (cm_daemonCheckOfflineVolInterval)
        lastBusyVolCheck = now - cm_daemonCheckOfflineVolInterval/2 * (rand() % cm_daemonCheckOfflineVolInterval);
    if (cm_daemonPerformanceTuningInterval)
        lastPerformanceCheck = now - cm_daemonPerformanceTuningInterval/2 * (rand() % cm_daemonPerformanceTuningInterval);
    lastServerRankCheck = now - cm_daemonRankServerInterval/2 * (rand() % cm_daemonRankServerInterval);
    if (cm_daemonRDRShakeExtentsInterval)
        lastRDRShakeExtents = now - cm_daemonRDRShakeExtentsInterval/2 * (rand() % cm_daemonRDRShakeExtentsInterval);
    if (cm_daemonAfsdHookReloadInterval)
        lastAfsdHookReload = now;
    lastEAccesCheck = now;

    hHookDll = cm_LoadAfsdHookLib();
    if (hHookDll)
        daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);

    while (daemon_ShutdownFlag == 0) {
        if (powerStateSuspended) {
            Sleep(1000);
            continue;
        }
	/* check to see if the listener threads halted due to network
	 * disconnect or other issues.  If so, attempt to restart them.
	 */
	smb_RestartListeners(0);

        if (daemon_ShutdownFlag == 1)
            break;

        if (configureFirewall) {
	    /* Open Microsoft Firewall to allow in port 7001 */
	    switch (icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT)) {
	    case 0:
		afsi_log("Windows Firewall Configuration succeeded");
		configureFirewall = 0;
		break;
	    case 1:
		afsi_log("Invalid Windows Firewall Port Set");
		break;
	    case 2:
		afsi_log("Unable to open Windows Firewall Profile");
		break;
	    case 3:
		afsi_log("Unable to create/modify Windows Firewall Port entries");
		break;
	    default:
		afsi_log("Unknown Windows Firewall Configuration error");
	    }
	}

        /* find out what time it is */
        now = osi_Time();

        /* Determine whether an address change took place that we need to respond to */
        if (bAddrChangeCheck)
            bAddrChangeCheck = 0;

        if (lastIPAddrChange != 0 && lastIPAddrChange + 2500 < now) {
            bAddrChangeCheck = 1;
            lastIPAddrChange = 0;
        }

        /* check down servers */
        if ((bAddrChangeCheck || now > lastDownServerCheck + cm_daemonCheckDownInterval) &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            lastDownServerCheck = now;
	    osi_Log0(afsd_logp, "cm_Daemon CheckDownServers");
            cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
            if (daemon_ShutdownFlag == 1)
                break;
	    now = osi_Time();
        }

        if (bAddrChangeCheck &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            cm_ForceNewConnectionsAllServers();
        }

        /* check up servers */
        if ((bAddrChangeCheck || now > lastUpServerCheck + cm_daemonCheckUpInterval) &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            lastUpServerCheck = now;
	    osi_Log0(afsd_logp, "cm_Daemon CheckUpServers");
            cm_CheckServers(CM_FLAG_CHECKUPSERVERS, NULL);
            if (daemon_ShutdownFlag == 1)
                break;
	    now = osi_Time();
        }

        if (bAddrChangeCheck &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            smb_CheckVCs();
            cm_VolStatus_Network_Addr_Change();
        }

        /*
         * Once every five minutes inspect the volume list and enforce
         * the volume location expiration time.
         */
        if (now > lastVolCheck + 300 &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            lastVolCheck = now;
            cm_RefreshVolumes(cm_daemonCheckVolInterval);
            if (daemon_ShutdownFlag == 1)
                break;
	    now = osi_Time();
        }

	/* Rank all up servers */
	if ((now > lastServerRankCheck + cm_daemonRankServerInterval) &&
	    daemon_ShutdownFlag == 0 &&
	    powerStateSuspended == 0) {
	    lastServerRankCheck = now;
	    osi_Log0(afsd_logp, "cm_Daemon RankServer");
	    cm_RankUpServers();
	    if(daemon_ShutdownFlag == 1)
		break;
	    now = osi_Time();
	}

        if (cm_daemonCheckVolCBInterval &&
            now > lastVolCBRenewalCheck + cm_daemonCheckVolCBInterval &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            lastVolCBRenewalCheck = now;
            cm_VolumeRenewROCallbacks();
            if (daemon_ShutdownFlag == 1)
                break;
            now = osi_Time();
        }

        if ((bAddrChangeCheck || (cm_daemonCheckOfflineVolInterval &&
                                  now > lastBusyVolCheck + cm_daemonCheckOfflineVolInterval)) &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            lastBusyVolCheck = now;
            cm_CheckOfflineVolumes();
            if (daemon_ShutdownFlag == 1)
                break;
	    now = osi_Time();
        }

        if (now > lastCBExpirationCheck + cm_daemonCheckCBInterval &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            lastCBExpirationCheck = now;
            cm_CheckCBExpiration();
            if (daemon_ShutdownFlag == 1)
                break;
	    now = osi_Time();
        }

        if (now > lastTokenCacheCheck + cm_daemonTokenCheckInterval &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            lastTokenCacheCheck = now;
            cm_CheckTokenCache(now);
            if (daemon_ShutdownFlag == 1)
                break;
	    now = osi_Time();
        }

        if (now > lastEAccesCheck + cm_daemonEAccesCheckInterval &&
             daemon_ShutdownFlag == 0 &&
             powerStateSuspended == 0) {
            lastEAccesCheck = now;
            cm_EAccesClearOutdatedEntries();
            if (daemon_ShutdownFlag == 1)
                break;
	    now = osi_Time();
        }

        if (cm_daemonRDRShakeExtentsInterval &&
            now > lastRDRShakeExtents + cm_daemonRDRShakeExtentsInterval &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            cm_req_t req;
            cm_InitReq(&req);
            lastRDRShakeExtents = now;
            if (cm_data.buf_redirCount > cm_data.buf_freeCount)
                buf_RDRShakeSomeExtentsFree(&req, FALSE, 10 /* seconds */);
            if (daemon_ShutdownFlag == 1)
                break;
	    now = osi_Time();
        }

        /* allow an exit to be called prior to stopping the service */
        if (cm_daemonAfsdHookReloadInterval &&
            lastAfsdHookReload != 0 && lastAfsdHookReload < now) {
            if (hHookDll) {
                FreeLibrary(hHookDll);
                hHookDll = NULL;
                daemonHook = NULL;
            }

            hHookDll = cm_LoadAfsdHookLib();
            if (hHookDll)
                daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
        }

        if (daemonHook)
        {
            BOOL hookRc = daemonHook();

            if (hookRc == FALSE)
            {
                SetEvent(WaitToTerminate);
            }

            if (daemon_ShutdownFlag == 1) {
                break;
            }
	    now = osi_Time();
        }

        if (cm_daemonPerformanceTuningInterval &&
            now > lastPerformanceCheck + cm_daemonPerformanceTuningInterval &&
            daemon_ShutdownFlag == 0 &&
            powerStateSuspended == 0) {
            lastPerformanceCheck = now;
            cm_PerformanceTuningCheck();
            if (daemon_ShutdownFlag == 1)
                break;
	    now = osi_Time();
        }

        /*
         * sleep .5 seconds.  if the thread blocks for a long time
         * we risk not being able to close the cache before Windows
         * kills our process during system shutdown.
         */
        thrd_Sleep(500);
    }

    if (hHookDll) {
        FreeLibrary(hHookDll);
    }

    thrd_SetEvent(cm_Daemon_ShutdownEvent);
    pthread_exit(NULL);
    return NULL;
}
Esempio n. 3
0
long ReadData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op,
              cm_user_t *userp, long *readp)
{
    //osi_hyper_t offset;
    long code;
    cm_buf_t *bufferp;
    osi_hyper_t fileLength;
    osi_hyper_t thyper;
    osi_hyper_t lastByte;
    osi_hyper_t bufferOffset;
    long bufIndex, nbytes;
    int sequential = 0;
    cm_req_t req;

    cm_InitReq(&req);

    bufferp = NULL;

    lock_ObtainWrite(&scp->rw);

    /* start by looking up the file's end */
    code = cm_SyncOp(scp, NULL, userp, &req, 0,
                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
    if (code)
        goto done;

    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);

    /* now we have the entry locked, look up the length */
    fileLength = scp->length;

    /* adjust count down so that it won't go past EOF */
    thyper.LowPart = count;
    thyper.HighPart = 0;
    thyper = LargeIntegerAdd(offset, thyper);	/* where read should end */
    lastByte = thyper;
    if (LargeIntegerGreaterThan(thyper, fileLength)) {
        /* we'd read past EOF, so just stop at fileLength bytes.
        * Start by computing how many bytes remain in the file.
        */
        thyper = LargeIntegerSubtract(fileLength, offset);

        /* if we are past EOF, read 0 bytes */
        if (LargeIntegerLessThanZero(thyper))
            count = 0;
        else
            count = thyper.LowPart;
    }

    *readp = count;

    /* now, copy the data one buffer at a time,
     * until we've filled the request packet
     */
    while (1) {
        /* if we've copied all the data requested, we're done */
        if (count <= 0) break;

        /* otherwise, load up a buffer of data */
        thyper.HighPart = offset.HighPart;
        thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
        if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
            /* wrong buffer */
            if (bufferp) {
                buf_Release(bufferp);
                bufferp = NULL;
            }
            lock_ReleaseWrite(&scp->rw);

            code = buf_Get(scp, &thyper, &bufferp);

            lock_ObtainWrite(&scp->rw);
            if (code) goto done;
            bufferOffset = thyper;

            /* now get the data in the cache */
            while (1) {
                code = cm_SyncOp(scp, bufferp, userp, &req, 0,
                                 CM_SCACHESYNC_NEEDCALLBACK
                                 | CM_SCACHESYNC_READ);
                if (code)
                    goto done;

                cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);

                if (cm_HaveBuffer(scp, bufferp, 0)) break;

                /* otherwise, load the buffer and try again */
                code = cm_GetBuffer(scp, bufferp, NULL, userp, &req);
                if (code) break;
            }
            if (code) {
                buf_Release(bufferp);
                bufferp = NULL;
                goto done;
            }
        }	/* if (wrong buffer) ... */

        /* now we have the right buffer loaded.  Copy out the
         * data from here to the user's buffer.
         */
        bufIndex = offset.LowPart & (buf_bufferSize - 1);

        /* and figure out how many bytes we want from this buffer */
        nbytes = buf_bufferSize - bufIndex;	/* what remains in buffer */
        if (nbytes > count) nbytes = count;	/* don't go past EOF */

        /* now copy the data */
        memcpy(op, bufferp->datap + bufIndex, nbytes);

        /* adjust counters, pointers, etc. */
        op += nbytes;
        count -= nbytes;
        thyper.LowPart = nbytes;
        thyper.HighPart = 0;
        offset = LargeIntegerAdd(thyper, offset);
    } /* while 1 */

done:
    lock_ReleaseWrite(&scp->rw);
    //lock_ReleaseMutex(&fidp->mx);
    if (bufferp)
        buf_Release(bufferp);

    if (code == 0 && sequential)
        cm_ConsiderPrefetch(scp, &lastByte, *readp, userp, &req);

    return code;
}
Esempio n. 4
0
long WriteData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op,
               cm_user_t *userp, long *writtenp)
{
    long code = 0;
    long written = 0;
    osi_hyper_t fileLength;	/* file's length at start of write */
    osi_hyper_t minLength;	/* don't read past this */
    afs_uint32 nbytes;		/* # of bytes to transfer this iteration */
    cm_buf_t *bufferp;
    osi_hyper_t thyper;		/* hyper tmp variable */
    osi_hyper_t bufferOffset;
    afs_uint32 bufIndex;	/* index in buffer where our data is */
    int doWriteBack;
    osi_hyper_t writeBackOffset;/* offset of region to write back when
    * I/O is done */
    DWORD filter = 0;
    cm_req_t req;

    cm_InitReq(&req);

    bufferp = NULL;
    doWriteBack = 0;

    lock_ObtainWrite(&scp->rw);

    /* start by looking up the file's end */
    code = cm_SyncOp(scp, NULL, userp, &req, 0,
                     CM_SCACHESYNC_NEEDCALLBACK
                     | CM_SCACHESYNC_SETSTATUS
                     | CM_SCACHESYNC_GETSTATUS);
    if (code)
        goto done;

    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS);

#if 0
    /* make sure we have a writable FD */
    if (!(fidp->flags & SMB_FID_OPENWRITE)) {
        code = CM_ERROR_BADFDOP;
        goto done;
    }
#endif

    /* now we have the entry locked, look up the length */
    fileLength = scp->length;
    minLength = fileLength;
    if (LargeIntegerGreaterThan(minLength, scp->serverLength))
        minLength = scp->serverLength;

    /* adjust file length if we extend past EOF */
    thyper.LowPart = count;
    thyper.HighPart = 0;
    thyper = LargeIntegerAdd(offset, thyper);	/* where write should end */
    if (LargeIntegerGreaterThan(thyper, fileLength)) {
        /* we'd write past EOF, so extend the file */
        scp->mask |= CM_SCACHEMASK_LENGTH;
        scp->length = thyper;
        filter |= (FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE);
    } else
        filter |= FILE_NOTIFY_CHANGE_LAST_WRITE;

    /* now, if the new position (thyper) and the old (offset) are in
     * different storeback windows, remember to store back the previous
     * storeback window when we're done with the write.
     */
    if ((thyper.LowPart & (-cm_chunkSize)) !=
            (offset.LowPart & (-cm_chunkSize))) {
        /* they're different */
        doWriteBack = 1;
        writeBackOffset.HighPart = offset.HighPart;
        writeBackOffset.LowPart = offset.LowPart & (-cm_chunkSize);
    }

    *writtenp = count;

    /* now, copy the data one buffer at a time, until we've filled the
     * request packet */
    while (1) {
        /* if we've copied all the data requested, we're done */
        if (count <= 0) break;

        /* handle over quota or out of space */
        if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) {
            *writtenp = written;
            break;
        }

        /* otherwise, load up a buffer of data */
        thyper.HighPart = offset.HighPart;
        thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
        if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
            /* wrong buffer */
            if (bufferp) {
                lock_ReleaseMutex(&bufferp->mx);
                buf_Release(bufferp);
                bufferp = NULL;
            }
            lock_ReleaseWrite(&scp->rw);

            code = buf_Get(scp, &thyper, &bufferp);

            lock_ObtainMutex(&bufferp->mx);
            lock_ObtainWrite(&scp->rw);
            if (code)
                goto done;

            bufferOffset = thyper;

            /* now get the data in the cache */
            while (1) {
                code = cm_SyncOp(scp, bufferp, userp, &req, 0,
                                 CM_SCACHESYNC_NEEDCALLBACK
                                 | CM_SCACHESYNC_WRITE
                                 | CM_SCACHESYNC_BUFLOCKED);
                if (code)
                    goto done;

                cm_SyncOpDone(scp, bufferp,
                              CM_SCACHESYNC_NEEDCALLBACK
                              | CM_SCACHESYNC_WRITE
                              | CM_SCACHESYNC_BUFLOCKED);

                /* If we're overwriting the entire buffer, or
                 * if we're writing at or past EOF, mark the
                 * buffer as current so we don't call
                 * cm_GetBuffer.  This skips the fetch from the
                 * server in those cases where we're going to
                 * obliterate all the data in the buffer anyway,
                 * or in those cases where there is no useful
                 * data at the server to start with.
                 *
                 * Use minLength instead of scp->length, since
                 * the latter has already been updated by this
                 * call.
                 */
                if (LargeIntegerGreaterThanOrEqualTo(bufferp->offset, minLength) ||
                        LargeIntegerEqualTo(offset, bufferp->offset) &&
                        (count >= buf_bufferSize ||
                         LargeIntegerGreaterThanOrEqualTo(LargeIntegerAdd(offset, ConvertLongToLargeInteger(count)), minLength))) {
                    if (count < buf_bufferSize
                            && bufferp->dataVersion == -1)
                        memset(bufferp->datap, 0,
                               buf_bufferSize);
                    bufferp->dataVersion = scp->dataVersion;
                }

                if (cm_HaveBuffer(scp, bufferp, 1)) break;

                /* otherwise, load the buffer and try again */
                lock_ReleaseMutex(&bufferp->mx);
                code = cm_GetBuffer(scp, bufferp, NULL, userp,
                                    &req);
                lock_ReleaseWrite(&scp->rw);
                lock_ObtainMutex(&bufferp->mx);
                lock_ObtainWrite(&scp->rw);
                if (code)
                    break;
            }
            if (code) {
                lock_ReleaseMutex(&bufferp->mx);
                buf_Release(bufferp);
                bufferp = NULL;
                goto done;
            }
        }	/* if (wrong buffer) ... */

        /* now we have the right buffer loaded.  Copy out the
         * data from here to the user's buffer.
         */
        bufIndex = offset.LowPart & (buf_bufferSize - 1);

        /* and figure out how many bytes we want from this buffer */
        nbytes = buf_bufferSize - bufIndex;	/* what remains in buffer */
        if (nbytes > count)
            nbytes = count;	/* don't go past end of request */

        /* now copy the data */
        memcpy(bufferp->datap + bufIndex, op, nbytes);
        buf_SetDirty(bufferp, bufIndex, nbytes, userp);

        /* adjust counters, pointers, etc. */
        op += nbytes;
        count -= nbytes;
        written += nbytes;
        thyper.LowPart = nbytes;
        thyper.HighPart = 0;
        offset = LargeIntegerAdd(thyper, offset);
    } /* while 1 */

done:
    lock_ReleaseWrite(&scp->rw);
    if (bufferp) {
        lock_ReleaseMutex(&bufferp->mx);
        buf_Release(bufferp);
    }

    if (code == 0 && doWriteBack) {
        lock_ObtainWrite(&scp->rw);
        code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
        lock_ReleaseWrite(&scp->rw);
        if (code == 0)
            cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
                               writeBackOffset.HighPart, cm_chunkSize, 0, userp);
    }

    /* cm_SyncOpDone is called when cm_BkgStore completes */
    return code;
}
Esempio n. 5
0
static void cm_CheckServersMulti(afs_uint32 flags, cm_cell_t *cellp)
{
    /*
     * The goal of this function is to probe simultaneously
     * probe all of the up/down servers (vldb/file) as
     * specified by flags in the minimum number of RPCs.
     * Effectively that means use one multi_RXAFS_GetCapabilities()
     * followed by possibly one multi_RXAFS_GetTime() and
     * one multi_VL_ProbeServer().
     *
     * To make this work we must construct the list of vldb
     * and file servers that are to be probed as well as the
     * associated data structures.
     */

    int srvAddrCount = 0;
    struct srvAddr **addrs = NULL;
    cm_conn_t **conns = NULL;
    struct rx_connection **rxconns = NULL;
    cm_req_t req;
    afs_int32 i, nconns = 0, maxconns;
    afs_int32 *conntimer, *results;
    Capabilities *caps = NULL;
    cm_server_t ** serversp, *tsp;
    afs_uint32 isDown, wasDown;
    afs_uint32 code;
    time_t start;
    char hoststr[16];

    cm_InitReq(&req);
    maxconns = max(cm_numFileServers,cm_numVldbServers);
    if (maxconns == 0)
        return;

    conns = (cm_conn_t **)malloc(maxconns * sizeof(cm_conn_t *));
    rxconns = (struct rx_connection **)malloc(maxconns * sizeof(struct rx_connection *));
    conntimer = (afs_int32 *)malloc(maxconns * sizeof (afs_int32));
    results = (afs_int32 *)malloc(maxconns * sizeof (afs_int32));
    serversp = (cm_server_t **)malloc(maxconns * sizeof(cm_server_t *));
    caps = (Capabilities *)malloc(maxconns * sizeof(Capabilities));

    memset(caps, 0, maxconns * sizeof(Capabilities));

    if ((flags & CM_FLAG_CHECKFILESERVERS) ||
        !(flags & (CM_FLAG_CHECKFILESERVERS|CM_FLAG_CHECKVLDBSERVERS)))
    {
        lock_ObtainRead(&cm_serverLock);
	for (nconns=0, tsp = cm_serversAllFirstp;
	      tsp != NULL && nconns < maxconns;
	      tsp = (cm_server_t *)osi_QNext(&tsp->allq)) {
            if (tsp->type != CM_SERVER_FILE ||
                tsp->cellp == NULL ||           /* SetPref only */
                cellp && cellp != tsp->cellp)
                continue;

            cm_GetServerNoLock(tsp);
            lock_ReleaseRead(&cm_serverLock);

            lock_ObtainMutex(&tsp->mx);
            isDown = tsp->flags & CM_SERVERFLAG_DOWN;

	    if (tsp->pingCount > 0 ||
                !((isDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) ||
                   (!isDown && (flags & CM_FLAG_CHECKUPSERVERS)))) {
                lock_ReleaseMutex(&tsp->mx);
                lock_ObtainRead(&cm_serverLock);
                cm_PutServerNoLock(tsp);
                continue;
            }

	    InterlockedIncrement(&tsp->pingCount);
            lock_ReleaseMutex(&tsp->mx);

	    if (cm_noIPAddr > 0)
		code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &conns[nconns]);
	    else
		code = RX_CALL_DEAD;
            if (code) {
		lock_ObtainMutex(&tsp->mx);
		if (code == RX_CALL_DEAD)
		    cm_MarkServerDown(tsp, code, isDown);
		InterlockedDecrement(&tsp->pingCount);
		lock_ReleaseMutex(&tsp->mx);

		lock_ObtainRead(&cm_serverLock);
		cm_PutServerNoLock(tsp);
                continue;
            }
            lock_ObtainRead(&cm_serverLock);
            rxconns[nconns] = cm_GetRxConn(conns[nconns]);
            if (conntimer[nconns] = (isDown ? 1 : 0))
                rx_SetConnHardDeadTime(rxconns[nconns], 10);
	    serversp[nconns] = tsp;
            nconns++;
        }
        lock_ReleaseRead(&cm_serverLock);

        if (nconns) {
            /* Perform the multi call */
            start = time(NULL);
            multi_Rx(rxconns,nconns)
            {
                multi_RXAFS_GetCapabilities(&caps[multi_i]);
                results[multi_i]=multi_error;
            } multi_End;
        }
Esempio n. 6
0
void
cm_PingServer(cm_server_t *tsp)
{
    long code;
    int wasDown = 0;
    cm_conn_t *connp;
    struct rx_connection * rxconnp;
    Capabilities caps = {0, 0};
    char hoststr[16];
    cm_req_t req;

    lock_ObtainMutex(&tsp->mx);
    if (InterlockedIncrement(&tsp->pingCount) > 1) {
	tsp->waitCount++;
	osi_SleepM((LONG_PTR)tsp, &tsp->mx);
	lock_ObtainMutex(&tsp->mx);
	InterlockedDecrement(&tsp->pingCount);
	if (--tsp->waitCount > 0)
	    osi_Wakeup((LONG_PTR)tsp);
	lock_ReleaseMutex(&tsp->mx);
	return;
    }
    wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
    afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
    lock_ReleaseMutex(&tsp->mx);

    if (cm_noIPAddr > 0)
	code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &connp);
    else
	code = RX_CALL_DEAD;	/* No network */
    if (code == 0) {
	/* now call the appropriate ping call.  Drop the timeout if
	* the server is known to be down, so that we don't waste a
	* lot of time retiming out down servers.
	*/

	osi_Log4(afsd_logp, "cm_PingServer server %s (%s) was %s with caps 0x%x",
		  osi_LogSaveString(afsd_logp, hoststr),
		  tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
		  wasDown ? "down" : "up",
		  tsp->capabilities);

        rxconnp = cm_GetRxConn(connp);
	if (wasDown)
	    rx_SetConnHardDeadTime(rxconnp, 10);
	if (tsp->type == CM_SERVER_VLDB) {
	    code = VL_ProbeServer(rxconnp);
	}
	else {
	    /* file server */
	    code = RXAFS_GetCapabilities(rxconnp, &caps);
	}
	if (wasDown)
	    rx_SetConnHardDeadTime(rxconnp, HardDeadtimeout);
        rx_PutConnection(rxconnp);
	cm_PutConn(connp);
    }	/* got an unauthenticated connection to this server */

    lock_ObtainMutex(&tsp->mx);
    if (code >= 0 || code == RXGEN_OPCODE) {
	/* mark server as up */
	_InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
        tsp->downTime = 0;

	/* we currently handle 32-bits of capabilities */
	if (code != RXGEN_OPCODE && caps.Capabilities_len > 0) {
	    tsp->capabilities = caps.Capabilities_val[0];
	    xdr_free((xdrproc_t) xdr_Capabilities, &caps);
	    caps.Capabilities_len = 0;
	    caps.Capabilities_val = 0;
	} else {
	    tsp->capabilities = 0;
	}

	osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is up with caps 0x%x",
		  osi_LogSaveString(afsd_logp, hoststr),
		  tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
		  tsp->capabilities);

        /* Now update the volume status if necessary */
        if (wasDown) {
            cm_server_vols_t * tsrvp;
            cm_volume_t * volp;
            int i;

            for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
                for (i=0; i<NUM_SERVER_VOLS; i++) {
                    if (tsrvp->ids[i] != 0) {
                        cm_InitReq(&req);

                        lock_ReleaseMutex(&tsp->mx);
                        code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
                                                &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp);
                        lock_ObtainMutex(&tsp->mx);
                        if (code == 0) {
                            cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
                            cm_PutVolume(volp);
                        }
                    }
                }
            }
            cm_RankServer(tsp);
        }
    } else {
	cm_MarkServerDown(tsp, code, wasDown);

	osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is down with caps 0x%x",
		  osi_LogSaveString(afsd_logp, hoststr),
		  tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
		  tsp->capabilities);
    }

    InterlockedDecrement(&tsp->pingCount);
    if (tsp->waitCount > 0)
	osi_Wakeup((LONG_PTR)tsp);
    lock_ReleaseMutex(&tsp->mx);
}