static void print_header(void) { printf("diskscan version %s\n\n", VERSION); VERBOSE("Verbosity set"); VVERBOSE("High verbosity set"); VVVERBOSE("Very high verbosity set"); }
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; }
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++; }
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; }
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]); } } } }