Beispiel #1
0
static void print_header(void)
{
	printf("diskscan version %s\n\n", VERSION);
	VERBOSE("Verbosity set");
	VVERBOSE("High verbosity set");
	VVVERBOSE("Very high verbosity set");
}
Beispiel #2
0
static void latency_bucket_prepare(disk_t *disk, struct scan_state *state, uint64_t offset)
{
	assert(state->latency_bucket < disk->latency_graph_len);
	latency_t *l = &disk->latency_graph[state->latency_bucket];
	const uint64_t start_sector = offset / disk->sector_size;

	VVERBOSE("bucket prepare bucket=%u", state->latency_bucket);

	l->start_sector = start_sector;
	l->latency_min_msec = UINT32_MAX;
	state->latency_count = 0;
}
Beispiel #3
0
static void latency_bucket_finish(disk_t *disk, struct scan_state *state, uint64_t offset)
{
	latency_t *l = &disk->latency_graph[state->latency_bucket];
	const uint64_t end_sector = offset / disk->sector_size;

	VVERBOSE("bucket finish bucket=%d", state->latency_bucket);

	l->end_sector = end_sector;
	l->latency_median_msec = median(state->latency, state->latency_count);

	state->latency_count = 0;
	state->latency_bucket++;
}
Beispiel #4
0
int disk_scan(disk_t *disk, enum scan_mode mode, unsigned data_size)
{
	disk->run = 1;
	void *data = allocate_buffer(data_size);
	uint32_t *scan_order = NULL;
	int result = 0;
	struct scan_state state = {.latency = NULL, .progress_bytes = 0, .progress_full = 1000};
	struct timespec ts_start;
	struct timespec ts_end;
	time_t scan_time;

	disk->conclusion = CONCLUSION_SCAN_PROBLEM;

	if (data_size % disk->sector_size != 0) {
		data_size -= data_size % disk->sector_size;
		if (data_size == 0)
			data_size = disk->sector_size;
		ERROR("Cannot scan data not in multiples of the sector size, adjusted scan size to %u", data_size);
	}

	set_realtime(true);
	clock_gettime(CLOCK_MONOTONIC, &ts_start);

	INFO("Scanning disk %s in %u byte steps", disk->path, data_size);
	scan_time = time(NULL);
	INFO("Scan started at: %s", ctime(&scan_time));
	VVVERBOSE("Using buffer of size %d", data_size);

	if (data == NULL) {
		ERROR("Failed to allocate data buffer, errno=%d: %s", errno, strerror(errno));
		result = 1;
		goto Exit;
	}

	uint64_t offset;
	const uint64_t disk_size_bytes = disk->num_bytes;
	const uint64_t latency_stride = calc_latency_stride(disk);
	VVERBOSE("latency stride is %"PRIu64, latency_stride);

	state.latency_bucket = 0;
	state.latency_stride = latency_stride;
	state.latency_count = 0;
	state.latency = malloc(sizeof(uint32_t) * latency_stride);
	state.data = data;

	scan_order = calc_scan_order(disk, mode, latency_stride, data_size);
	if (!scan_order) {
		result = 1;
		ERROR("Failed to generate scan order");
		goto Exit;
	}

	verbose_extra_newline = 1;
	for (offset = 0; disk->run && offset < disk_size_bytes; offset += latency_stride * disk->sector_size) {
		VERBOSE("Scanning stride starting at %"PRIu64" done %"PRIu64"%%", offset, offset*100/disk_size_bytes);
		progress_calc(disk, &state, 0);
		latency_bucket_prepare(disk, &state, offset);
		if (!disk_scan_latency_stride(disk, &state, offset, data_size, scan_order))
			break;
		latency_bucket_finish(disk, &state, offset + latency_stride * disk->sector_size);

		if (disk->is_ata)
			disk_ata_monitor(disk);
		else
			disk_scsi_monitor(disk);
	}
	verbose_extra_newline = 0;

	if (!disk->run) {
		INFO("Disk scan interrupted");
		disk->conclusion = CONCLUSION_ABORTED;
	} else {
		disk->conclusion = conclusion_calc(disk);
	}
	report_scan_done(disk);

Exit:
	clock_gettime(CLOCK_MONOTONIC, &ts_end);
	set_realtime(false);
	free(scan_order);
	free_buffer(data, data_size);
	free(state.latency);
	disk->run = 0;
	scan_time = time(NULL);
	INFO("Scan ended at: %s", ctime(&scan_time));
	INFO("Scan took %d second", (int)(ts_end.tv_sec - ts_start.tv_sec));
	return result;
}
Beispiel #5
0
void
backup_remote(phost_t host[], int which)
{
    /* receive a header from stdin, after that comes the tarfile.
     * From the header we can deduce what to do with the archive.
     * for daily, weekly and monthly we just put the archive in the
     * correct place, and possibly add encryption
     * remote is illegal
     * restore is also special
     */
    pheader_t header = NULL;
    char *out = NULL;
    char *decrypt = NULL;
    char *tar = NULL;
    char *split = NULL;
    unsigned int t = 0;
    unsigned long long int bytes;

    /* make the dirs */
    hdup_setup(host, which);

    /* do the allocation your self here */
    header = (pheader_t) g_malloc (sizeof(header_t));

    /* make some room */
    header->prot_ver  = (char*) g_malloc( strlen(PROT_VER) + 1);
    header->prot_name = (char*) g_malloc( strlen(PROT_NAME) + 1 );
    header->hostname   = (char *)g_malloc(MAXPATHLEN);
    header->scheme = (char *)g_malloc(8);
    header->date   = (char *)g_malloc(11);
    header->compression = (char *)g_malloc(5);
    header->encryption = (char *)g_malloc(1);
    header->extractdir = (char *)g_malloc(MAXPATHLEN);

    hdup_getheader(header, stdin);
    if ( hdup_checkheader(header) != 0 ) {
        /* header is bogus */
        LOG("%s","Protocol: bogus header");
        hdup_cleanup(-1,host[which]);
    }

    if(!g_str_equal(header->hostname, host[which]->name)) {
        /* header->hostname MUST match host[which]->name */
        LOG("%s","Protocol: local hostname does not match remote hostname");
        hdup_cleanup(-1,host[which]);
    }

    host[which]->date = header->date; /* copy from stdin */
    /* forget the put something in hdup->compression [miek 26-06-2003] */
    host[which]->compression = header->compression;

    /* scheme is already checked */
    hdup_archive(host[which], hdup_scheme(header->scheme));
    hdup_overview("Scheme rcvd",header->scheme);

    if (g_ascii_strncasecmp(header->scheme,scheme[RESTORE], strlen(scheme[RESTORE])) == 0) {
        /* remote restore operation */
        /* tell this here, MG 18 May 2004 */
        LOG("%s: STARTING REMOTE RESTORE", host[which]->name);

        /* should check if the file is split */
        /* check the extract dir */
        if ( hdup_globfilecheck(header->extractdir,NULL) == 0 )
            FATAL("%s %s %s", "Extract dir: ", header->extractdir, " does not exist");

        /* select the right compression, from the header... */
        /* extractfile is NULL here - so it does not work remotely */
        if (g_ascii_strncasecmp(header->compression, TAR_BZIP, strlen(TAR_BZIP)) == 0)
            tar = setup_untarcmd(host[which],header->extractdir,NULL, BZIP);
        if (g_ascii_strncasecmp(header->compression, TAR_GZIP, strlen(TAR_BZIP)) == 0)
            tar = setup_untarcmd(host[which],header->extractdir,NULL, GZIP);
        if (g_ascii_strncasecmp(header->compression, TAR_NONE, strlen(TAR_BZIP)) == 0)
            tar = setup_untarcmd(host[which],header->extractdir,NULL, NONE);

        if (host[which]->alg != NULL) {
            if (g_ascii_strncasecmp(header->encryption, "y",1) == 0 ) {
                VERBOSE("%s", "Encryption found - trying to decrypt");
                decrypt = setup_decryptcmd(host[which]);
                VVERBOSE("%s %s", "Decryption command: ", decrypt);
                out = g_strdup_printf("%s | %s", decrypt, tar);
            } else {
                VERBOSE("%s","Encryption specified in config - not using");
                out = tar;
            }
        } else
            out = tar;

        /* our output command has been specified */
        /* dont lock for restore
        hdup_lock(host[which], LOCK);
        */

        if (stream2pipe(stdin, out, NULL, &bytes) != 0) {
            LOG("%s", "Could not remotely restore the archive");
            hdup_cleanup(-1,host[which]);
        }
    } else if (g_ascii_strncasecmp(header->scheme,scheme[REMOTE], strlen(scheme[REMOTE])) == 0) {
        LOG("%s","Protocol: Illegal scheme: \'remote\'");
        hdup_cleanup(-1,host[which]);
    } else {
        /* place it on disk - check the chunksize in the config */
        LOG("%s: STARTING REMOTE BACKUP", host[which]->name);

        /* first check the encryption flag in the header */
        if (g_ascii_strncasecmp(header->encryption,"y",1) == 0)
            host[which]->archivename = g_strconcat(host[which]->archivename, MCRYPT_EXT, NULL);

        if ( host[which]->chunksize != NULL )
            split = setup_splitcmd(host[which]);

        /* Skip crypto stuff in the config file. This also allows the
         * configfiles at both ends to be identical
         */
        if ( host[which]->alg != NULL )
            VERBOSE("%s","Will not encrypt archives from remote hosts - encrypt them locally");

        /* set the lock */
        (void)hdup_lock(host[which], LOCK);
        if ( host[which]->chunksize == NULL ) {
            if (stream2file(stdin, host[which]->archivename, &bytes) == 0) {
                (void)hdup_chown (host[which]->archivename, host[which]->user,
                                  host[which]->group);
                (void)hdup_chmod (host[which]->archivename);
                VERBOSE("wrote %s", hdup_humansize((long long)bytes));
            } else {
                LOG("%s", "Could not create archive");
                hdup_cleanup(-1,host[which]);
            }
        } else {
            /* splitting */
            if (stream2pipe(stdin, split, NULL, &bytes) == 0) {
                t = hdup_chown_dir(host[which]->dirname_date,
                                   hdup_scheme(header->scheme) , host[which]->user,
                                   host[which]->group);
                VERBOSE("Chunks created: %d", t);
                VERBOSE("Chunk size: %s",host[which]->chunksize);
                hdup_chmod_dir(host[which]->dirname_date,hdup_scheme(header->scheme));
            } else {
                LOG("%s", "Could not create archive");
                hdup_cleanup(-1,host[which]);
            }
        }
    }
}