From: Kern Sibbald Date: Fri, 24 Nov 2006 09:58:28 +0000 (+0000) Subject: kes Separate read/write source strings to keep track of where X-Git-Tag: Release-2.0.0~227 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=d0c1f5f22cbea872106e4f54ea979419ee58fc03;p=bacula%2Fbacula kes Separate read/write source strings to keep track of where storage devices are used in a job. kes Implement a new method of keeping track of which storage device is used in a Job. USTORE keeps both a pointer to the resource and to the source string. kes Modify all code to use new storage set subroutines in job.c kes Modify migrate.c so that the definitive selection of the storage resource is done in the do_migration_init() routine prior to the job going into the job queue. This permits accurate deadlock detection (same read and write storage resource). kes Remove bfill from btape (I think it was a left over stub). git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3690 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/kernstodo b/bacula/kernstodo index db177e3f1d..235b1017dd 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -41,6 +41,7 @@ Document: Priority: +- Fix prog copyright (SD) all other files. - Migration Volume span bug - Rescue release - Bug reports diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index 47e70441b7..e1a0442a80 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -202,7 +202,6 @@ bool do_backup(JCR *jcr) goto bail_out; } - if (!send_runscripts_commands(jcr)) { goto bail_out; } @@ -466,7 +465,7 @@ void backup_cleanup(JCR *jcr, int TermCode) jcr->client->name(), cr.Uname, jcr->fileset->name(), jcr->FSCreateTime, jcr->pool->name(), jcr->pool_source, - jcr->wstore->name(), jcr->storage_source, + jcr->wstore->name(), jcr->wstore_source, schedt, sdt, edt, diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 69381516fc..ac4cfa109e 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -307,6 +307,40 @@ inline char *STORE::dev_name() const inline char *STORE::name() const { return hdr.name; } +/* + * This is a sort of "unified" store that has both the + * storage pointer and the text of where the pointer was + * found. + */ +class USTORE { +public: + STORE *store; + POOLMEM *store_source; + + /* Methods */ + USTORE() { store = NULL; store_source = get_pool_memory(PM_MESSAGE); } + ~USTORE() { destroy(); } + void set_source(const char *where); + void destroy(); +}; + +inline void USTORE::destroy() +{ + if (store_source) { + free_pool_memory(store_source); + store_source = NULL; + } +} + + +inline void USTORE::set_source(const char *where) +{ + if (!store_source) { + store_source = get_pool_memory(PM_MESSAGE); + } + pm_strcpy(store_source, where); +} + /* * Job Resource diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 798ff22037..43d5bdcdd3 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -87,6 +87,7 @@ JobId_t run_job(JCR *jcr) { int stat; if (setup_job(jcr)) { + Dmsg0(200, "Add jrc to work queue\n"); /* Queue the job to be run */ if ((stat = jobq_add(&job_queue, jcr)) != 0) { berrno be; @@ -143,10 +144,6 @@ bool setup_job(JCR *jcr) jcr->pool_source = get_pool_memory(PM_MESSAGE); pm_strcpy(jcr->pool_source, _("unknown source")); } - if (!jcr->storage_source) { - jcr->storage_source = get_pool_memory(PM_MESSAGE); - pm_strcpy(jcr->storage_source, _("unknown source")); - } /* * Create Job record @@ -160,12 +157,12 @@ bool setup_job(JCR *jcr) Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n", jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel); - generate_daemon_event(jcr, "JobStart"); - if (!get_or_create_client_record(jcr)) { goto bail_out; } + generate_daemon_event(jcr, "JobStart"); + if (job_canceled(jcr)) { goto bail_out; } @@ -209,8 +206,6 @@ bool setup_job(JCR *jcr) } generate_job_event(jcr, "JobInit"); - - Dmsg0(200, "Add jrc to work queue\n"); return true; bail_out: @@ -389,12 +384,17 @@ bool cancel_job(UAContext *ua, JCR *jcr) copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); } } else { + USTORE store; if (jcr->rstorage) { - set_wstorage(ua->jcr, jcr->rstore); + store.store = jcr->rstore; + pm_strcpy(store.store_source, jcr->rstore_source); } else { - set_wstorage(ua->jcr, jcr->wstore); + store.store = jcr->wstore; + pm_strcpy(store.store_source, jcr->wstore_source); } + set_wstorage(ua->jcr, &store); } + if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); return false; @@ -616,7 +616,7 @@ DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name) void apply_pool_overrides(JCR *jcr) { if (jcr->run_pool_override) { - pm_strcpy(jcr->pool_source, _("Run Pool override")); + pm_strcpy(jcr->pool_source, _("run pool override")); } /* * Apply any level related Pool selections @@ -626,9 +626,9 @@ void apply_pool_overrides(JCR *jcr) if (jcr->full_pool) { jcr->pool = jcr->full_pool; if (jcr->run_full_pool_override) { - pm_strcpy(jcr->pool_source, _("Run FullPool override")); + pm_strcpy(jcr->pool_source, _("run FullPool override")); } else { - pm_strcpy(jcr->pool_source, _("Job FullPool override")); + pm_strcpy(jcr->pool_source, _("job FullPool override")); } } break; @@ -636,9 +636,9 @@ void apply_pool_overrides(JCR *jcr) if (jcr->inc_pool) { jcr->pool = jcr->inc_pool; if (jcr->run_inc_pool_override) { - pm_strcpy(jcr->pool_source, _("Run IncPool override")); + pm_strcpy(jcr->pool_source, _("run IncPool override")); } else { - pm_strcpy(jcr->pool_source, _("Job IncPool override")); + pm_strcpy(jcr->pool_source, _("job IncPool override")); } } break; @@ -646,9 +646,9 @@ void apply_pool_overrides(JCR *jcr) if (jcr->diff_pool) { jcr->pool = jcr->diff_pool; if (jcr->run_diff_pool_override) { - pm_strcpy(jcr->pool_source, _("Run DiffPool override")); + pm_strcpy(jcr->pool_source, _("run DiffPool override")); } else { - pm_strcpy(jcr->pool_source, _("Job DiffPool override")); + pm_strcpy(jcr->pool_source, _("job DiffPool override")); } } break; @@ -834,9 +834,13 @@ void dird_free_jcr_pointers(JCR *jcr) free_pool_memory(jcr->pool_source); jcr->pool_source = NULL; } - if (jcr->storage_source) { - free_pool_memory(jcr->storage_source); - jcr->storage_source = NULL; + if (jcr->wstore_source) { + free_pool_memory(jcr->wstore_source); + jcr->wstore_source = NULL; + } + if (jcr->rstore_source) { + free_pool_memory(jcr->rstore_source); + jcr->rstore_source = NULL; } if (jcr->stime) { Dmsg0(200, "Free JCR stime\n"); @@ -888,12 +892,24 @@ void dird_free_jcr(JCR *jcr) * or in the Pool record. The Pool record overrides the Job * record. */ -STORE *get_job_storage(JOB *job) +void get_job_storage(USTORE *store, JOB *job, RUN *run) { + if (run && run->pool && run->pool->storage) { + store->store = (STORE *)run->pool->storage->first(); + pm_strcpy(store->store_source, _("run pool override")); + return; + } + if (run && run->storage) { + store->store = run->storage; + pm_strcpy(store->store_source, _("run storage override")); + return; + } if (job->pool->storage) { - return (STORE *)job->pool->storage->first(); + store->store = (STORE *)job->pool->storage->first(); + pm_strcpy(store->store_source, _("job pool storage")); } else { - return (STORE *)job->storage->first(); + store->store = (STORE *)job->storage->first(); + pm_strcpy(store->store_source, _("job storage")); } } @@ -924,16 +940,12 @@ void set_jcr_defaults(JCR *jcr, JOB *job) jcr->pool_source = get_pool_memory(PM_MESSAGE); pm_strcpy(jcr->pool_source, _("unknown source")); } - if (!jcr->storage_source) { - jcr->storage_source = get_pool_memory(PM_MESSAGE); - pm_strcpy(jcr->storage_source, _("unknown source")); - } jcr->JobPriority = job->Priority; /* Copy storage definitions -- deleted in dir_free_jcr above */ if (job->storage) { copy_rwstorage(jcr, job->storage, _("Job resource")); } else { - copy_rwstorage(jcr, job->pool->storage, _("Job resource")); + copy_rwstorage(jcr, job->pool->storage, _("Pool resource")); } jcr->client = job->client; if (!jcr->client_name) { @@ -974,6 +986,7 @@ void set_jcr_defaults(JCR *jcr, JOB *job) jcr->JobLevel = L_NONE; break; default: + jcr->JobLevel = L_FULL; break; } } @@ -984,20 +997,36 @@ void set_jcr_defaults(JCR *jcr, JOB *job) */ void copy_rwstorage(JCR *jcr, alist *storage, const char *where) { - copy_rstorage(jcr, storage, where); - copy_wstorage(jcr, storage, where); + switch(jcr->JobType) { + case JT_RESTORE: + case JT_VERIFY: + case JT_MIGRATE: + copy_rstorage(jcr, storage, where); + break; + default: + copy_wstorage(jcr, storage, where); + break; + } } /* Set storage override */ -void set_rwstorage(JCR *jcr, STORE *store) +void set_rwstorage(JCR *jcr, USTORE *store) { if (!store) { Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n")); return; } - set_rstorage(jcr, store); - set_wstorage(jcr, store); + switch(jcr->JobType) { + case JT_RESTORE: + case JT_VERIFY: + case JT_MIGRATE: + set_rstorage(jcr, store); + break; + default: + set_wstorage(jcr, store); + break; + } } void free_rwstorage(JCR *jcr) @@ -1020,33 +1049,40 @@ void copy_rstorage(JCR *jcr, alist *storage, const char *where) foreach_alist(st, storage) { jcr->rstorage->append(st); } - pm_strcpy(jcr->storage_source, where); - } - if (jcr->rstorage) { - jcr->rstore = (STORE *)jcr->rstorage->first(); + if (!jcr->rstore_source) { + jcr->rstore_source = get_pool_memory(PM_MESSAGE); + } + pm_strcpy(jcr->rstore_source, where); + if (jcr->rstorage) { + jcr->rstore = (STORE *)jcr->rstorage->first(); + } } } /* Set storage override */ -void set_rstorage(JCR *jcr, STORE *store) +void set_rstorage(JCR *jcr, USTORE *store) { STORE *storage; - if (!store) { + if (!store->store) { return; } if (!jcr->rstorage) { jcr->rstorage = New(alist(10, not_owned_by_alist)); } - jcr->rstore = store; + jcr->rstore = store->store; + if (!jcr->rstore_source) { + jcr->rstore_source = get_pool_memory(PM_MESSAGE); + } + pm_strcpy(jcr->rstore_source, store->store_source); foreach_alist(storage, jcr->rstorage) { - if (store == storage) { + if (store->store == storage) { return; } } /* Store not in list, so add it */ - jcr->rstorage->prepend(store); + jcr->rstorage->prepend(store->store); } void free_rstorage(JCR *jcr) @@ -1070,35 +1106,45 @@ void copy_wstorage(JCR *jcr, alist *storage, const char *where) } jcr->wstorage = New(alist(10, not_owned_by_alist)); foreach_alist(st, storage) { + Dmsg1(50, "storage=%s\n", st->name()); jcr->wstorage->append(st); } - pm_strcpy(jcr->storage_source, where); - } - if (jcr->wstorage) { - jcr->wstore = (STORE *)jcr->wstorage->first(); + if (!jcr->wstore_source) { + jcr->wstore_source = get_pool_memory(PM_MESSAGE); + } + pm_strcpy(jcr->wstore_source, where); + if (jcr->wstorage) { + jcr->wstore = (STORE *)jcr->wstorage->first(); + Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source); + } } } /* Set storage override */ -void set_wstorage(JCR *jcr, STORE *store) +void set_wstorage(JCR *jcr, USTORE *store) { STORE *storage; - if (!store) { + if (!store->store) { return; } if (!jcr->wstorage) { jcr->wstorage = New(alist(10, not_owned_by_alist)); } - jcr->wstore = store; + jcr->wstore = store->store; + if (!jcr->wstore_source) { + jcr->wstore_source = get_pool_memory(PM_MESSAGE); + } + pm_strcpy(jcr->wstore_source, store->store_source); + Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source); foreach_alist(storage, jcr->wstorage) { - if (store == storage) { + if (store->store == storage) { return; } } /* Store not in list, so add it */ - jcr->wstorage->prepend(store); + jcr->wstorage->prepend(store->store); } void free_wstorage(JCR *jcr) diff --git a/bacula/src/dird/jobq.c b/bacula/src/dird/jobq.c index 2c02aa5e77..6246fcdb5c 100755 --- a/bacula/src/dird/jobq.c +++ b/bacula/src/dird/jobq.c @@ -702,9 +702,12 @@ static bool acquire_resources(JCR *jcr) } if (jcr->wstore) { + Dmsg1(200, "Wstore=%s\n", jcr->wstore->name()); if (jcr->rstore == jcr->wstore) { /* deadlock */ jcr->rstore->NumConcurrentJobs = 0; /* back out rstore */ - Jmsg(jcr, M_FATAL, 0, _("Job canceled. Attempt to read and write same device.\n")); + Jmsg(jcr, M_FATAL, 0, _("Job canceled. Attempt to read and write same device.\n" + " Read storage \"%s\" (From %s) -- Write storage \"%s\" (From %s)\n"), + jcr->rstore->name(), jcr->rstore_source, jcr->wstore->name(), jcr->wstore_source); set_jcr_job_status(jcr, JS_Canceled); return false; } diff --git a/bacula/src/dird/migrate.c b/bacula/src/dird/migrate.c index c8e90f0d20..6f660a6b59 100644 --- a/bacula/src/dird/migrate.c +++ b/bacula/src/dird/migrate.c @@ -66,10 +66,37 @@ static int get_next_dbid_from_list(char **p, DBId_t *DBId); /* * Called here before the job is run to do the job - * specific setup. + * specific setup. Note, one of the important things to + * complete in this init code is to make the definitive + * choice of input and output storage devices. This is + * because immediately after the init, the job is queued + * in the jobq.c code, and it checks that all the resources + * (storage resources in particular) are available, so these + * must all be properly defined. + * + * previous_jr refers to the job DB record of the Job that is + * going to be migrated. + * prev_job refers to the job resource of the Job that is + * going to be migrated. + * jcr is the jcr for the current "migration" job. It is a + * control job that is put in the DB as a migration job, which + * means that this job migrated a previous job to a new job. + * No Volume or File data is associated with this control + * job. + * mig_jcr refers to the newly migrated job that is run by + * the current jcr. It is a backup job that moves (migrates) the + * data written for the previous_jr into the new pool. This + * job (mig_jcr) becomes the new backup job that replaces + * the original backup job. */ bool do_migration_init(JCR *jcr) { + POOL_DBR pr; + POOL *pool; + char ed1[100]; + JOB *job, *prev_job; + JCR *mig_jcr; /* newly migrated job */ + /* If we find a job or jobs to migrate it is previous_jr.JobId */ if (!get_job_to_migrate(jcr)) { return false; @@ -97,7 +124,7 @@ bool do_migration_init(JCR *jcr) return false; } - /* If pool storage specified, use it instead of job storage */ + /* If pool storage specified, use it instead of job storage */ copy_wstorage(jcr, jcr->pool->storage, _("Pool resource")); if (jcr->wstorage->size() == 0) { @@ -106,40 +133,7 @@ bool do_migration_init(JCR *jcr) } create_restore_bootstrap_file(jcr); - return true; -} - -/* - * Do a Migration of a previous job - * - * Returns: false on failure - * true on success - */ -bool do_migration(JCR *jcr) -{ - POOL_DBR pr; - POOL *pool; - char ed1[100]; - BSOCK *sd; - JOB *job, *prev_job; - JCR *mig_jcr; /* newly migrated job */ - /* - * previous_jr refers to the job DB record of the Job that is - * going to be migrated. - * prev_job refers to the job resource of the Job that is - * going to be migrated. - * jcr is the jcr for the current "migration" job. It is a - * control job that is put in the DB as a migration job, which - * means that this job migrated a previous job to a new job. - * No Volume or File data is associated with this control - * job. - * mig_jcr refers to the newly migrated job that is run by - * the current jcr. It is a backup job that moves (migrates) the - * data written for the previous_jr into the new pool. This - * job (mig_jcr) becomes the new backup job that replaces - * the original backup job. - */ if (jcr->previous_jr.JobId == 0 || jcr->ExpectedFiles == 0) { set_jcr_job_status(jcr, JS_Terminated); Dmsg1(dbglevel, "JobId=%d expected files == 0\n", (int)jcr->JobId); @@ -148,7 +142,6 @@ bool do_migration(JCR *jcr) } else { Jmsg(jcr, M_INFO, 0, _("Previous Job has no data to migrate.\n")); } - migration_cleanup(jcr, jcr->JobStatus); return true; /* no work */ } @@ -248,6 +241,23 @@ bool do_migration(JCR *jcr) /* If pool storage specified, use it instead of job storage for backup */ copy_wstorage(jcr, jcr->pool->storage, _("Next pool resource")); + + return true; +} + +/* + * Do a Migration of a previous job + * + * Returns: false on failure + * true on success + */ +bool do_migration(JCR *jcr) +{ + char ed1[100]; + BSOCK *sd; + JCR *mig_jcr = jcr->mig_jcr; /* newly migrated job */ + + /* Print Job Start message */ Jmsg(jcr, M_INFO, 0, _("Start Migration JobId %s, Job=%s\n"), edit_uint64(jcr->JobId, ed1), jcr->Job); @@ -1078,7 +1088,8 @@ void migration_cleanup(JCR *jcr, int TermCode) " Client: %s\n" " FileSet: \"%s\" %s\n" " Pool: \"%s\" (From %s)\n" -" Storage: \"%s\" (From %s)\n" +" Read Storage: \"%s\" (From %s_\n" +" Write Storage: \"%s\" (From %s)\n" " Start time: %s\n" " End time: %s\n" " Elapsed time: %s\n" @@ -1104,7 +1115,8 @@ void migration_cleanup(JCR *jcr, int TermCode) jcr->client->name(), jcr->fileset->name(), jcr->FSCreateTime, jcr->pool->name(), jcr->pool_source, - jcr->wstore->name(), jcr->storage_source, + jcr->rstore->name(), jcr->rstore_source, + jcr->wstore->name(), jcr->wstore_source, sdt, edt, edit_utime(RunTime, elapsed, sizeof(elapsed)), diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index f83152fcca..3980b3af4d 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -84,10 +84,10 @@ bool connect_to_storage_daemon(JCR *jcr, int retry_interval, } /* If there is a write storage use it */ - if (jcr->wstorage) { - store = (STORE *)jcr->wstorage->first(); + if (jcr->wstore) { + store = jcr->wstore; } else { - store = (STORE *)jcr->rstorage->first(); + store = jcr->rstore; } /* @@ -216,7 +216,8 @@ bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore) /* Do read side of storage daemon */ if (ok && rstore) { foreach_alist(storage, rstore) { - pm_strcpy(store_name, storage->hdr.name); + Dmsg1(100, "Rstore=%s\n", storage->name()); + pm_strcpy(store_name, storage->name()); bash_spaces(store_name); pm_strcpy(media_type, storage->media_type); bash_spaces(media_type); @@ -246,7 +247,8 @@ bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore) /* Do write side of storage daemon */ if (ok && wstore) { foreach_alist(storage, wstore) { - pm_strcpy(store_name, storage->hdr.name); + Dmsg1(100, "Wstore=%s\n", storage->name()); + pm_strcpy(store_name, storage->name()); bash_spaces(store_name); pm_strcpy(media_type, storage->media_type); bash_spaces(media_type); diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 1c48fc9ab1..25dbfa3db4 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -111,16 +111,16 @@ extern DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name); extern void apply_pool_overrides(JCR *jcr); extern JobId_t run_job(JCR *jcr); extern bool cancel_job(UAContext *ua, JCR *jcr); -extern STORE *get_job_storage(JOB *job); +extern void get_job_storage(USTORE *store, JOB *job, RUN *run); extern void init_jcr_job_record(JCR *jcr); extern void copy_rwstorage(JCR *jcr, alist *storage, const char *where); -extern void set_rwstorage(JCR *jcr, STORE *store); +extern void set_rwstorage(JCR *jcr, USTORE *store); extern void free_rwstorage(JCR *jcr); extern void copy_wstorage(JCR *jcr, alist *storage, const char *where); -extern void set_wstorage(JCR *jcr, STORE *store); +extern void set_wstorage(JCR *jcr, USTORE *store); extern void free_wstorage(JCR *jcr); extern void copy_rstorage(JCR *jcr, alist *storage, const char *where); -extern void set_rstorage(JCR *jcr, STORE *store); +extern void set_rstorage(JCR *jcr, USTORE *store); extern void free_rstorage(JCR *jcr); extern bool setup_job(JCR *jcr); extern void create_clones(JCR *jcr); diff --git a/bacula/src/dird/scheduler.c b/bacula/src/dird/scheduler.c index 6b9550442f..f06e2378a0 100644 --- a/bacula/src/dird/scheduler.c +++ b/bacula/src/dird/scheduler.c @@ -218,7 +218,10 @@ again: jcr->run_diff_pool_override = true; } if (run->storage) { - set_rwstorage(jcr, run->storage); /* override storage */ + USTORE store; + store.store = run->storage; + pm_strcpy(store.store_source, _("run override")); + set_rwstorage(jcr, &store); /* override storage */ } if (run->msgs) { jcr->messages = run->msgs; /* override messages */ diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index a019c3be6c..8e6bb272d9 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -684,8 +684,11 @@ static void do_storage_setdebug(UAContext *ua, STORE *store, int level, int trac { BSOCK *sd; JCR *jcr = ua->jcr; - - set_wstorage(jcr, store); + USTORE lstore; + + lstore.store = store; + pm_strcpy(lstore.store_source, _("unknown source")); + set_wstorage(jcr, &lstore); /* Try connecting for up to 15 seconds */ bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d\n"), store->name(), store->address, store->SDport); @@ -1309,7 +1312,7 @@ static int delete_pool(UAContext *ua) static void do_mount_cmd(UAContext *ua, const char *command) { - STORE *store; + USTORE store; BSOCK *sd; JCR *jcr = ua->jcr; char dev_name[MAX_NAME_LENGTH]; @@ -1321,25 +1324,26 @@ static void do_mount_cmd(UAContext *ua, const char *command) } Dmsg2(120, "%s: %s\n", command, ua->UA_sock->msg); - store = get_storage_resource(ua, true/*arg is storage*/); - if (!store) { + store.store = get_storage_resource(ua, true/*arg is storage*/); + pm_strcpy(store.store_source, _("unknown source")); + if (!store.store) { return; } - set_wstorage(jcr, store); - drive = get_storage_drive(ua, store); + set_wstorage(jcr, &store); + drive = get_storage_drive(ua, store.store); if (strcmp(command, "mount") == 0) { - slot = get_storage_slot(ua, store); + slot = get_storage_slot(ua, store.store); } Dmsg3(120, "Found storage, MediaType=%s DevName=%s drive=%d\n", - store->media_type, store->dev_name(), drive); + store.store->media_type, store.store->dev_name(), drive); if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) { bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); return; } sd = jcr->store_bsock; - bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); + bstrncpy(dev_name, store.store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); if (slot > 0) { bnet_fsend(sd, "%s %s drive=%d slot=%d", command, dev_name, drive, slot); diff --git a/bacula/src/dird/ua_dotcmds.c b/bacula/src/dird/ua_dotcmds.c index 2552cd2f70..3d0d9bb53a 100644 --- a/bacula/src/dird/ua_dotcmds.c +++ b/bacula/src/dird/ua_dotcmds.c @@ -291,13 +291,13 @@ static int defaultscmd(UAContext *ua, const char *cmd) } job = (JOB *)GetResWithName(R_JOB, ua->argv[1]); if (job) { - STORE *store; + USTORE store; bsendmsg(ua, "job=%s", job->hdr.name); bsendmsg(ua, "pool=%s", job->pool->hdr.name); bsendmsg(ua, "messages=%s", job->messages->hdr.name); bsendmsg(ua, "client=%s", job->client->hdr.name); - store = get_job_storage(job); - bsendmsg(ua, "storage=%s", store->hdr.name); + get_job_storage(&store, job, NULL); + bsendmsg(ua, "storage=%s", store.store->name()); bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:""); bsendmsg(ua, "level=%s", level_to_str(job->JobLevel)); bsendmsg(ua, "type=%s", job_type_to_str(job->JobType)); diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index cfbb7a6c89..fbd26f8e0b 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -162,7 +162,7 @@ bail_out: */ void update_slots(UAContext *ua) { - STORE *store; + USTORE store; vol_list_t *vl, *vol_list = NULL; MEDIA_DBR mr; char *slot_list; @@ -177,12 +177,13 @@ void update_slots(UAContext *ua) if (!open_db(ua)) { return; } - store = get_storage_resource(ua, true/*arg is storage*/); - if (!store) { + store.store = get_storage_resource(ua, true/*arg is storage*/); + if (!store.store) { return; } - set_wstorage(ua->jcr, store); - drive = get_storage_drive(ua, store); + pm_strcpy(store.store_source, _("command line")); + set_wstorage(ua->jcr, &store); + drive = get_storage_drive(ua, store.store); scan = find_arg(ua, NT_("scan")) >= 0; if ((i=find_arg_with_value(ua, NT_("Enabled"))) >= 0) { @@ -242,7 +243,7 @@ void update_slots(UAContext *ua) memset(&mr, 0, sizeof(mr)); mr.Slot = vl->Slot; mr.InChanger = 1; - mr.StorageId = store->StorageId; + mr.StorageId = store.store->StorageId; /* Set InChanger to zero for this Slot */ db_lock(ua->db); db_make_inchanger_unique(ua->jcr, ua->db, &mr); @@ -256,10 +257,10 @@ void update_slots(UAContext *ua) bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); db_lock(ua->db); if (db_get_media_record(ua->jcr, ua->db, &mr)) { - if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store->StorageId) { + if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store.store->StorageId) { mr.Slot = vl->Slot; mr.InChanger = 1; - mr.StorageId = store->StorageId; + mr.StorageId = store.store->StorageId; if (have_enabled) { mr.Enabled = Enabled; } @@ -284,7 +285,7 @@ void update_slots(UAContext *ua) } memset(&mr, 0, sizeof(mr)); mr.InChanger = 1; - mr.StorageId = store->StorageId; + mr.StorageId = store.store->StorageId; db_lock(ua->db); for (int i=1; i <= max_slots; i++) { if (slot_list[i]) { @@ -310,7 +311,7 @@ bail_out: */ static int do_label(UAContext *ua, const char *cmd, int relabel) { - STORE *store; + USTORE store; BSOCK *sd; char dev_name[MAX_NAME_LENGTH]; MEDIA_DBR mr, omr; @@ -341,12 +342,13 @@ static int do_label(UAContext *ua, const char *cmd, int relabel) label_barcodes = true; } - store = get_storage_resource(ua, true/*use default*/); - if (!store) { + store.store = get_storage_resource(ua, true/*use default*/); + if (!store.store) { return 1; } - set_wstorage(ua->jcr, store); - drive = get_storage_drive(ua, store); + pm_strcpy(store.store_source, _("command line")); + set_wstorage(ua->jcr, &store); + drive = get_storage_drive(ua, store.store); if (label_barcodes) { label_from_barcodes(ua, drive); @@ -416,16 +418,16 @@ checkName: if (i >= 0) { mr.Slot = atoi(ua->argv[i]); mr.InChanger = 1; /* assumed if we are labeling it */ - } else if (store->autochanger) { + } else if (store.store->autochanger) { if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) { return 1; } mr.Slot = ua->pint32_val; mr.InChanger = 1; /* assumed if we are labeling it */ } - mr.StorageId = store->StorageId; + mr.StorageId = store.store->StorageId; - bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType)); + bstrncpy(mr.MediaType, store.store->media_type, sizeof(mr.MediaType)); /* Must select Pool if not already done */ if (pr.PoolId == 0) { @@ -455,7 +457,7 @@ checkName: } } if (ua->automount) { - bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); + bstrncpy(dev_name, store.store->dev_name(), sizeof(dev_name)); bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name); bash_spaces(dev_name); bnet_fsend(sd, "mount %s drive=%d", dev_name, drive); diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index ce329205d5..2e2dcf61e0 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -448,6 +448,7 @@ static bool list_nextvol(UAContext *ua, int ndays) JOB *job; JCR *jcr = ua->jcr; POOL *pool; + USTORE store; RUN *run; time_t runtime; bool found = false; @@ -480,12 +481,8 @@ static bool list_nextvol(UAContext *ua, int ndays) bstrncpy(pr.Name, "*UnknownPool*", sizeof(pr.Name)); } mr.PoolId = jcr->jr.PoolId; - if (run->storage) { - jcr->wstore = run->storage; - } else { - jcr->wstore = get_job_storage(job); - } - mr.StorageId = jcr->wstore->StorageId; + get_job_storage(&store, job, run); + mr.StorageId = store.store->StorageId; if (!find_next_volume_for_append(jcr, &mr, 1, false/*no create*/)) { bsendmsg(ua, _("Could not find next Volume for Job %s (%s, %s).\n"), job->hdr.name, pr.Name, level_to_str(run->level)); diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index ddc82bd206..bfa2e2844f 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -70,7 +70,7 @@ int run_cmd(UAContext *ua, const char *cmd) JOB *job = NULL; JOB *verify_job = NULL; JOB *previous_job = NULL; - STORE *store = NULL; + USTORE store; CLIENT *client = NULL; FILESET *fileset = NULL; POOL *pool = NULL; @@ -345,24 +345,26 @@ int run_cmd(UAContext *ua, const char *cmd) } if (store_name) { - store = (STORE *)GetResWithName(R_STORAGE, store_name); - if (!store) { + store.store = (STORE *)GetResWithName(R_STORAGE, store_name); + pm_strcpy(store.store_source, _("command line")); + if (!store.store) { if (*store_name != 0) { bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name); } - store = select_storage_resource(ua); + store.store = select_storage_resource(ua); + pm_strcpy(store.store_source, _("user selection")); } } else { - store = get_job_storage(job); /* use default */ + get_job_storage(&store, job, NULL); /* use default */ } - if (!store) { + if (!store.store) { return 1; - } else if (!acl_access_ok(ua, Storage_ACL, store->name())) { + } else if (!acl_access_ok(ua, Storage_ACL, store.store->name())) { bsendmsg(ua, _("No authorization. Storage \"%s\".\n"), - store->name()); + store.store->name()); return 0; } - Dmsg1(800, "Using storage=%s\n", store->name()); + Dmsg1(800, "Using storage=%s\n", store.store->name()); if (pool_name) { pool = (POOL *)GetResWithName(R_POOL, pool_name); @@ -451,7 +453,7 @@ int run_cmd(UAContext *ua, const char *cmd) jcr->verify_job = verify_job; jcr->previous_job = previous_job; - set_rwstorage(jcr, store); + set_rwstorage(jcr, &store); jcr->client = client; jcr->fileset = fileset; jcr->pool = pool; @@ -800,9 +802,10 @@ try_again: goto try_again; case 1: /* Storage */ - store = select_storage_resource(ua); - if (store) { - set_rwstorage(jcr, store); + store.store = select_storage_resource(ua); + if (store.store) { + pm_strcpy(store.store_source, _("user selection")); + set_rwstorage(jcr, &store); goto try_again; } break; diff --git a/bacula/src/dird/ua_status.c b/bacula/src/dird/ua_status.c index 89afc6fb25..fc1c2d889a 100644 --- a/bacula/src/dird/ua_status.c +++ b/bacula/src/dird/ua_status.c @@ -288,8 +288,11 @@ static void do_director_status(UAContext *ua) static void do_storage_status(UAContext *ua, STORE *store) { BSOCK *sd; + USTORE lstore; - set_wstorage(ua->jcr, store); + lstore.store = store; + pm_strcpy(lstore.store_source, _("unknown source")); + set_wstorage(ua->jcr, &lstore); /* Try connecting for up to 15 seconds */ bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d\n"), store->name(), store->address, store->SDport); @@ -445,7 +448,6 @@ static void list_scheduled_jobs(UAContext *ua) time_t runtime; RUN *run; JOB *job; - STORE* store; int level, num_jobs = 0; int priority; bool hdr_printed = false; @@ -472,6 +474,7 @@ static void list_scheduled_jobs(UAContext *ua) continue; } for (run=NULL; (run = find_next_run(run, job, runtime, days)); ) { + USTORE store; level = job->JobLevel; if (run->level) { level = run->level; @@ -480,11 +483,6 @@ static void list_scheduled_jobs(UAContext *ua) if (run->Priority) { priority = run->Priority; } - if (run->storage) { - store = run->storage; - } else { - store = get_job_storage(job); - } if (!hdr_printed) { prt_runhdr(ua); hdr_printed = true; @@ -495,7 +493,8 @@ static void list_scheduled_jobs(UAContext *ua) sp->priority = priority; sp->runtime = runtime; sp->pool = run->pool; - sp->store = store; + get_job_storage(&store, job, run); + sp->store = store.store; sched.binary_insert_multiple(sp, my_compare); num_jobs++; } diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 8d15a91ef9..4f53c2baaa 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -236,7 +236,8 @@ public: }; POOLMEM *client_uname; /* client uname */ POOLMEM *pool_source; /* Where pool came from */ - POOLMEM *storage_source; /* Where storage came from */ + POOLMEM *rstore_source; /* Where read storage came from */ + POOLMEM *wstore_source; /* Where write storage came from */ int replace; /* Replace option */ int NumVols; /* Number of Volume used in pool */ int reschedule_count; /* Number of times rescheduled */ diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 8c7f3de857..c59d6e8dac 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -92,7 +92,6 @@ static bool my_mount_next_read_volume(DCR *dcr); static void scan_blocks(); static void set_volume_name(const char *VolName, int volnum); static void rawfill_cmd(); -static void bfill_cmd(); static bool open_the_device(); static void autochangercmd(); static void do_unfill(); @@ -2522,60 +2521,12 @@ static void rawfill_cmd() } -/* - * Fill a tape using Bacula block writes - */ -static void bfill_cmd() -{ - DEV_BLOCK *block = dcr->block; - uint32_t block_num = 0; - uint32_t *p; - int my_errno; - int fd; - uint32_t i; - - fd = open("/dev/urandom", O_RDONLY); - if (fd) { - read(fd, block->buf, block->buf_len); - close(fd); - } else { - uint32_t *p = (uint32_t *)block->buf; - srandom(time(NULL)); - for (i=0; ibuf_len/sizeof(uint32_t); i++) { - p[i] = random(); - } - } - p = (uint32_t *)block->buf; - Pmsg1(0, _("Begin writing Bacula blocks of %u bytes.\n"), block->buf_len); - for ( ;; ) { - *p = block_num; - block->binbuf = block->buf_len; - block->bufp = block->buf + block->binbuf; - if (!write_block_to_dev(dcr)) { - break; - } - if ((block_num++ % 100) == 0) { - printf("+"); - fflush(stdout); - } - p[0] += p[13]; - for (i=1; i<(block->buf_len/sizeof(uint32_t)-1); i++) { - p[i] += p[i-1]; - } - } - my_errno = errno; - printf("\n"); - printf(_("Write failed at block %u.\n"), block_num); - weofcmd(); -} - struct cmdstruct { const char *key; void (*func)(); const char *help; }; static struct cmdstruct commands[] = { {NT_("autochanger"),autochangercmd, _("test autochanger")}, {NT_("bsf"), bsfcmd, _("backspace file")}, {NT_("bsr"), bsrcmd, _("backspace record")}, - {NT_("bfill"), bfill_cmd, _("fill tape using Bacula writes")}, {NT_("cap"), capcmd, _("list device capabilities")}, {NT_("clear"), clearcmd, _("clear tape errors")}, {NT_("eod"), eodcmd, _("go to end of Bacula data for append")}, diff --git a/bacula/src/version.h b/bacula/src/version.h index ff576be27a..5346f4f2a8 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,9 @@ #undef VERSION #define VERSION "1.39.29" -#define BDATE "20 November 2006" -#define LSMDATE "20Nov06" +#define BDATE "24 November 2006" +#define LSMDATE "24Nov06" + #define PROG_COPYRIGHT "Copyright (C) 2000-%s Free Software Foundation Europe e.V.\n" #define BYEAR "2006" /* year for copyright messages in progs */ diff --git a/bacula/technotes-1.39 b/bacula/technotes-1.39 index b19a25f78e..933422cfe2 100644 --- a/bacula/technotes-1.39 +++ b/bacula/technotes-1.39 @@ -2,6 +2,18 @@ General: 22Nov06 +kes Separate read/write source strings to keep track of where + storage devices are used in a job. +kes Implement a new method of keeping track of which storage + device is used in a Job. USTORE keeps both a pointer to the + resource and to the source string. +kes Modify all code to use new storage set subroutines in job.c +kes Modify migrate.c so that the definitive selection of the storage + resource is done in the do_migration_init() routine prior to + the job going into the job queue. This permits accurate + deadlock detection (same read and write storage resource). +kes Remove bfill from btape (I think it was a left over stub). +22Nov06 kes Make sure that the storage for a job is pulled first from the Pool and if not from the Job. kes Ensure that either the Pool or the Job specifies a Storage