X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fdriver.c;h=594f694ec052b660c1e0839479752537c4a57994;hb=310f09c0f55a2fb6f3f3746d6ded20099792b773;hp=c9f53e45fc1a86f87ac46b9c2423f57f76d2670a;hpb=eefb15c5c04acb3c75f0c704ea664feb1bbae75c;p=debian%2Famanda diff --git a/server-src/driver.c b/server-src/driver.c index c9f53e4..594f694 100644 --- a/server-src/driver.c +++ b/server-src/driver.c @@ -24,7 +24,7 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: driver.c,v 1.164 2006/03/22 15:07:08 martinea Exp $ + * $Id: driver.c,v 1.198.2.6 2006/12/27 14:44:48 martinea Exp $ * * controlling process for the Amanda backup system */ @@ -34,7 +34,7 @@ * tape. Probably not effective though, should do this in planner. */ -/*#define HOLD_DEBUG*/ +#define HOLD_DEBUG #include "amanda.h" #include "clock.h" @@ -53,61 +53,63 @@ static disklist_t waitq, runq, tapeq, roomq; static int pending_aborts; static disk_t *taper_disk; static int degraded_mode; -static unsigned long reserved_space; -static unsigned long total_disksize; +static off_t reserved_space; +static off_t total_disksize; static char *dumper_program; static char *chunker_program; static int inparallel; static int nodump = 0; -static unsigned long tape_length, tape_left = 0; +static off_t tape_length = (off_t)0; +static off_t tape_left = (off_t)0; static int current_tape = 1; static int conf_taperalgo; static int conf_runtapes; static time_t sleep_time; static int idle_reason; -static char *datestamp; -static char *timestamp; +static char *driver_timestamp; +static char *hd_driver_timestamp; static am_host_t *flushhost = NULL; static int need_degraded=0; static event_handle_t *dumpers_ev_time = NULL; static event_handle_t *schedule_ev_read = NULL; -static void allocate_bandwidth P((interface_t *ip, int kps)); -static int assign_holdingdisk P((assignedhd_t **holdp, disk_t *diskp)); -static void adjust_diskspace P((disk_t *diskp, cmd_t cmd)); -static void delete_diskspace P((disk_t *diskp)); -static assignedhd_t **build_diskspace P((char *destname)); -static int client_constrained P((disk_t *dp)); -static void deallocate_bandwidth P((interface_t *ip, int kps)); -static void dump_schedule P((disklist_t *qp, char *str)); -static int dump_to_tape P((disk_t *dp)); -static assignedhd_t **find_diskspace P((unsigned long size, int *cur_idle, - assignedhd_t *preferred)); -static int free_kps P((interface_t *ip)); -static unsigned long free_space P((void)); -static void dumper_result P((disk_t *dp)); -static void handle_dumper_result P((void *)); -static void handle_chunker_result P((void *)); -static void handle_dumpers_time P((void *)); -static void handle_taper_result P((void *)); -static void holdingdisk_state P((char *time_str)); -static dumper_t *idle_dumper P((void)); -static void interface_state P((char *time_str)); -static int num_busy_dumpers P((void)); -static int queue_length P((disklist_t q)); -static disklist_t read_flush P((void)); -static void read_schedule P((void *cookie)); -static void short_dump_state P((void)); -static void startaflush P((void)); -static void start_degraded_mode P((disklist_t *queuep)); -static void start_some_dumps P((disklist_t *rq)); -static void continue_port_dumps(); -static void update_failed_dump_to_tape P((disk_t *)); +static int wait_children(int count); +static void wait_for_children(void); +static void allocate_bandwidth(interface_t *ip, unsigned long kps); +static int assign_holdingdisk(assignedhd_t **holdp, disk_t *diskp); +static void adjust_diskspace(disk_t *diskp, cmd_t cmd); +static void delete_diskspace(disk_t *diskp); +static assignedhd_t **build_diskspace(char *destname); +static int client_constrained(disk_t *dp); +static void deallocate_bandwidth(interface_t *ip, unsigned long kps); +static void dump_schedule(disklist_t *qp, char *str); +static int dump_to_tape(disk_t *dp); +static assignedhd_t **find_diskspace(off_t size, int *cur_idle, + assignedhd_t *preferred); +static unsigned long free_kps(interface_t *ip); +static off_t free_space(void); +static void dumper_result(disk_t *dp); +static void handle_dumper_result(void *); +static void handle_chunker_result(void *); +static void handle_dumpers_time(void *); +static void handle_taper_result(void *); +static void holdingdisk_state(char *time_str); +static dumper_t *idle_dumper(void); +static void interface_state(char *time_str); +static int queue_length(disklist_t q); +static disklist_t read_flush(void); +static void read_schedule(void *cookie); +static void short_dump_state(void); +static void startaflush(void); +static void start_degraded_mode(disklist_t *queuep); +static void start_some_dumps(disklist_t *rq); +static void continue_port_dumps(void); +static void update_failed_dump_to_tape(disk_t *); #if 0 -static void dump_state P((const char *str)); +static void dump_state(const char *str); #endif -int main P((int main_argc, char **main_argv)); +int main(int main_argc, char **main_argv); static const char *idle_strings[] = { #define NOT_IDLE 0 @@ -131,9 +133,9 @@ static const char *idle_strings[] = { }; int -main(main_argc, main_argv) - int main_argc; - char **main_argv; +main( + int main_argc, + char ** main_argv) { disklist_t origq; disk_t *diskp; @@ -151,17 +153,23 @@ main(main_argc, main_argv) int result_argc; char *result_argv[MAX_ARGS+1]; char *taper_program; - amwait_t retstat; char *conf_tapetype; tapetype_t *tape; + char *line; + int new_argc, my_argc; + char **new_argv, **my_argv; safe_fd(-1, 0); - setvbuf(stdout, (char *)NULL, _IOLBF, 0); - setvbuf(stderr, (char *)NULL, _IOLBF, 0); + setvbuf(stdout, (char *)NULL, (int)_IOLBF, 0); + setvbuf(stderr, (char *)NULL, (int)_IOLBF, 0); set_pname("driver"); + dbopen(DBG_SUBDIR_SERVER); + + atexit(wait_for_children); + /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); @@ -172,23 +180,29 @@ main(main_argc, main_argv) startclock(); + parse_server_conf(main_argc, main_argv, &new_argc, &new_argv); + my_argc = new_argc; + my_argv = new_argv; + printf("%s: pid %ld executable %s version %s\n", - get_pname(), (long) getpid(), main_argv[0], version()); + get_pname(), (long) getpid(), my_argv[0], version()); - if (main_argc > 1) { - config_name = stralloc(main_argv[1]); + if (my_argc > 1) { + config_name = stralloc(my_argv[1]); config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL); - if(main_argc > 2) { - if(strncmp(main_argv[2], "nodump", 6) == 0) { + if(my_argc > 2) { + if(strncmp(my_argv[2], "nodump", 6) == 0) { nodump = 1; } } } else { + char my_cwd[STR_SIZE]; - if (getcwd(my_cwd, sizeof(my_cwd)) == NULL) { + if (getcwd(my_cwd, SIZEOF(my_cwd)) == NULL) { error("cannot determine current working directory"); + /*NOTREACHED*/ } config_dir = stralloc2(my_cwd, "/"); if ((config_name = strrchr(my_cwd, '/')) != NULL) { @@ -201,13 +215,50 @@ main(main_argc, main_argv) conffile = stralloc2(config_dir, CONFFILE_NAME); if(read_conffile(conffile)) { error("errors processing config file \"%s\"", conffile); + /*NOTREACHED*/ } amfree(conffile); - amfree(datestamp); - datestamp = construct_datestamp(NULL); - timestamp = construct_timestamp(NULL); - log_add(L_START,"date %s", datestamp); + dbrename(config_name, DBG_SUBDIR_SERVER); + + report_bad_conf_arg(); + + amfree(driver_timestamp); + /* read timestamp from stdin */ + while ((line = agets(stdin)) != NULL) { + if (line[0] != '\0') + break; + amfree(line); + } + if ( line == NULL ) { + error("Did not get DATE line from planner"); + /*NOTREACHED*/ + } + driver_timestamp = alloc(15); + strncpy(driver_timestamp, &line[5], 14); + driver_timestamp[14] = '\0'; + amfree(line); + log_add(L_START,"date %s", driver_timestamp); + + /* check that we don't do many dump in a day and usetimestamps is off */ + if(strlen(driver_timestamp) == 8) { + if (!nodump) { + char *conf_logdir = getconf_str(CNF_LOGDIR); + char *logfile = vstralloc(conf_logdir, "/log.", + driver_timestamp, ".0", NULL); + char *oldlogfile = vstralloc(conf_logdir, "/oldlog/log.", + driver_timestamp, ".0", NULL); + if(access(logfile, F_OK) == 0 || access(oldlogfile, F_OK) == 0) { + log_add(L_WARNING, "WARNING: This is not the first amdump run today. Enable the usetimestamps option in the configuration file if you want to run amdump more than once per calendar day."); + } + amfree(oldlogfile); + amfree(logfile); + } + hd_driver_timestamp = construct_timestamp(NULL); + } + else { + hd_driver_timestamp = stralloc(driver_timestamp); + } taper_program = vstralloc(libexecdir, "/", "taper", versionsuffix(), NULL); dumper_program = vstralloc(libexecdir, "/", "dumper", versionsuffix(), @@ -215,20 +266,12 @@ main(main_argc, main_argv) chunker_program = vstralloc(libexecdir, "/", "chunker", versionsuffix(), NULL); - conf_taperalgo = getconf_int(CNF_TAPERALGO); + conf_taperalgo = getconf_taperalgo(CNF_TAPERALGO); conf_tapetype = getconf_str(CNF_TAPETYPE); conf_runtapes = getconf_int(CNF_RUNTAPES); tape = lookup_tapetype(conf_tapetype); - tape_length = tape->length; - printf("driver: tape size %ld\n", tape_length); - - /* taper takes a while to get going, so start it up right away */ - - init_driverio(); - if(conf_runtapes > 0) { - startup_tape_process(taper_program); - taper_cmd(START_TAPER, datestamp, NULL, 0, NULL); - } + tape_length = tapetype_get_length(tape); + printf("driver: tape size " OFF_T_FMT "\n", (OFF_T_FMT_TYPE)tape_length); /* start initializing: read in databases */ @@ -238,73 +281,90 @@ main(main_argc, main_argv) } else { conf_diskfile = stralloc2(config_dir, conf_diskfile); } - if (read_diskfile(conf_diskfile, &origq) < 0) + if (read_diskfile(conf_diskfile, &origq) < 0) { error("could not load disklist \"%s\"", conf_diskfile); + /*NOTREACHED*/ + } amfree(conf_diskfile); /* set up any configuration-dependent variables */ inparallel = getconf_int(CNF_INPARALLEL); - reserve = getconf_int(CNF_RESERVE); + reserve = (unsigned long)getconf_int(CNF_RESERVE); - total_disksize = 0; + total_disksize = (off_t)0; for(hdp = getconf_holdingdisks(), dsk = 0; hdp != NULL; hdp = hdp->next, dsk++) { - hdp->up = (void *)alloc(sizeof(holdalloc_t)); + hdp->up = (void *)alloc(SIZEOF(holdalloc_t)); holdalloc(hdp)->allocated_dumpers = 0; - holdalloc(hdp)->allocated_space = 0L; + holdalloc(hdp)->allocated_space = (off_t)0; - if(get_fs_stats(hdp->diskdir, &fs) == -1 - || access(hdp->diskdir, W_OK) == -1) { + if(get_fs_stats(holdingdisk_get_diskdir(hdp), &fs) == -1 + || access(holdingdisk_get_diskdir(hdp), W_OK) == -1) { log_add(L_WARNING, "WARNING: ignoring holding disk %s: %s\n", - hdp->diskdir, strerror(errno)); + holdingdisk_get_diskdir(hdp), strerror(errno)); hdp->disksize = 0L; continue; } - if(fs.avail != -1) { - if(hdp->disksize > 0) { + if(fs.avail != (off_t)-1) { + if(hdp->disksize > (off_t)0) { if(hdp->disksize > fs.avail) { log_add(L_WARNING, - "WARNING: %s: %ld KB requested, but only %ld KB available.", - hdp->diskdir, hdp->disksize, fs.avail); + "WARNING: %s: " OFF_T_FMT " KB requested, " + "but only " OFF_T_FMT " KB available.", + holdingdisk_get_diskdir(hdp), + (OFF_T_FMT_TYPE)hdp->disksize, + (OFF_T_FMT_TYPE)fs.avail); hdp->disksize = fs.avail; } } - else if(fs.avail + hdp->disksize < 0) { + else if((fs.avail + hdp->disksize) < (off_t)0) { log_add(L_WARNING, - "WARNING: %s: not %ld KB free.", - hdp->diskdir, -hdp->disksize); - hdp->disksize = 0L; + "WARNING: %s: not " OFF_T_FMT " KB free.", + holdingdisk_get_diskdir(hdp), -hdp->disksize); + hdp->disksize = (off_t)0; continue; } else hdp->disksize += fs.avail; } - printf("driver: adding holding disk %d dir %s size %ld chunksize %ld\n", - dsk, hdp->diskdir, hdp->disksize, hdp->chunksize); + printf("driver: adding holding disk %d dir %s size " + OFF_T_FMT " chunksize " OFF_T_FMT "\n", + dsk, holdingdisk_get_diskdir(hdp), + (OFF_T_FMT_TYPE)hdp->disksize, + (OFF_T_FMT_TYPE)(holdingdisk_get_chunksize(hdp))); newdir = newvstralloc(newdir, - hdp->diskdir, "/", timestamp, + holdingdisk_get_diskdir(hdp), "/", hd_driver_timestamp, NULL); if(!mkholdingdir(newdir)) { - hdp->disksize = 0L; + hdp->disksize = (off_t)0; } total_disksize += hdp->disksize; } - reserved_space = total_disksize * (reserve / 100.0); + reserved_space = total_disksize * (off_t)(reserve / 100); - printf("reserving %ld out of %ld for degraded-mode dumps\n", - reserved_space, free_space()); + printf("reserving " OFF_T_FMT " out of " OFF_T_FMT + " for degraded-mode dumps\n", + (OFF_T_FMT_TYPE)reserved_space, (OFF_T_FMT_TYPE)free_space()); amfree(newdir); if(inparallel > MAX_DUMPERS) inparallel = MAX_DUMPERS; + /* taper takes a while to get going, so start it up right away */ + + init_driverio(); + if(conf_runtapes > 0) { + startup_tape_process(taper_program); + taper_cmd(START_TAPER, driver_timestamp, NULL, 0, NULL); + } + /* fire up the dumpers now while we are waiting */ - if(!nodump) startup_dump_processes(dumper_program, inparallel); + if(!nodump) startup_dump_processes(dumper_program, inparallel, driver_timestamp); /* * Read schedule from stdin. Usually, this is a pipe from planner, @@ -323,11 +383,11 @@ main(main_argc, main_argv) log_add(L_STATS, "startup time %s", walltime_str(curclock())); - printf("driver: start time %s inparallel %d bandwidth %d diskspace %lu", - walltime_str(curclock()), inparallel, free_kps((interface_t *)0), - free_space()); + printf("driver: start time %s inparallel %d bandwidth %lu diskspace " + OFF_T_FMT " ", walltime_str(curclock()), inparallel, + free_kps((interface_t *)0), (OFF_T_FMT_TYPE)free_space()); printf(" dir %s datestamp %s driver: drain-ends tapeq %s big-dumpers %s\n", - "OBSOLETE", datestamp, taperalgo2str(conf_taperalgo), + "OBSOLETE", driver_timestamp, taperalgo2str(conf_taperalgo), getconf_str(CNF_DUMPORDER)); fflush(stdout); @@ -352,7 +412,7 @@ main(main_argc, main_argv) if(!need_degraded) startaflush(); if(!nodump) - schedule_ev_read = event_register(0, EV_READFD, read_schedule, NULL); + schedule_ev_read = event_register((event_id_t)0, EV_READFD, read_schedule, NULL); short_dump_state(); event_loop(0); @@ -361,7 +421,13 @@ main(main_argc, main_argv) while(!empty(runq) && taper > 0) { diskp = dequeue_disk(&runq); - if(!degraded_mode) { + if (diskp->to_holdingdisk == HOLD_REQUIRED) { + log_add(L_FAIL, "%s %s %s %d [%s]", + diskp->host->hostname, diskp->name, sched(diskp)->datestamp, + sched(diskp)->level, + "can't dump required holdingdisk"); + } + else if (!degraded_mode) { int rc = dump_to_tape(diskp); if(rc == 1) log_add(L_INFO, @@ -380,9 +446,9 @@ main(main_argc, main_argv) log_add(L_FAIL, "%s %s %s %d [%s]", diskp->host->hostname, diskp->name, sched(diskp)->datestamp, sched(diskp)->level, - diskp->no_hold ? - "can't dump no-hold disk in degraded mode" : - "no more holding disk space"); + diskp->to_holdingdisk == HOLD_AUTO ? + "no more holding disk space" : + "can't dump no-hold disk in degraded mode"); } short_dump_state(); /* for amstatus */ @@ -393,7 +459,8 @@ main(main_argc, main_argv) if(!nodump) { for(dumper = dmptable; dumper < dmptable + inparallel; dumper++) { - dumper_cmd(dumper, QUIT, NULL); + if(dumper->fd >= 0) + dumper_cmd(dumper, QUIT, NULL); } } @@ -402,53 +469,10 @@ main(main_argc, main_argv) } /* wait for all to die */ - - while(1) { - char number[NUM_STR_SIZE]; - pid_t pid; - char *who; - char *what; - int code=0; - - if((pid = wait(&retstat)) == -1) { - if(errno == EINTR) continue; - else break; - } - what = NULL; - if(! WIFEXITED(retstat)) { - what = "signal"; - code = WTERMSIG(retstat); - } else if(WEXITSTATUS(retstat) != 0) { - what = "code"; - code = WEXITSTATUS(retstat); - } - who = NULL; - for(dumper = dmptable; dumper < dmptable + inparallel; dumper++) { - if(pid == dumper->pid) { - who = stralloc(dumper->name); - break; - } - } - if(who == NULL && pid == taper_pid) { - who = stralloc("taper"); - } - if(what != NULL && who == NULL) { - snprintf(number, sizeof(number), "%ld", (long)pid); - who = stralloc2("unknown pid ", number); - } - if(who && what) { - log_add(L_WARNING, "%s exited with %s %d\n", who, what, code); - printf("driver: %s exited with %s %d\n", who, what, code); - } - amfree(who); - } - - for(dumper = dmptable; dumper < dmptable + inparallel; dumper++) { - amfree(dumper->name); - } + wait_children(600); for(hdp = getconf_holdingdisks(); hdp != NULL; hdp = hdp->next) { - cleanup_holdingdisk(hdp->diskdir, 0); + cleanup_holdingdisk(holdingdisk_get_diskdir(hdp), 0); amfree(hdp->up); } amfree(newdir); @@ -456,10 +480,10 @@ main(main_argc, main_argv) check_unfree_serial(); printf("driver: FINISHED time %s\n", walltime_str(curclock())); fflush(stdout); - log_add(L_FINISH,"date %s time %s", datestamp, walltime_str(curclock())); - amfree(datestamp); - amfree(timestamp); + log_add(L_FINISH,"date %s time %s", driver_timestamp, walltime_str(curclock())); + amfree(driver_timestamp); + free_new_argv(new_argc, new_argv); amfree(dumper_program); amfree(taper_program); amfree(config_dir); @@ -471,16 +495,153 @@ main(main_argc, main_argv) malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2); } + dbclose(); + return 0; } +/* sleep up to count seconds, and wait for terminating child process */ +/* if sleep is negative, this function will not timeout */ +/* exit once all child process are finished or the timout expired */ +/* return 0 if no more children to wait */ +/* return 1 if some children are still alive */ +static int +wait_children(int count) +{ + pid_t pid; + amwait_t retstat; + char *who; + char *what; + int code=0; + dumper_t *dumper; + int wait_errno; + + do { + do { + pid = waitpid((pid_t)-1, &retstat, WNOHANG); + wait_errno = errno; + if (pid > 0) { + what = NULL; + if (! WIFEXITED(retstat)) { + what = "signal"; + code = WTERMSIG(retstat); + } else if (WEXITSTATUS(retstat) != 0) { + what = "code"; + code = WEXITSTATUS(retstat); + } + who = NULL; + for (dumper = dmptable; dumper < dmptable + inparallel; + dumper++) { + if (pid == dumper->pid) { + who = stralloc(dumper->name); + dumper->pid = -1; + break; + } + if (dumper->chunker && pid == dumper->chunker->pid) { + who = stralloc(dumper->chunker->name); + dumper->chunker->pid = -1; + break; + } + } + if (who == NULL && pid == taper_pid) { + who = stralloc("taper"); + taper_pid = -1; + } + if(what != NULL && who == NULL) { + who = stralloc("unknown"); + } + if(who && what) { + log_add(L_WARNING, "%s pid %u exited with %s %d\n", who, + (unsigned)pid, what, code); + printf("driver: %s pid %u exited with %s %d\n", who, + (unsigned)pid, what, code); + } + amfree(who); + } + } while (pid > 0 || wait_errno == EINTR); + if (errno != ECHILD) + sleep(1); + if (count > 0) + count--; + } while ((errno != ECHILD) && (count != 0)); + return (errno != ECHILD); +} + static void -startaflush() +kill_children(int signal) +{ + dumper_t *dumper; + + if(!nodump) { + for(dumper = dmptable; dumper < dmptable + inparallel; dumper++) { + if (!dumper->down && dumper->pid > 1) { + printf("driver: sending signal %d to %s pid %u\n", signal, + dumper->name, (unsigned)dumper->pid); + if (kill(dumper->pid, signal) == -1 && errno == ESRCH) { + if (dumper->chunker) + dumper->chunker->pid = 0; + } + if (dumper->chunker && dumper->chunker->pid > 1) { + printf("driver: sending signal %d to %s pid %u\n", signal, + dumper->chunker->name, + (unsigned)dumper->chunker->pid); + if (kill(dumper->chunker->pid, signal) == -1 && + errno == ESRCH) + dumper->chunker->pid = 0; + } + } + } + } + + if(taper_pid > 1) + printf("driver: sending signal %d to %s pid %u\n", signal, + "taper", (unsigned)taper_pid); + if (kill(taper_pid, signal) == -1 && errno == ESRCH) + taper_pid = 0; +} + +static void +wait_for_children(void) +{ + dumper_t *dumper; + + if(!nodump) { + for(dumper = dmptable; dumper < dmptable + inparallel; dumper++) { + if (dumper->pid > 1 && dumper->fd >= 0) { + dumper_cmd(dumper, QUIT, NULL); + if (dumper->chunker && dumper->chunker->pid > 1 && + dumper->chunker->fd >= 0) + chunker_cmd(dumper->chunker, QUIT, NULL); + } + } + } + + if(taper_pid > 1 && taper > 0) { + taper_cmd(QUIT, NULL, NULL, 0, NULL); + } + + if(wait_children(60) == 0) + return; + + kill_children(SIGHUP); + if(wait_children(60) == 0) + return; + + kill_children(SIGKILL); + if(wait_children(-1) == 0) + return; + +} + +static void +startaflush(void) { disk_t *dp = NULL; disk_t *fit = NULL; char *datestamp; - unsigned int extra_tapes = 0; + int extra_tapes = 0; + char *qname; + if(!degraded_mode && !taper_busy && !empty(tapeq)) { datestamp = sched(tapeq.head)->datestamp; @@ -491,10 +652,11 @@ startaflush() case ALGO_FIRSTFIT: fit = tapeq.head; while (fit != NULL) { - extra_tapes = (fit->tape_splitsize > 0) ? - conf_runtapes - current_tape : 0; - if(sched(fit)->act_size <= (tape_left + tape_length*extra_tapes) && - strcmp(sched(fit)->datestamp, datestamp) <= 0) { + extra_tapes = (fit->tape_splitsize > (off_t)0) ? + conf_runtapes - current_tape : 0; + if(sched(fit)->act_size <= (tape_left + + tape_length * (off_t)extra_tapes) && + strcmp(sched(fit)->datestamp, datestamp) <= 0) { dp = fit; fit = NULL; } @@ -518,9 +680,10 @@ startaflush() case ALGO_LARGESTFIT: fit = tapeq.head; while (fit != NULL) { - extra_tapes = (fit->tape_splitsize > 0) ? - conf_runtapes - current_tape : 0; - if(sched(fit)->act_size <= (tape_left + tape_length*extra_tapes) && + extra_tapes = (fit->tape_splitsize > (off_t)0) ? + conf_runtapes - current_tape : 0; + if(sched(fit)->act_size <= + (tape_left + tape_length * (off_t)extra_tapes) && (!dp || sched(fit)->act_size > sched(dp)->act_size) && strcmp(sched(fit)->datestamp, datestamp) <= 0) { dp = fit; @@ -552,21 +715,25 @@ startaflush() if(dp) remove_disk(&tapeq, dp); } if(taper_ev_read == NULL) { - taper_ev_read = event_register(taper, EV_READFD, + taper_ev_read = event_register((event_id_t)taper, EV_READFD, handle_taper_result, NULL); } - if (dp != NULL) { + if (dp) { taper_disk = dp; taper_busy = 1; + qname = quote_string(dp->name); taper_cmd(FILE_WRITE, dp, sched(dp)->destname, sched(dp)->level, - sched(dp)->datestamp); - fprintf(stderr,"driver: startaflush: %s %s %s %ld %ld\n", - taperalgo2str(conf_taperalgo), dp->host->hostname, - dp->name, sched(taper_disk)->act_size, tape_left); + sched(dp)->datestamp); + fprintf(stderr,"driver: startaflush: %s %s %s " + OFF_T_FMT " " OFF_T_FMT "\n", + taperalgo2str(conf_taperalgo), dp->host->hostname, qname, + (OFF_T_FMT_TYPE)sched(taper_disk)->act_size, + (OFF_T_FMT_TYPE)tape_left); if(sched(dp)->act_size <= tape_left) tape_left -= sched(dp)->act_size; else - tape_left = 0; + tape_left = (off_t)0; + amfree(qname); } else { error("FATAL: Taper marked busy and no work found."); /*NOTREACHED*/ @@ -579,8 +746,8 @@ startaflush() static int -client_constrained(dp) - disk_t *dp; +client_constrained( + disk_t * dp) { disk_t *dp2; @@ -605,8 +772,8 @@ client_constrained(dp) } static void -start_some_dumps(rq) - disklist_t *rq; +start_some_dumps( + disklist_t * rq) { int cur_idle; disk_t *diskp, *delayed_diskp, *diskp_accept; @@ -635,7 +802,6 @@ start_some_dumps(rq) } if (dumper->ev_read != NULL) { -/* assert(dumper->ev_read == NULL);*/ event_release(dumper->ev_read); dumper->ev_read = NULL; } @@ -666,7 +832,7 @@ start_some_dumps(rq) cur_idle = NOT_IDLE; dumporder = getconf_str(CNF_DUMPORDER); - if(strlen(dumporder) > (dumper-dmptable)) { + if(strlen(dumporder) > (size_t)(dumper-dmptable)) { dumptype = dumporder[dumper-dmptable]; } else { @@ -679,10 +845,6 @@ start_some_dumps(rq) for(diskp = rq->head; diskp != NULL; diskp = diskp->next) { assert(diskp->host != NULL && sched(diskp) != NULL); - /* round estimate to next multiple of DISK_BLOCK_KB */ - sched(diskp)->est_size = am_round(sched(diskp)->est_size, - DISK_BLOCK_KB); - if (diskp->host->start_t > now) { cur_idle = max(cur_idle, IDLE_START_WAIT); if (delayed_diskp == NULL || sleep_time > diskp->host->start_t) { @@ -700,12 +862,11 @@ start_some_dumps(rq) cur_idle = max(cur_idle, IDLE_NO_BANDWIDTH); } else if(sched(diskp)->no_space) { cur_idle = max(cur_idle, IDLE_NO_DISKSPACE); + } else if (diskp->to_holdingdisk == HOLD_NEVER) { + cur_idle = max(cur_idle, IDLE_NO_HOLD); } else if ((holdp = - find_diskspace(sched(diskp)->est_size,&cur_idle,NULL)) == NULL) { + find_diskspace(sched(diskp)->est_size, &cur_idle, NULL)) == NULL) { cur_idle = max(cur_idle, IDLE_NO_DISKSPACE); - } else if (diskp->no_hold) { - free_assignedhd(holdp); - cur_idle = max(cur_idle, IDLE_NO_HOLD); } else if (client_constrained(diskp)) { free_assignedhd(holdp); cur_idle = max(cur_idle, IDLE_CLIENT_CONSTRAINED); @@ -762,11 +923,11 @@ start_some_dumps(rq) if (diskp == NULL && delayed_diskp != NULL) { assert(sleep_time > now); sleep_time -= now; - dumpers_ev_time = event_register(sleep_time, EV_TIME, + dumpers_ev_time = event_register((event_id_t)sleep_time, EV_TIME, handle_dumpers_time, &runq); return; } else if (diskp != NULL) { - sched(diskp)->act_size = 0; + sched(diskp)->act_size = (off_t)0; allocate_bandwidth(diskp->host->netif, sched(diskp)->est_kps); sched(diskp)->activehd = assign_holdingdisk(holdp, diskp); amfree(holdp); @@ -777,41 +938,57 @@ start_some_dumps(rq) sched(diskp)->dumper = dumper; sched(diskp)->timestamp = now; - dumper->ev_read = event_register(dumper->fd, EV_READFD, - handle_dumper_result, dumper); dumper->busy = 1; /* dumper is now busy */ dumper->dp = diskp; /* link disk to dumper */ remove_disk(rq, diskp); /* take it off the run queue */ - sched(diskp)->origsize = -1; - sched(diskp)->dumpsize = -1; - sched(diskp)->dumptime = -1; - sched(diskp)->tapetime = -1; + sched(diskp)->origsize = (off_t)-1; + sched(diskp)->dumpsize = (off_t)-1; + sched(diskp)->dumptime = (time_t)0; + sched(diskp)->tapetime = (time_t)0; chunker = dumper->chunker; chunker->result = LAST_TOK; dumper->result = LAST_TOK; startup_chunk_process(chunker,chunker_program); + chunker_cmd(chunker, START, (void *)driver_timestamp); chunker->dumper = dumper; chunker_cmd(chunker, PORT_WRITE, diskp); cmd = getresult(chunker->fd, 1, &result_argc, result_argv, MAX_ARGS+1); if(cmd != PORT) { + assignedhd_t **h=NULL; + int activehd; + printf("driver: did not get PORT from %s for %s:%s\n", chunker->name, diskp->host->hostname, diskp->name); fflush(stdout); - return ; /* fatal problem */ - } - chunker->ev_read = event_register(chunker->fd, EV_READFD, - handle_chunker_result, chunker); - dumper->output_port = atoi(result_argv[2]); - dumper_cmd(dumper, PORT_DUMP, diskp); + deallocate_bandwidth(diskp->host->netif, sched(diskp)->est_kps); + h = sched(diskp)->holdp; + activehd = sched(diskp)->activehd; + h[activehd]->used = 0; + holdalloc(h[activehd]->disk)->allocated_dumpers--; + adjust_diskspace(diskp, DONE); + delete_diskspace(diskp); + diskp->host->inprogress--; + diskp->inprogress = 0; + sched(diskp)->dumper = NULL; + dumper->busy = 0; + dumper->dp = NULL; + sched(diskp)->attempted++; + free_serial_dp(diskp); + if(sched(diskp)->attempted < 2) + enqueue_disk(rq, diskp); + } + else { + dumper->ev_read = event_register((event_id_t)dumper->fd, EV_READFD, + handle_dumper_result, dumper); + chunker->ev_read = event_register((event_id_t)chunker->fd, EV_READFD, + handle_chunker_result, chunker); + dumper->output_port = atoi(result_argv[2]); + dumper_cmd(dumper, PORT_DUMP, diskp); + } diskp->host->start_t = now + 15; - } else if (/* cur_idle != NOT_IDLE && */ - (num_busy_dumpers() > 0 || taper_busy)) { - /* - * We are constrained. - */ } } } @@ -821,9 +998,10 @@ start_some_dumps(rq) * be because a disk has a delayed start, or amanda is constrained * by network or disk limits. */ + static void -handle_dumpers_time(cookie) - void *cookie; +handle_dumpers_time( + void * cookie) { disklist_t *runq = cookie; event_release(dumpers_ev_time); @@ -832,29 +1010,34 @@ handle_dumpers_time(cookie) } static void -dump_schedule(qp, str) - disklist_t *qp; - char *str; +dump_schedule( + disklist_t *qp, + char * str) { disk_t *dp; + char *qname; printf("dump of driver schedule %s:\n--------\n", str); for(dp = qp->head; dp != NULL; dp = dp->next) { - printf(" %-20s %-25s lv %d t %5ld s %8lu p %d\n", - dp->host->hostname, dp->name, sched(dp)->level, - sched(dp)->est_time, sched(dp)->est_size, sched(dp)->priority); + qname = quote_string(dp->name); + printf(" %-20s %-25s lv %d t %5lu s " OFF_T_FMT " p %d\n", + dp->host->hostname, qname, sched(dp)->level, + sched(dp)->est_time, + (OFF_T_FMT_TYPE)sched(dp)->est_size, sched(dp)->priority); + amfree(qname); } printf("--------\n"); } static void -start_degraded_mode(queuep) - disklist_t *queuep; +start_degraded_mode( + /*@keep@*/ disklist_t *queuep) { disk_t *dp; disklist_t newq; - unsigned long est_full_size; + off_t est_full_size; + char *qname; if (taper_ev_read != NULL) { event_release(taper_ev_read); @@ -865,10 +1048,11 @@ start_degraded_mode(queuep) dump_schedule(queuep, "before start degraded mode"); - est_full_size = 0; + est_full_size = (off_t)0; while(!empty(*queuep)) { dp = dequeue_disk(queuep); + qname = quote_string(dp->name); if(sched(dp)->level != 0) /* go ahead and do the disk as-is */ enqueue_disk(&newq, dp); @@ -881,27 +1065,30 @@ start_degraded_mode(queuep) else if(sched(dp)->degr_level != -1) { sched(dp)->level = sched(dp)->degr_level; sched(dp)->dumpdate = sched(dp)->degr_dumpdate; - sched(dp)->est_size = sched(dp)->degr_size; + sched(dp)->est_nsize = sched(dp)->degr_nsize; + sched(dp)->est_csize = sched(dp)->degr_csize; sched(dp)->est_time = sched(dp)->degr_time; sched(dp)->est_kps = sched(dp)->degr_kps; enqueue_disk(&newq, dp); } else { log_add(L_FAIL,"%s %s %s %d [can't switch to incremental dump]", - dp->host->hostname, dp->name, sched(dp)->datestamp, + dp->host->hostname, qname, sched(dp)->datestamp, sched(dp)->level); } } + amfree(qname); } - *queuep = newq; + /*@i@*/ *queuep = newq; degraded_mode = 1; dump_schedule(queuep, "after start degraded mode"); } -static void continue_port_dumps() +static void +continue_port_dumps(void) { disk_t *dp, *ndp; assignedhd_t **h; @@ -912,13 +1099,17 @@ static void continue_port_dumps() for( dp = roomq.head; dp; dp = ndp ) { ndp = dp->next; /* find last holdingdisk used by this dump */ - for( i = 0, h = sched(dp)->holdp; h[i+1]; i++ ); + for( i = 0, h = sched(dp)->holdp; h[i+1]; i++ ) { + (void)h; /* Quiet lint */ + } /* find more space */ h = find_diskspace( sched(dp)->est_size - sched(dp)->act_size, &active_dumpers, h[i] ); if( h ) { for(dumper = dmptable; dumper < dmptable + inparallel && - dumper->dp != dp; dumper++); + dumper->dp != dp; dumper++) { + (void)dp; /* Quiet lint */ + } assert( dumper < dmptable + inparallel ); sched(dp)->activehd = assign_holdingdisk( h, dp ); chunker_cmd( dumper->chunker, CONTINUE, dp ); @@ -964,7 +1155,7 @@ static void continue_port_dumps() * We abort that dump, hopefully not wasting too much time retrying it. */ remove_disk( &roomq, dp ); - chunker_cmd( sched(dp)->dumper->chunker, ABORT, NULL ); + chunker_cmd( sched(dp)->dumper->chunker, ABORT, NULL); dumper_cmd( sched(dp)->dumper, ABORT, NULL ); pending_aborts++; } @@ -972,15 +1163,18 @@ static void continue_port_dumps() static void -handle_taper_result(void *cookie) +handle_taper_result( + void * cookie) { disk_t *dp; - int filenum; + off_t filenum; cmd_t cmd; int result_argc; char *result_argv[MAX_ARGS+1]; int avail_tapes = 0; + (void)cookie; /* Quiet unused parameter warning */ + assert(cookie == NULL); do { @@ -995,12 +1189,13 @@ handle_taper_result(void *cookie) case DONE: /* DONE