From: Eric Bollengier Date: Thu, 18 Dec 2008 19:56:23 +0000 (+0000) Subject: ebl Replace File:Block in BSR by Address to fix #1190 X-Git-Tag: Release-3.0.0~453 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6a6cd1ca8ce3f8932f9383e7d1bb0102f199010b;p=bacula%2Fbacula ebl Replace File:Block in BSR by Address to fix #1190 git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@8190 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 2d3b624264..563503652c 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -844,6 +844,8 @@ struct VOL_PARAMS { uint32_t StartBlock; /* start block on tape */ uint32_t EndBlock; /* last block */ int32_t Slot; /* Slot */ + uint64_t StartAddr; /* Start address */ + uint64_t EndAddr; /* End address */ // uint32_t Copy; /* identical copy */ // uint32_t Stripe; /* RAIT strip number */ }; diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index 82602d5eef..16e28644ec 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -463,6 +463,8 @@ int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS Vols[i].EndFile = str_to_uint64(row[5]); Vols[i].StartBlock = str_to_uint64(row[6]); Vols[i].EndBlock = str_to_uint64(row[7]); + Vols[i].StartAddr = (((uint64_t)Vols[i].StartFile)<<32) | Vols[i].StartBlock; + Vols[i].EndAddr = (((uint64_t)Vols[i].EndFile)<<32) | Vols[i].EndBlock; // Vols[i].Copy = str_to_uint64(row[8]); Vols[i].Slot = str_to_uint64(row[9]); StorageId = str_to_uint64(row[10]); diff --git a/bacula/src/dird/bsr.c b/bacula/src/dird/bsr.c index fe38277f28..b3081a6e73 100644 --- a/bacula/src/dird/bsr.c +++ b/bacula/src/dird/bsr.c @@ -325,6 +325,7 @@ void display_bsr_info(UAContext *ua, RESTORE_CTX &rx) */ static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd) { + char ed1[50], ed2[50]; uint32_t count = 0; uint32_t total_count = 0; uint32_t LastIndex = 0; @@ -362,18 +363,20 @@ static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd) } fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); - if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { - fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); - } else { - fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, - bsr->VolParams[i].EndFile); - } - if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { - fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock); - } else { - fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, - bsr->VolParams[i].EndBlock); - } +// if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { +// fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); +// } else { +// fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, +// bsr->VolParams[i].EndFile); +// } +// if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { +// fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock); +// } else { +// fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, +// bsr->VolParams[i].EndBlock); +// } + fprintf(fd, "VolAddr=%s-%s\n", edit_uint64(bsr->VolParams[i].StartAddr, ed1), + edit_uint64(bsr->VolParams[i].EndAddr, ed2)); // Dmsg2(100, "bsr VolParam FI=%u LI=%u\n", // bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex); @@ -428,18 +431,20 @@ static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd) } fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); - if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { - fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); - } else { - fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, - bsr->VolParams[i].EndFile); - } - if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { - fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock); - } else { - fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, - bsr->VolParams[i].EndBlock); - } +// if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { +// fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); +// } else { +// fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, +// bsr->VolParams[i].EndFile); +// } +// if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { +// fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock); +// } else { +// fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, +// bsr->VolParams[i].EndBlock); +// } + fprintf(fd, "VolAddr=%s-%s\n", edit_uint64(bsr->VolParams[i].StartAddr, ed1), + edit_uint64(bsr->VolParams[i].EndAddr, ed2)); // Dmsg2(100, "bsr VolParam FI=%u LI=%u\n", // bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex); diff --git a/bacula/src/stored/bsr.h b/bacula/src/stored/bsr.h index 9e594dedfe..304de114d3 100644 --- a/bacula/src/stored/bsr.h +++ b/bacula/src/stored/bsr.h @@ -106,6 +106,12 @@ struct BSR_VOLBLOCK { bool done; /* local done */ }; +struct BSR_VOLADDR { + BSR_VOLADDR *next; + uint64_t saddr; /* start address */ + uint64_t eaddr; /* end address */ + bool done; /* local done */ +}; struct BSR_FINDEX { BSR_FINDEX *next; @@ -157,6 +163,7 @@ struct BSR { uint32_t found; /* count of restored files this bsr */ BSR_VOLFILE *volfile; BSR_VOLBLOCK *volblock; + BSR_VOLADDR *voladdr; BSR_SESSTIME *sesstime; BSR_SESSID *sessid; BSR_JOBID *JobId; diff --git a/bacula/src/stored/match_bsr.c b/bacula/src/stored/match_bsr.c index ca05a54580..9304c8886e 100644 --- a/bacula/src/stored/match_bsr.c +++ b/bacula/src/stored/match_bsr.c @@ -36,15 +36,6 @@ /* * ***FIXME*** - * find_smallest_volfile needs to be fixed to only look at items that - * are not marked as done. Otherwise, it can find a bsr - * that has already been consumed, and this will cause the - * bsr to be used, thus we may seek back and re-read the - * same records, causing an error. This deficiency must - * be fixed. For the moment, it has been kludged in - * read_record.c to avoid seeking back if find_next_bsr - * returns a bsr pointing to a smaller address (file/block). - * * Also for efficiency, once a bsr is done, it really should be * delinked from the bsr chain. This will avoid the above * problem and make traversal of the bsr chain more efficient. @@ -73,7 +64,7 @@ static int match_job_level(BSR *bsr, BSR_JOBLEVEL *job_level, SESSION_LABEL *ses static int match_jobid(BSR *bsr, BSR_JOBID *jobid, SESSION_LABEL *sessrec, bool done); static int match_findex(BSR *bsr, BSR_FINDEX *findex, DEV_RECORD *rec, bool done); static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, bool done); -static int match_volblock(BSR *bsr, BSR_VOLBLOCK *volblock, DEV_RECORD *rec, bool done); +static int match_voladdr(BSR *bsr, BSR_VOLADDR *voladdr, DEV_RECORD *rec, bool done); static int match_stream(BSR *bsr, BSR_STREAM *stream, DEV_RECORD *rec, bool done); static int match_all(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, SESSION_LABEL *sessrec, bool done, JCR *jcr); static int match_block_sesstime(BSR *bsr, BSR_SESSTIME *sesstime, DEV_BLOCK *block); @@ -255,7 +246,29 @@ BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev) } /* - * ***FIXME*** + * Get the smallest address from this voladdr part + * Don't use "done" elements + */ +static bool get_smallest_voladdr(BSR_VOLADDR *va, uint64_t *ret) +{ + bool ok=false; + uint64_t min_val=0; + + for (; va ; va = va->next) { + if (!va->done) { + if (ok) { + min_val = MIN(min_val, va->saddr); + } else { + min_val = va->saddr; + ok=true; + } + } + } + *ret = min_val; + return ok; +} + +/* FIXME * This routine needs to be fixed to only look at items that * are not marked as done. Otherwise, it can find a bsr * that has already been consumed, and this will cause the @@ -264,6 +277,7 @@ BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev) * be fixed. For the moment, it has been kludged in * read_record.c to avoid seeking back if find_next_bsr * returns a bsr pointing to a smaller address (file/block). + * */ static BSR *find_smallest_volfile(BSR *found_bsr, BSR *bsr) { @@ -272,6 +286,18 @@ static BSR *find_smallest_volfile(BSR *found_bsr, BSR *bsr) BSR_VOLBLOCK *vb; uint32_t found_bsr_sfile, bsr_sfile; uint32_t found_bsr_sblock, bsr_sblock; + uint64_t found_bsr_saddr, bsr_saddr; + + /* if we have VolAddr, use it, else try with File and Block */ + if (get_smallest_voladdr(found_bsr->voladdr, &found_bsr_saddr)) { + if (get_smallest_voladdr(bsr->voladdr, &bsr_saddr)) { + if (found_bsr_saddr > bsr_saddr) { + return bsr; + } else { + return found_bsr; + } + } + } /* Find the smallest file in the found_bsr */ vf = found_bsr->volfile; @@ -374,20 +400,20 @@ static int match_all(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, volrec->VolumeName); if (!match_volfile(bsr, bsr->volfile, rec, 1)) { - Dmsg3(dbglevel, "Fail on file=%u. bsr=%u,%u\n", - rec->File, bsr->volfile->sfile, bsr->volfile->efile); + if (bsr->volfile) { + Dmsg3(dbglevel, "Fail on file=%u. bsr=%u,%u\n", + rec->File, bsr->volfile->sfile, bsr->volfile->efile); + } goto no_match; } - Dmsg3(dbglevel, "OK bsr file=%u. bsr=%u,%u\n", - rec->File, bsr->volfile->sfile, bsr->volfile->efile); - if (!match_volblock(bsr, bsr->volblock, rec, 1)) { - Dmsg3(dbglevel, "Fail on Block=%u. bsr=%u,%u\n", - rec->Block, bsr->volblock->sblock, bsr->volblock->eblock); + if (!match_voladdr(bsr, bsr->voladdr, rec, 1)) { + if (bsr->voladdr) { + Dmsg3(dbglevel, "Fail on Addr=%lld. bsr=%lld,%lld\n", + get_record_address(rec), bsr->voladdr->saddr, bsr->voladdr->eaddr); + } goto no_match; } - Dmsg3(dbglevel, "OK bsr Block=%u. bsr=%u,%u\n", - rec->Block, bsr->volblock->sblock, bsr->volblock->eblock); if (!match_sesstime(bsr, bsr->sesstime, rec, 1)) { Dmsg2(dbglevel, "Fail on sesstime. bsr=%u rec=%u\n", @@ -605,42 +631,35 @@ static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, bool d return 0; } -static int match_volblock(BSR *bsr, BSR_VOLBLOCK *volblock, DEV_RECORD *rec, bool done) +static int match_voladdr(BSR *bsr, BSR_VOLADDR *voladdr, DEV_RECORD *rec, bool done) { - /* - * Currently block matching does not work correctly for disk - * files in all cases, so it is "turned off" by the following - * return statement. - */ - return 1; - - - if (!volblock) { + if (!voladdr) { return 1; /* no specification matches all */ } /* For the moment, these tests work only with disk. */ if (rec->state & REC_ISTAPE) { return 1; /* All File records OK for this match */ } -// Dmsg3(dbglevel, "match_volblock: sblock=%u eblock=%u recblock=%u\n", -// volblock->sblock, volblock->eblock, rec->Block); - if (volblock->sblock <= rec->Block && volblock->eblock >= rec->Block) { + uint64_t addr = get_record_address(rec); +// Dmsg3(dbglevel, "match_voladdr: saddr=%lld eaddr=%lld recaddr=%lld\n", +// volblock->saddr, volblock->eaddr, addr); + if (voladdr->saddr <= addr && voladdr->eaddr >= addr) { return 1; } /* Once we get past last eblock, we are done */ - if (rec->Block > volblock->eblock) { - volblock->done = true; /* set local done */ + if (addr > voladdr->eaddr) { + voladdr->done = true; /* set local done */ } - if (volblock->next) { - return match_volblock(bsr, volblock->next, rec, volblock->done && done); + if (voladdr->next) { + return match_voladdr(bsr, voladdr->next, rec, voladdr->done && done); } /* If we are done and all prior matches are done, this bsr is finished */ - if (volblock->done && done) { + if (voladdr->done && done) { bsr->done = true; bsr->root->reposition = true; - Dmsg2(dbglevel, "bsr done from volblock rec=%u voleblock=%u\n", - rec->Block, volblock->eblock); + Dmsg2(dbglevel, "bsr done from voladdr rec=%lld voleaddr=%lld\n", + addr, voladdr->eaddr); } return 0; } @@ -733,3 +752,29 @@ static int match_findex(BSR *bsr, BSR_FINDEX *findex, DEV_RECORD *rec, bool done } return 0; } + +uint64_t get_bsr_start_addr(BSR *bsr, uint32_t *file, uint32_t *block) +{ + uint64_t bsr_addr = 0; + uint32_t sfile = 0, sblock = 0; + + if (bsr) { + if (bsr->voladdr) { + bsr_addr = bsr->voladdr->saddr; + sfile = bsr_addr>>32; + sblock = (uint32_t)bsr_addr; + + } else if (bsr->volfile && bsr->volblock) { + bsr_addr = (((uint64_t)bsr->volfile->sfile)<<32)|bsr->volblock->sblock; + sfile = bsr->volfile->sfile; + sblock = bsr->volblock->sblock; + } + } + + if (file && block) { + *file = sfile; + *block = sblock; + } + + return bsr_addr; +} diff --git a/bacula/src/stored/parse_bsr.c b/bacula/src/stored/parse_bsr.c index ceeaba618e..4603dbaeaa 100644 --- a/bacula/src/stored/parse_bsr.c +++ b/bacula/src/stored/parse_bsr.c @@ -52,6 +52,7 @@ static BSR *store_findex(LEX *lc, BSR *bsr); static BSR *store_sessid(LEX *lc, BSR *bsr); static BSR *store_volfile(LEX *lc, BSR *bsr); static BSR *store_volblock(LEX *lc, BSR *bsr); +static BSR *store_voladdr(LEX *lc, BSR *bsr); static BSR *store_sesstime(LEX *lc, BSR *bsr); static BSR *store_include(LEX *lc, BSR *bsr); static BSR *store_exclude(LEX *lc, BSR *bsr); @@ -85,6 +86,7 @@ struct kw_items items[] = { {"exclude", store_exclude}, {"volfile", store_volfile}, {"volblock", store_volblock}, + {"voladdr", store_voladdr}, {"stream", store_stream}, {"slot", store_slot}, {"device", store_device}, @@ -212,17 +214,17 @@ static bool is_positioning_ok(BSR *bsr) { /* * Every bsr should have a volfile entry and a volblock entry + * or a VolAddr * if we are going to use positioning */ for ( ; bsr; bsr=bsr->next) { - if (!bsr->volfile || !bsr->volblock) { + if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) { return false; } } return true; } - static BSR *store_vol(LEX *lc, BSR *bsr) { int token; @@ -563,6 +565,40 @@ static BSR *store_volblock(LEX *lc, BSR *bsr) return bsr; } +/* + * Routine to handle Volume start/end address + */ +static BSR *store_voladdr(LEX *lc, BSR *bsr) +{ + int token; + BSR_VOLADDR *voladdr; + + for (;;) { + token = lex_get_token(lc, T_PINT64_RANGE); + if (token == T_ERROR) { + return NULL; + } + voladdr = (BSR_VOLADDR *)malloc(sizeof(BSR_VOLADDR)); + memset(voladdr, 0, sizeof(BSR_VOLADDR)); + voladdr->saddr = lc->pint64_val; + voladdr->eaddr = lc->pint64_val2; + /* Add it to the end of the chain */ + if (!bsr->voladdr) { + bsr->voladdr = voladdr; + } else { + /* Add to end of chain */ + BSR_VOLADDR *bs = bsr->voladdr; + for ( ;bs->next; bs=bs->next) + { } + bs->next = voladdr; + } + token = lex_get_token(lc, T_ALL); + if (token != T_COMMA) { + break; + } + } + return bsr; +} static BSR *store_sessid(LEX *lc, BSR *bsr) { @@ -705,6 +741,13 @@ void dump_volblock(BSR_VOLBLOCK *volblock) } } +void dump_voladdr(BSR_VOLADDR *voladdr) +{ + if (voladdr) { + Pmsg2(-1, _("VolAddr : %lld-%lld\n"), voladdr->saddr, voladdr->eaddr); + dump_voladdr(voladdr->next); + } +} void dump_findex(BSR_FINDEX *FileIndex) { @@ -795,6 +838,7 @@ void dump_bsr(BSR *bsr, bool recurse) dump_sesstime(bsr->sesstime); dump_volfile(bsr->volfile); dump_volblock(bsr->volblock); + dump_voladdr(bsr->voladdr); dump_client(bsr->client); dump_jobid(bsr->JobId); dump_job(bsr->job); @@ -840,6 +884,7 @@ void remove_bsr(BSR *bsr) free_bsr_item((BSR *)bsr->sesstime); free_bsr_item((BSR *)bsr->volfile); free_bsr_item((BSR *)bsr->volblock); + free_bsr_item((BSR *)bsr->voladdr); free_bsr_item((BSR *)bsr->JobId); free_bsr_item((BSR *)bsr->job); free_bsr_item((BSR *)bsr->FileIndex); diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 8902bf81dd..ac2ab67461 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -183,6 +183,10 @@ int match_bsr_block(BSR *bsr, DEV_BLOCK *block); void position_bsr_block(BSR *bsr, DEV_BLOCK *block); BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); bool is_this_bsr_done(BSR *bsr, DEV_RECORD *rec); +uint64_t get_bsr_start_addr(BSR *bsr, + uint32_t *file=NULL, + uint32_t *block=NULL); + /* From mount.c */ bool mount_next_read_volume(DCR *dcr); @@ -203,6 +207,7 @@ 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); +uint64_t get_record_address(DEV_RECORD *rec); /* From read_record.c */ bool read_records(DCR *dcr, diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c index 0ea2ce0491..aa606d0806 100644 --- a/bacula/src/stored/read_record.c +++ b/bacula/src/stored/read_record.c @@ -344,19 +344,21 @@ static bool try_repositioning(JCR *jcr, DEV_RECORD *rec, DCR *dcr) * when find_next_bsr() is fixed not to return a bsr already * completed. */ - if (dev->file > bsr->volfile->sfile || - (dev->file == bsr->volfile->sfile && dev->block_num > bsr->volblock->sblock)) { + uint32_t block, file; + /* TODO: use dev->file_addr ? */ + uint64_t dev_addr = (((uint64_t) dev->file)<<32) | dev->block_num; + uint64_t bsr_addr = get_bsr_start_addr(bsr, &file, &block); + + if (dev_addr > bsr_addr) { return false; } if (verbose) { - Jmsg(jcr, M_INFO, 0, _("Reposition from (file:block) %u:%u to %u:%u\n"), - dev->file, dev->block_num, bsr->volfile->sfile, - bsr->volblock->sblock); + Jmsg(jcr, M_INFO,0, _("Reposition from (file:block) %u:%u to %u:%u\n"), + dev->file, dev->block_num, file, block); } Dmsg4(10, "Try_Reposition from (file:block) %u:%u to %u:%u\n", - dev->file, dev->block_num, bsr->volfile->sfile, - bsr->volblock->sblock); - dev->reposition(dcr, bsr->volfile->sfile, bsr->volblock->sblock); + dev->file, dev->block_num, file, block); + dev->reposition(dcr, file, block); rec->Block = 0; } return false; @@ -369,6 +371,7 @@ static BSR *position_to_first_file(JCR *jcr, DCR *dcr) { BSR *bsr = NULL; DEVICE *dev = dcr->dev; + uint32_t file, block; /* * Now find and position to first file and block * on this tape. @@ -376,11 +379,11 @@ static BSR *position_to_first_file(JCR *jcr, DCR *dcr) if (jcr->bsr) { jcr->bsr->reposition = true; /* force repositioning */ bsr = find_next_bsr(jcr->bsr, dev); - if (bsr && (bsr->volfile->sfile != 0 || bsr->volblock->sblock != 0)) { + + if (get_bsr_start_addr(bsr, &file, &block) > 0) { Jmsg(jcr, M_INFO, 0, _("Forward spacing Volume \"%s\" to file:block %u:%u.\n"), - dev->VolHdr.VolumeName, - bsr->volfile->sfile, bsr->volblock->sblock); - dev->reposition(dcr, bsr->volfile->sfile, bsr->volblock->sblock); + dev->VolHdr.VolumeName, file, block); + dev->reposition(dcr, file, block); } } return bsr; diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index b5893981f2..d2a12e6cf9 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -422,6 +422,10 @@ bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec) return true; } +uint64_t get_record_address(DEV_RECORD *rec) +{ + return ((uint64_t)rec->File)<<32 | rec->Block; +} /* * Read a Record from the block @@ -456,7 +460,6 @@ bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec) rec->File = ((DEVICE *)block->dev)->EndFile; } - /* * Get the header. There is always a full header, * otherwise we find it in the next block. diff --git a/bacula/technotes-2.5 b/bacula/technotes-2.5 index 81fdc109fe..03605aee1f 100644 --- a/bacula/technotes-2.5 +++ b/bacula/technotes-2.5 @@ -10,6 +10,8 @@ filepattern (restore with regex in bsr) mixed priorities General: +18Dec08 +ebl Replace File:Block in BSR by Address to fix #1190 16Dec08 kes Correct missing return in Darwin code. 15Dec08