From ef440f6ff950294887e1e61e8304aba12de37996 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 13 Dec 2006 19:42:12 +0000 Subject: [PATCH] kes Implement code that should properly set that a job was migrated, if the migration was successful even if there were no file to migrate. kes Apply Richard's patch to fix building or filed/restore.c without OpenSSL support. kes Ensure that at least one block is written by the SD even if the FD dies or fails -- should fix bug #728. kes Convert stored/record.c ASSERT into a soft fail if the length of a record is too insanely long. This should fix bug #??? git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3798 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 3 ++- bacula/projects | 26 ++++++++++++++++++++++++++ bacula/src/dird/migrate.c | 6 ++++++ bacula/src/filed/restore.c | 7 +++++-- bacula/src/stored/append.c | 4 ++-- bacula/src/stored/bls.c | 4 ++-- bacula/src/stored/btape.c | 8 ++++---- bacula/src/stored/label.c | 2 +- bacula/src/stored/protos.h | 2 +- bacula/src/stored/read_record.c | 4 ++-- bacula/src/stored/record.c | 17 ++++++++++++++--- bacula/technotes-1.39 | 13 ++++++++++++- 12 files changed, 77 insertions(+), 19 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 9729fb8722..8a541ed63c 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -61,6 +61,8 @@ Priority: For 1.39: +- Fix hardlinked immutable files when linking a second file, the + immutable flag must be removed prior to trying to link it. - Implement Python event for backing up/restoring a file. - Change dbcheck to tell users to use native tools for fixing broken databases, and to ensure they have the proper indexes. @@ -1750,4 +1752,3 @@ Block Position: 0 example conf files (especially in the manual). - Fix prog copyright (SD) all other files. - Document need for UTF-8 format - diff --git a/bacula/projects b/bacula/projects index 4dd5f76505..723f0593d0 100644 --- a/bacula/projects +++ b/bacula/projects @@ -1193,3 +1193,29 @@ Notes: functionality is the ultimate goal. Assistance with either code or testing would be fantastic. + +Item 1: On the bconsole "restore" command line, implement separate + option for specifying the host to restore from, and the + host to restore to. + + Date: 11 December 2006 + + Origin: Discussion on Bacula-users entitled 'Scripted restores to + different clients', December 2006 + + Status: New feature request + + What: While using bconsole interactively, you can specify the client + that a backup job is to be restored for, and then you can + specify later a different client to send the restored files + back to. However, using the 'restore' command with all options + on the command line, this cannot be done, due to the ambiguous + 'client' parameter. Additionally, this parameter means different + things depending on if it's specified on the command line or + afterwards, in the Modify Job screens. + + Why: This feature would enable restore jobs to be more completely + automated, for example by a web or GUI front-end. + + Notes: client can also be implied by specifying the jobid on the command + line diff --git a/bacula/src/dird/migrate.c b/bacula/src/dird/migrate.c index ee827237f1..991b581312 100644 --- a/bacula/src/dird/migrate.c +++ b/bacula/src/dird/migrate.c @@ -1090,6 +1090,12 @@ void migration_cleanup(JCR *jcr, int TermCode) break; } } else { + if (jcr->previous_jr.JobId != 0) { + /* Mark previous job as migrated */ + Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s", + (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, ec1)); + db_sql_query(jcr->db, query.c_str(), NULL, NULL); + } term_msg = _("%s -- no files to migrate"); } diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 142bd40a39..846efa4e22 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -188,16 +188,19 @@ void do_restore(JCR *jcr) jcr->compress_buf_size = compress_buf_size; } + cipher_ctx.cipher = NULL; + alt_cipher_ctx.cipher = NULL; if (have_crypto) { - cipher_ctx.cipher = NULL; cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE); cipher_ctx.buf_len = 0; cipher_ctx.packet_len = 0; - cipher_ctx.cipher = NULL; alt_cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE); alt_cipher_ctx.buf_len = 0; alt_cipher_ctx.packet_len = 0; + } else { + cipher_ctx.buf = NULL; + alt_cipher_ctx.buf = NULL; } /* diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index 1e5b5f91ff..7985e594e3 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -278,10 +278,10 @@ bool do_append_data(JCR *jcr) Dmsg1(200, "Write EOS label JobStatus=%c\n", jcr->JobStatus); /* - * If !OK, check if we can still write. This may not be the case + * Check if we can still write. This may not be the case * if we are at the end of the tape or we got a fatal I/O error. */ - if (ok || dev->can_write()) { + if (dev->can_write()) { if (!write_session_label(dcr, EOS_LABEL)) { Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"), dev->bstrerror()); diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index caebdc9b0e..94cc2bf2bd 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -284,7 +284,7 @@ static void do_blocks(char *infname) DEV_RECORD *record; record = new_record(); read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK); - read_record_from_block(block, record); + read_record_from_block(dcr, block, record); get_session_record(dev, record, &sessrec); free_record(record); Jmsg(jcr, M_INFO, 0, _("Mounted Volume \"%s\".\n"), dcr->VolumeName); @@ -312,7 +312,7 @@ static void do_blocks(char *infname) block->BlockNumber, block->block_len, block->BlockVer, block->VolSessionId, block->VolSessionTime); if (verbose == 1) { - read_record_from_block(block, rec); + read_record_from_block(dcr, block, rec); Pmsg9(-1, _("File:blk=%u:%u blk_num=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n"), dev->file, dev->block_num, block->BlockNumber, block->block_len, diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 4c7a7c5bbc..2f64288fb6 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -751,7 +751,7 @@ static int re_read_block_test() goto bail_out; } memset(rec->data, 0, rec->data_len); - if (!read_record_from_block(block, rec)) { + if (!read_record_from_block(dcr, block, rec)) { berrno be; Pmsg1(0, _("Read block failed! ERR=%s\n"), be.strerror(dev->dev_errno)); goto bail_out; @@ -863,7 +863,7 @@ read_again: goto bail_out; } memset(rec->data, 0, rec->data_len); - if (!read_record_from_block(block, rec)) { + if (!read_record_from_block(dcr, block, rec)) { berrno be; Pmsg2(0, _("Read record failed. Block %d! ERR=%s\n"), i, be.strerror(dev->dev_errno)); goto bail_out; @@ -1030,7 +1030,7 @@ read_again: goto bail_out; } memset(rec->data, 0, rec->data_len); - if (!read_record_from_block(block, rec)) { + if (!read_record_from_block(dcr, block, rec)) { berrno be; Pmsg1(0, _("Read record failed! ERR=%s\n"), be.strerror(dev->dev_errno)); goto bail_out; @@ -1773,7 +1773,7 @@ static void scan_blocks() block->VolSessionId, block->VolSessionTime); if (verbose == 1) { DEV_RECORD *rec = new_record(); - read_record_from_block(block, rec); + read_record_from_block(dcr, block, rec); Pmsg8(-1, _("Blk_block: %u dev_blk=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n"), block->BlockNumber, dev->block_num, block->block_len, FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, rec->VolSessionTime, diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index d997f23461..26db7b941d 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -153,7 +153,7 @@ int read_dev_volume_label(DCR *dcr) "labeled Volume, because: ERR=%s"), NPRT(VolName), dev->print_name(), dev->print_errmsg()); Dmsg1(30, "%s", jcr->errmsg); - } else if (!read_record_from_block(block, record)) { + } else if (!read_record_from_block(dcr, block, record)) { Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n")); Dmsg1(30, "%s", jcr->errmsg); } else if (!unser_volume_label(dev, record)) { diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 8227166610..2e3bbdf3a8 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -198,7 +198,7 @@ const char *FI_to_ascii(char *buf, int fi); const char *stream_to_ascii(char *buf, int stream, int fi); bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec); DEV_RECORD *new_record(); void free_record(DEV_RECORD *rec); void empty_record(DEV_RECORD *rec); diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c index cc555c4d24..7dfd412ecd 100644 --- a/bacula/src/stored/read_record.c +++ b/bacula/src/stored/read_record.c @@ -112,7 +112,7 @@ bool read_records(DCR *dcr, * most likely reading the previous record. */ read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK); - read_record_from_block(block, trec); + read_record_from_block(dcr, block, trec); handle_session_record(dev, trec, &sessrec); ok = record_cb(dcr, trec); free_record(trec); @@ -188,7 +188,7 @@ bool read_records(DCR *dcr, rec->state = 0; Dmsg1(dbglvl, "Block %s empty\n", is_block_empty(rec)?"is":"NOT"); for (rec->state=0; ok && !is_block_empty(rec); ) { - if (!read_record_from_block(block, rec)) { + if (!read_record_from_block(dcr, block, rec)) { Dmsg3(400, "!read-break. state=%s blk=%d rem=%d\n", rec_state_to_str(rec), block->BlockNumber, rec->remainder); break; diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index f5827f2afe..1fd96ca2dd 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -426,7 +426,7 @@ bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec) * routine may have to be called again with a new * block if the entire record was not read. */ -bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) +bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec) { ser_declare; uint32_t remlen; @@ -538,7 +538,18 @@ bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) return false; } - ASSERT(data_bytes < MAX_BLOCK_LENGTH); /* temp sanity check */ + /* Sanity check */ + if (data_bytes >= MAX_BLOCK_LENGTH) { + /* + * Something is wrong, force read of next block, abort + * continuing with this block. + */ + rec->state |= (REC_NO_HEADER | REC_BLOCK_EMPTY); + empty_block(block); + Jmsg2(dcr->jcr, M_WARNING, 0, _("Sanity check failed. maxlen=%d datalen=%d. Block discarded.\n"), + MAX_BLOCK_LENGTH, data_bytes); + return false; + } rec->data = check_pool_memory_size(rec->data, rec->data_len+data_bytes); @@ -565,7 +576,7 @@ bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) rec->remainder = 1; /* partial record transferred */ Dmsg1(450, "read_record_block: partial xfered=%d\n", rec->data_len); rec->state |= (REC_PARTIAL_RECORD | REC_BLOCK_EMPTY); - return 1; + return true; } rec->remainder = 0; Dmsg4(450, "Rtn full rd_rec_blk FI=%s SessId=%d Strm=%s len=%d\n", diff --git a/bacula/technotes-1.39 b/bacula/technotes-1.39 index 2adab9c47b..c98ffb5303 100644 --- a/bacula/technotes-1.39 +++ b/bacula/technotes-1.39 @@ -1,8 +1,19 @@ Technical notes on version 1.39 General: +13Dec06 +kes Implement code that should properly set that a job was migrated, + if the migration was successful even if there were no file to + migrate. +kes Apply Richard's patch to fix building or filed/restore.c without + OpenSSL support. +kes Ensure that at least one block is written by the SD even if the + FD dies or fails -- should fix bug #728. +kes Convert stored/record.c ASSERT into a soft fail if the length of + a record is too insanely long. This should fix bug #??? 12Dec06 - +kes Fix automatic labeling of File volumes, which was broken by new + removable device code. 10Dec06 kes Remove typedef uLong for HP in baconfig.h. It broke things. lf Fix job byte reporting -- the digest code runs in verify.c and -- 2.39.2