--- /dev/null
+Index: src/dird/bsr.c
+===================================================================
+--- src/dird/bsr.c (révision 8163)
++++ src/dird/bsr.c (copie de travail)
+@@ -325,6 +325,7 @@
+ */
+ 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;
+@@ -374,6 +375,8 @@
+ 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);
+
+@@ -440,6 +443,8 @@
+ 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);
+
+Index: src/cats/cats.h
+===================================================================
+--- src/cats/cats.h (révision 8163)
++++ src/cats/cats.h (copie de travail)
+@@ -844,6 +844,8 @@
+ 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 */
+ };
+Index: src/cats/sql_get.c
+===================================================================
+--- src/cats/sql_get.c (révision 8163)
++++ src/cats/sql_get.c (copie de travail)
+@@ -463,6 +463,8 @@
+ 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]);
+Index: src/stored/match_bsr.c
+===================================================================
+--- src/stored/match_bsr.c (révision 8174)
++++ src/stored/match_bsr.c (copie de travail)
+@@ -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_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,68 +246,123 @@
+ }
+
+ /*
+- * ***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
+- * 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).
++ * 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;
++}
++
++/*
++ * Get the smallest file number from this volfile part
++ * Don't use "done" elements
++ */
++static bool get_smallest_volfile(BSR_VOLFILE *vf, uint32_t *ret)
++{
++ bool ok=false;
++ uint32_t min_val=0;
++
++ for (; vf ; vf = vf->next) {
++ if (!vf->done) {
++ if (ok) {
++ min_val = MIN(min_val, vf->sfile);
++ } else {
++ min_val = vf->sfile;
++ ok=true;
++ }
++ }
++ }
++ *ret = min_val;
++ return ok;
++}
++
++/*
++ * Get the smallest block number from this volblock part
++ * Don't use "done" elements
++ */
++static bool get_smallest_volblock(BSR_VOLBLOCK *vb, uint32_t *ret)
++{
++ bool ok=false;
++ uint32_t min_val=0;
++
++ for (; vb ; vb = vb->next) {
++ if (!vb->done) {
++ if (ok) {
++ min_val = MIN(min_val, vb->sblock);
++ } else {
++ min_val = vb->sblock;
++ ok=true;
++ }
++ }
++ }
++ *ret = min_val;
++ return ok;
++}
++
++/*
++ *
++ */
+ static BSR *find_smallest_volfile(BSR *found_bsr, BSR *bsr)
+ {
+ BSR *return_bsr = found_bsr;
+- BSR_VOLFILE *vf;
+- BSR_VOLBLOCK *vb;
+- uint32_t found_bsr_sfile, bsr_sfile;
+- uint32_t found_bsr_sblock, bsr_sblock;
++ uint32_t found_bsr_sfile=0, bsr_sfile=0;
++ uint32_t found_bsr_sblock=0, bsr_sblock=0;
++ uint64_t found_bsr_saddr=0, bsr_saddr=0;
+
+- /* Find the smallest file in the found_bsr */
+- vf = found_bsr->volfile;
+- found_bsr_sfile = vf->sfile;
+- while ( (vf=vf->next) ) {
+- if (vf->sfile < found_bsr_sfile) {
+- found_bsr_sfile = vf->sfile;
++ /* 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 bsr */
+- vf = bsr->volfile;
+- bsr_sfile = vf->sfile;
+- while ( (vf=vf->next) ) {
+- if (vf->sfile < bsr_sfile) {
+- bsr_sfile = vf->sfile;
+- }
++ if (!get_smallest_volfile(found_bsr->volfile, &found_bsr_sfile)) {
++ return bsr; /* found_bsr seems to be done...*/
+ }
++
++ if (!get_smallest_volfile(bsr->volfile, &bsr_sfile)) {
++ return found_bsr; /* bsr seems to be done... */
++ }
+
+ /* if the bsr file is less than the found_bsr file, return bsr */
+ if (found_bsr_sfile > bsr_sfile) {
+ return_bsr = bsr;
+ } else if (found_bsr_sfile == bsr_sfile) {
+- /* Files are equal */
+- /* find smallest block in found_bsr */
+- vb = found_bsr->volblock;
+- found_bsr_sblock = vb->sblock;
+- while ( (vb=vb->next) ) {
+- if (vb->sblock < found_bsr_sblock) {
+- found_bsr_sblock = vb->sblock;
+- }
++ /* Files are equal, use block to find the smallest */
++ if (!get_smallest_volblock(found_bsr->volblock, &found_bsr_sblock)) {
++ return bsr; /* Should not be there */
+ }
+- /* Find smallest block in bsr */
+- vb = bsr->volblock;
+- bsr_sblock = vb->sblock;
+- while ( (vb=vb->next) ) {
+- if (vb->sblock < bsr_sblock) {
+- bsr_sblock = vb->sblock;
+- }
++
++ if (!get_smallest_volblock(bsr->volblock, &bsr_sblock)) {
++ return found_bsr; /* Should not be there */
+ }
++
+ /* Compare and return the smallest */
+ if (found_bsr_sblock > bsr_sblock) {
+ return_bsr = bsr;
+ }
+ }
++ Dmsg5(dbglevel, "find_smallest_volfile bsr=0x%p %i > %i | %i > %i\n",
++ return_bsr, found_bsr_sfile, bsr_sfile, found_bsr_sblock, bsr_sblock);
+ return return_bsr;
+ }
+
+@@ -381,13 +427,11 @@
+ 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)) {
++ Dmsg3(dbglevel, "Fail on Addr=%lld. bsr=%lld,%lld\n",
++ rec->Addr, 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 +649,34 @@
+ 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) {
++// Dmsg3(dbglevel, "match_voladdr: saddr=%q eaddr=%q recaddr=%q\n",
++// volblock->saddr, volblock->eaddr, rec->Addr);
++ if (voladdr->saddr <= rec->Addr && voladdr->eaddr >= rec->Addr) {
+ return 1;
+ }
+ /* Once we get past last eblock, we are done */
+- if (rec->Block > volblock->eblock) {
+- volblock->done = true; /* set local done */
++ if (rec->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=%q voleaddr=%q\n",
++ rec->Addr, voladdr->eaddr);
+ }
+ return 0;
+ }
+Index: src/stored/parse_bsr.c
+===================================================================
+--- src/stored/parse_bsr.c (révision 8163)
++++ src/stored/parse_bsr.c (copie de travail)
+@@ -52,6 +52,7 @@
+ 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 @@
+ {"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 @@
+ {
+ /*
+ * 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,7 +565,41 @@
+ 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)
+ {
+ int token;
+@@ -705,6 +741,13 @@
+ }
+ }
+
++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 @@
+ 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 @@
+ 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);
+Index: src/stored/record.c
+===================================================================
+--- src/stored/record.c (révision 8163)
++++ src/stored/record.c (copie de travail)
+@@ -210,7 +210,7 @@
+
+ void empty_record(DEV_RECORD *rec)
+ {
+- rec->File = rec->Block = 0;
++ rec->Addr = rec->File = rec->Block = 0;
+ rec->VolSessionId = rec->VolSessionTime = 0;
+ rec->FileIndex = rec->Stream = 0;
+ rec->data_len = rec->remainder = 0;
+@@ -455,8 +455,8 @@
+ rec->Block = ((DEVICE *)block->dev)->EndBlock;
+ rec->File = ((DEVICE *)block->dev)->EndFile;
+ }
++ rec->Addr = ((boffset_t)rec->File)<<32 | rec->Block;
+
+-
+ /*
+ * Get the header. There is always a full header,
+ * otherwise we find it in the next block.
+Index: src/stored/record.h
+===================================================================
+--- src/stored/record.h (révision 8163)
++++ src/stored/record.h (copie de travail)
+@@ -97,6 +97,7 @@
+ */
+ uint32_t File; /* File number */
+ uint32_t Block; /* Block number */
++ uint64_t Addr; /* Block address */
+ uint32_t VolSessionId; /* sequential id within this session */
+ uint32_t VolSessionTime; /* session start time */
+ int32_t FileIndex; /* sequential file number */
+Index: src/stored/bsr.h
+===================================================================
+--- src/stored/bsr.h (révision 8163)
++++ src/stored/bsr.h (copie de travail)
+@@ -106,6 +106,12 @@
+ 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 @@
+ 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;