]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/testing/bsr_addr.patch
ebl cleanup
[bacula/bacula] / bacula / patches / testing / bsr_addr.patch
1 Index: src/dird/bsr.c
2 ===================================================================
3 --- src/dird/bsr.c      (revision 8163)
4 +++ src/dird/bsr.c      (working copy)
5 @@ -325,6 +325,7 @@
6   */
7  static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd)
8  {
9 +   char ed1[50], ed2[50];
10     uint32_t count = 0;
11     uint32_t total_count = 0;
12     uint32_t LastIndex = 0;
13 @@ -362,18 +363,20 @@
14              }
15              fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
16              fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
17 -            if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
18 -               fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile);
19 -            } else {
20 -               fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
21 -                       bsr->VolParams[i].EndFile);
22 -            }
23 -            if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
24 -               fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
25 -            } else {
26 -               fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
27 -                       bsr->VolParams[i].EndBlock);
28 -            }
29 +//            if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
30 +//               fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile);
31 +//            } else {
32 +//               fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
33 +//                       bsr->VolParams[i].EndFile);
34 +//            }
35 +//            if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
36 +//               fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
37 +//            } else {
38 +//               fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
39 +//                       bsr->VolParams[i].EndBlock);
40 +//            }
41 +            fprintf(fd, "VolAddr=%s-%s\n", edit_uint64(bsr->VolParams[i].StartAddr, ed1),
42 +                    edit_uint64(bsr->VolParams[i].EndAddr, ed2));
43     //       Dmsg2(100, "bsr VolParam FI=%u LI=%u\n",
44     //          bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex);
45  
46 @@ -428,18 +431,20 @@
47              }
48              fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
49              fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
50 -            if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
51 -               fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile);
52 -            } else {
53 -               fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
54 -                       bsr->VolParams[i].EndFile);
55 -            }
56 -            if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
57 -               fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
58 -            } else {
59 -               fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
60 -                       bsr->VolParams[i].EndBlock);
61 -            }
62 +//            if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
63 +//               fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile);
64 +//            } else {
65 +//               fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
66 +//                       bsr->VolParams[i].EndFile);
67 +//            }
68 +//            if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
69 +//               fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
70 +//            } else {
71 +//               fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
72 +//                       bsr->VolParams[i].EndBlock);
73 +//            }
74 +            fprintf(fd, "VolAddr=%s-%s\n", edit_uint64(bsr->VolParams[i].StartAddr, ed1),
75 +                    edit_uint64(bsr->VolParams[i].EndAddr, ed2));
76     //       Dmsg2(100, "bsr VolParam FI=%u LI=%u\n",
77     //          bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex);
78  
79 Index: src/cats/cats.h
80 ===================================================================
81 --- src/cats/cats.h     (revision 8163)
82 +++ src/cats/cats.h     (working copy)
83 @@ -844,6 +844,8 @@
84     uint32_t StartBlock;               /* start block on tape */
85     uint32_t EndBlock;                 /* last block */
86     int32_t Slot;                      /* Slot */
87 +   uint64_t StartAddr;                /* Start address */
88 +   uint64_t EndAddr;                  /* End address */
89  // uint32_t Copy;                     /* identical copy */
90  // uint32_t Stripe;                   /* RAIT strip number */
91  };
92 Index: src/cats/sql_get.c
93 ===================================================================
94 --- src/cats/sql_get.c  (revision 8163)
95 +++ src/cats/sql_get.c  (working copy)
96 @@ -463,6 +463,8 @@
97                 Vols[i].EndFile = str_to_uint64(row[5]);
98                 Vols[i].StartBlock = str_to_uint64(row[6]);
99                 Vols[i].EndBlock = str_to_uint64(row[7]);
100 +               Vols[i].StartAddr = (((uint64_t)Vols[i].StartFile)<<32) | Vols[i].StartBlock;
101 +               Vols[i].EndAddr =   (((uint64_t)Vols[i].EndFile)<<32) | Vols[i].EndBlock;
102  //             Vols[i].Copy = str_to_uint64(row[8]);
103                 Vols[i].Slot = str_to_uint64(row[9]);
104                 StorageId = str_to_uint64(row[10]);
105 Index: src/stored/match_bsr.c
106 ===================================================================
107 --- src/stored/match_bsr.c      (revision 8174)
108 +++ src/stored/match_bsr.c      (working copy)
109 @@ -36,15 +36,6 @@
110  
111  /*
112   * ***FIXME***
113 - * find_smallest_volfile needs to be fixed to only look at items that
114 - *   are not marked as done.  Otherwise, it can find a bsr
115 - *   that has already been consumed, and this will cause the
116 - *   bsr to be used, thus we may seek back and re-read the
117 - *   same records, causing an error.  This deficiency must
118 - *   be fixed.  For the moment, it has been kludged in 
119 - *   read_record.c to avoid seeking back if find_next_bsr
120 - *   returns a bsr pointing to a smaller address (file/block).
121 - *
122   * Also for efficiency, once a bsr is done, it really should be
123   *   delinked from the bsr chain.  This will avoid the above 
124   *   problem and make traversal of the bsr chain more efficient.
125 @@ -73,7 +64,7 @@
126  static int match_jobid(BSR *bsr, BSR_JOBID *jobid, SESSION_LABEL *sessrec, bool done);
127  static int match_findex(BSR *bsr, BSR_FINDEX *findex, DEV_RECORD *rec, bool done);
128  static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, bool done);
129 -static int match_volblock(BSR *bsr, BSR_VOLBLOCK *volblock, DEV_RECORD *rec, bool done);
130 +static int match_voladdr(BSR *bsr, BSR_VOLADDR *voladdr, DEV_RECORD *rec, bool done);
131  static int match_stream(BSR *bsr, BSR_STREAM *stream, DEV_RECORD *rec, bool done);
132  static int match_all(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, SESSION_LABEL *sessrec, bool done, JCR *jcr);
133  static int match_block_sesstime(BSR *bsr, BSR_SESSTIME *sesstime, DEV_BLOCK *block);
134 @@ -255,68 +246,123 @@
135  }
136  
137  /*
138 - * ***FIXME***
139 - * This routine needs to be fixed to only look at items that
140 - *   are not marked as done.  Otherwise, it can find a bsr
141 - *   that has already been consumed, and this will cause the
142 - *   bsr to be used, thus we may seek back and re-read the
143 - *   same records, causing an error.  This deficiency must
144 - *   be fixed.  For the moment, it has been kludged in 
145 - *   read_record.c to avoid seeking back if find_next_bsr
146 - *   returns a bsr pointing to a smaller address (file/block).
147 + * Get the smallest address from this voladdr part
148 + * Don't use "done" elements
149   */
150 +static bool get_smallest_voladdr(BSR_VOLADDR *va, uint64_t *ret)
151 +{
152 +   bool ok=false;
153 +   uint64_t min_val=0;
154 +
155 +   for (; va ; va = va->next) {
156 +      if (!va->done) {
157 +         if (ok) {
158 +            min_val = MIN(min_val, va->saddr);
159 +         } else {
160 +            min_val = va->saddr;
161 +            ok=true;
162 +         }
163 +      }
164 +   }
165 +   *ret = min_val;
166 +   return ok;
167 +}
168 +
169 +/*
170 + * Get the smallest file number from this volfile part
171 + * Don't use "done" elements
172 + */
173 +static bool get_smallest_volfile(BSR_VOLFILE *vf, uint32_t *ret)
174 +{
175 +   bool ok=false;
176 +   uint32_t min_val=0;
177 +
178 +   for (; vf ; vf = vf->next) {
179 +      if (!vf->done) {
180 +         if (ok) {
181 +            min_val = MIN(min_val, vf->sfile);
182 +         } else {
183 +            min_val = vf->sfile;
184 +            ok=true;
185 +         }
186 +      }
187 +   }
188 +   *ret = min_val;
189 +   return ok;
190 +}
191 +
192 +/*
193 + * Get the smallest block number from this volblock part
194 + * Don't use "done" elements
195 + */
196 +static bool get_smallest_volblock(BSR_VOLBLOCK *vb, uint32_t *ret)
197 +{
198 +   bool ok=false;
199 +   uint32_t min_val=0;
200 +
201 +   for (; vb ; vb = vb->next) {
202 +      if (!vb->done) {
203 +         if (ok) {
204 +            min_val = MIN(min_val, vb->sblock);
205 +         } else {
206 +            min_val = vb->sblock;
207 +            ok=true;
208 +         }
209 +      }
210 +   }
211 +   *ret = min_val;
212 +   return ok;
213 +}
214 +
215 +/*
216 + *
217 + */
218  static BSR *find_smallest_volfile(BSR *found_bsr, BSR *bsr)
219  {
220     BSR *return_bsr = found_bsr;
221 -   BSR_VOLFILE *vf;
222 -   BSR_VOLBLOCK *vb;
223 -   uint32_t found_bsr_sfile, bsr_sfile;
224 -   uint32_t found_bsr_sblock, bsr_sblock;
225 +   uint32_t found_bsr_sfile=0, bsr_sfile=0;
226 +   uint32_t found_bsr_sblock=0, bsr_sblock=0;
227 +   uint64_t found_bsr_saddr=0, bsr_saddr=0;
228  
229 -   /* Find the smallest file in the found_bsr */
230 -   vf = found_bsr->volfile;
231 -   found_bsr_sfile = vf->sfile;
232 -   while ( (vf=vf->next) ) {
233 -      if (vf->sfile < found_bsr_sfile) {
234 -         found_bsr_sfile = vf->sfile;
235 +   /* if we have VolAddr, use it, else try with File and Block */
236 +   if (get_smallest_voladdr(found_bsr->voladdr, &found_bsr_saddr)) {
237 +      if (get_smallest_voladdr(bsr->voladdr, &bsr_saddr)) {
238 +         if (found_bsr_saddr > bsr_saddr) {
239 +            return bsr;
240 +         } else {
241 +            return found_bsr;
242 +         }
243        }
244     }
245  
246 -   /* Find the smallest file in the bsr */
247 -   vf = bsr->volfile;
248 -   bsr_sfile = vf->sfile;
249 -   while ( (vf=vf->next) ) {
250 -      if (vf->sfile < bsr_sfile) {
251 -         bsr_sfile = vf->sfile;
252 -      }
253 +   if (!get_smallest_volfile(found_bsr->volfile, &found_bsr_sfile)) {
254 +      return bsr;               /* found_bsr seems to be done...*/
255     }
256 +   
257 +   if (!get_smallest_volfile(bsr->volfile, &bsr_sfile)) {
258 +      return found_bsr;         /* bsr seems to be done... */
259 +   }
260      
261     /* if the bsr file is less than the found_bsr file, return bsr */
262     if (found_bsr_sfile > bsr_sfile) {
263        return_bsr = bsr;
264     } else if (found_bsr_sfile == bsr_sfile) {
265 -      /* Files are equal */
266 -      /* find smallest block in found_bsr */
267 -      vb = found_bsr->volblock;
268 -      found_bsr_sblock = vb->sblock;
269 -      while ( (vb=vb->next) ) {
270 -         if (vb->sblock < found_bsr_sblock) {
271 -            found_bsr_sblock = vb->sblock;
272 -         }
273 +      /* Files are equal, use block to find the smallest */
274 +      if (!get_smallest_volblock(found_bsr->volblock, &found_bsr_sblock)) {
275 +         return bsr;            /* Should not be there */
276        }
277 -      /* Find smallest block in bsr */
278 -      vb = bsr->volblock;
279 -      bsr_sblock = vb->sblock;
280 -      while ( (vb=vb->next) ) {
281 -         if (vb->sblock < bsr_sblock) {
282 -            bsr_sblock = vb->sblock;
283 -         }
284 +
285 +      if (!get_smallest_volblock(bsr->volblock, &bsr_sblock)) {
286 +         return found_bsr;      /* Should not be there */
287        }
288 +
289        /* Compare and return the smallest */
290        if (found_bsr_sblock > bsr_sblock) {
291           return_bsr = bsr;
292        }
293     }
294 +   Dmsg5(dbglevel, "find_smallest_volfile bsr=0x%p %i > %i | %i > %i\n",
295 +         return_bsr, found_bsr_sfile, bsr_sfile, found_bsr_sblock, bsr_sblock);
296     return return_bsr;
297  }
298  
299 @@ -381,13 +427,11 @@
300     Dmsg3(dbglevel, "OK bsr file=%u. bsr=%u,%u\n", 
301           rec->File, bsr->volfile->sfile, bsr->volfile->efile);
302  
303 -   if (!match_volblock(bsr, bsr->volblock, rec, 1)) {
304 -      Dmsg3(dbglevel, "Fail on Block=%u. bsr=%u,%u\n", 
305 -         rec->Block, bsr->volblock->sblock, bsr->volblock->eblock);
306 +   if (!match_voladdr(bsr, bsr->voladdr, rec, 1)) {
307 +      Dmsg3(dbglevel, "Fail on Addr=%lld. bsr=%lld,%lld\n", 
308 +            get_record_address(rec), bsr->voladdr->saddr, bsr->voladdr->eaddr);
309        goto no_match;
310     }
311 -   Dmsg3(dbglevel, "OK bsr Block=%u. bsr=%u,%u\n", 
312 -      rec->Block, bsr->volblock->sblock, bsr->volblock->eblock);
313  
314     if (!match_sesstime(bsr, bsr->sesstime, rec, 1)) {
315        Dmsg2(dbglevel, "Fail on sesstime. bsr=%u rec=%u\n",
316 @@ -605,42 +649,35 @@
317     return 0;
318  }
319  
320 -static int match_volblock(BSR *bsr, BSR_VOLBLOCK *volblock, DEV_RECORD *rec, bool done)
321 +static int match_voladdr(BSR *bsr, BSR_VOLADDR *voladdr, DEV_RECORD *rec, bool done)
322  {
323 -   /*
324 -    * Currently block matching does not work correctly for disk
325 -    * files in all cases, so it is "turned off" by the following 
326 -    * return statement.
327 -    */
328 -   return 1;
329 -
330 -
331 -   if (!volblock) {
332 +   if (!voladdr) {
333        return 1;                       /* no specification matches all */
334     }
335     /* For the moment, these tests work only with disk. */
336     if (rec->state & REC_ISTAPE) {
337        return 1;                       /* All File records OK for this match */
338     }
339 -//  Dmsg3(dbglevel, "match_volblock: sblock=%u eblock=%u recblock=%u\n",
340 -//             volblock->sblock, volblock->eblock, rec->Block);
341 -   if (volblock->sblock <= rec->Block && volblock->eblock >= rec->Block) {
342 +   uint64_t addr = get_record_address(rec);
343 +//  Dmsg3(dbglevel, "match_voladdr: saddr=%lld eaddr=%lld recaddr=%lld\n",
344 +//             volblock->saddr, volblock->eaddr, addr);
345 +   if (voladdr->saddr <= addr && voladdr->eaddr >= addr) {
346        return 1;
347     }
348     /* Once we get past last eblock, we are done */
349 -   if (rec->Block > volblock->eblock) {
350 -      volblock->done = true;              /* set local done */
351 +   if (addr > voladdr->eaddr) {
352 +      voladdr->done = true;              /* set local done */
353     }
354 -   if (volblock->next) {
355 -      return match_volblock(bsr, volblock->next, rec, volblock->done && done);
356 +   if (voladdr->next) {
357 +      return match_voladdr(bsr, voladdr->next, rec, voladdr->done && done);
358     }
359  
360     /* If we are done and all prior matches are done, this bsr is finished */
361 -   if (volblock->done && done) {
362 +   if (voladdr->done && done) {
363        bsr->done = true;
364        bsr->root->reposition = true;
365 -      Dmsg2(dbglevel, "bsr done from volblock rec=%u voleblock=%u\n",
366 -         rec->Block, volblock->eblock);
367 +      Dmsg2(dbglevel, "bsr done from voladdr rec=%lld voleaddr=%lld\n",
368 +            addr, voladdr->eaddr);
369     }
370     return 0;
371  }
372 @@ -733,3 +770,48 @@
373     }
374     return 0;
375  }
376 +
377 +uint64_t get_bsr_start_addr(BSR *bsr, uint32_t *file, uint32_t *block)
378 +{
379 +   uint64_t bsr_addr = 0;
380 +   uint32_t sfile = 0, sblock = 0;
381 +
382 +   if (bsr) {
383 +      if (bsr->voladdr) {
384 +         bsr_addr = bsr->voladdr->saddr;
385 +         sfile = bsr_addr>>32;
386 +         sblock = (uint32_t)bsr_addr;
387 +         
388 +      } else if (bsr->volfile && bsr->volblock) {
389 +         bsr_addr = (((uint64_t)bsr->volfile->sfile)<<32)|bsr->volblock->sblock;
390 +         sfile = bsr->volfile->sfile;
391 +         sblock = bsr->volblock->sblock;
392 +      }
393 +   }
394 +
395 +   if (file && block) {
396 +      file = sfile;
397 +      block = sblock;
398 +   }
399 +
400 +   return bsr_addr;
401 +}
402 +
403 +/* DEV > BSR => 1
404 + * DEV = BSR => 0
405 + * DEV < BSR => -1
406 + */
407 +int cmp_device_bsr_position(DEVICE *dev, BSR *bsr)
408 +{
409 +   uint64_t bsr_addr = get_bsr_start_addr(bsr);
410 +
411 +   /* TODO: replace by file_addr ? */
412 +   uint64_t dev_addr = ((uint64_t dev->file)<<32) | dev->block_num;
413 +
414 +   if (dev_addr > bsr_addr)
415 +      return 1;
416 +   else if (dev_addr == bsr_addr)
417 +      return 0;
418 +   else
419 +      return -1;
420 +}
421 Index: src/stored/read_record.c
422 ===================================================================
423 --- src/stored/read_record.c    (revision 8163)
424 +++ src/stored/read_record.c    (working copy)
425 @@ -344,19 +344,21 @@
426         *   when find_next_bsr() is fixed not to return a bsr already
427         *   completed.
428         */
429 -      if (dev->file > bsr->volfile->sfile ||             
430 -         (dev->file == bsr->volfile->sfile && dev->block_num > bsr->volblock->sblock)) {
431 +      uint32_t block, file;
432 +      /* TODO: use dev->file_addr ? */
433 +      uint64_t dev_addr = ((uint64_t dev->file)<<32) | dev->block_num;
434 +      uint64_t bsr_addr = get_bsr_start_addr(bsr, &file, &block);
435 +
436 +      if (dev_addr > bsr_addr) {
437           return false;
438        }
439        if (verbose) {
440 -         Jmsg(jcr, M_INFO, 0, _("Reposition from (file:block) %u:%u to %u:%u\n"),
441 -            dev->file, dev->block_num, bsr->volfile->sfile,
442 -            bsr->volblock->sblock);
443 +         Jmsg(jcr, M_INFO,0, _("Reposition from (file:block) %u:%u to %u:%u\n"),
444 +              dev->file, dev->block_num, file, block);
445        }
446        Dmsg4(10, "Try_Reposition from (file:block) %u:%u to %u:%u\n",
447 -            dev->file, dev->block_num, bsr->volfile->sfile,
448 -            bsr->volblock->sblock);
449 -      dev->reposition(dcr, bsr->volfile->sfile, bsr->volblock->sblock);
450 +            dev->file, dev->block_num, file, block);
451 +      dev->reposition(dcr, file, block);
452        rec->Block = 0;
453     }
454     return false;
455 @@ -369,6 +371,7 @@
456  {
457     BSR *bsr = NULL;
458     DEVICE *dev = dcr->dev;
459 +   uint32_t file, block;
460     /*
461      * Now find and position to first file and block
462      *   on this tape.
463 @@ -376,11 +379,11 @@
464     if (jcr->bsr) {
465        jcr->bsr->reposition = true;    /* force repositioning */
466        bsr = find_next_bsr(jcr->bsr, dev);
467 -      if (bsr && (bsr->volfile->sfile != 0 || bsr->volblock->sblock != 0)) {
468 +      
469 +      if (get_bsr_start_addr(bsr, &file, &block) > 0) {
470           Jmsg(jcr, M_INFO, 0, _("Forward spacing Volume \"%s\" to file:block %u:%u.\n"),
471 -            dev->VolHdr.VolumeName,
472 -            bsr->volfile->sfile, bsr->volblock->sblock);
473 -         dev->reposition(dcr, bsr->volfile->sfile, bsr->volblock->sblock);
474 +              dev->VolHdr.VolumeName, file, block);
475 +         dev->reposition(dcr, file, block);
476        }
477     }
478     return bsr;
479 Index: src/stored/parse_bsr.c
480 ===================================================================
481 --- src/stored/parse_bsr.c      (revision 8163)
482 +++ src/stored/parse_bsr.c      (working copy)
483 @@ -52,6 +52,7 @@
484  static BSR *store_sessid(LEX *lc, BSR *bsr);
485  static BSR *store_volfile(LEX *lc, BSR *bsr);
486  static BSR *store_volblock(LEX *lc, BSR *bsr);
487 +static BSR *store_voladdr(LEX *lc, BSR *bsr);
488  static BSR *store_sesstime(LEX *lc, BSR *bsr);
489  static BSR *store_include(LEX *lc, BSR *bsr);
490  static BSR *store_exclude(LEX *lc, BSR *bsr);
491 @@ -85,6 +86,7 @@
492     {"exclude", store_exclude},
493     {"volfile", store_volfile},
494     {"volblock", store_volblock},
495 +   {"voladdr",  store_voladdr},
496     {"stream",   store_stream},
497     {"slot",     store_slot},
498     {"device",   store_device},
499 @@ -212,17 +214,17 @@
500  {
501     /*
502      * Every bsr should have a volfile entry and a volblock entry
503 +    * or a VolAddr
504      *   if we are going to use positioning
505      */
506     for ( ; bsr; bsr=bsr->next) {
507 -      if (!bsr->volfile || !bsr->volblock) {
508 +      if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) {
509           return false;
510        }
511     }
512     return true;
513  }
514  
515 -
516  static BSR *store_vol(LEX *lc, BSR *bsr)
517  {
518     int token;
519 @@ -563,7 +565,41 @@
520     return bsr;
521  }
522  
523 +/*
524 + * Routine to handle Volume start/end address
525 + */
526 +static BSR *store_voladdr(LEX *lc, BSR *bsr)
527 +{
528 +   int token;
529 +   BSR_VOLADDR *voladdr;
530  
531 +   for (;;) {
532 +      token = lex_get_token(lc, T_PINT64_RANGE);
533 +      if (token == T_ERROR) {
534 +         return NULL;
535 +      }
536 +      voladdr = (BSR_VOLADDR *)malloc(sizeof(BSR_VOLADDR));
537 +      memset(voladdr, 0, sizeof(BSR_VOLADDR));
538 +      voladdr->saddr = lc->pint64_val;
539 +      voladdr->eaddr = lc->pint64_val2;
540 +      /* Add it to the end of the chain */
541 +      if (!bsr->voladdr) {
542 +         bsr->voladdr = voladdr;
543 +      } else {
544 +         /* Add to end of chain */
545 +         BSR_VOLADDR *bs = bsr->voladdr;
546 +         for ( ;bs->next; bs=bs->next)
547 +            {  }
548 +         bs->next = voladdr;
549 +      }
550 +      token = lex_get_token(lc, T_ALL);
551 +      if (token != T_COMMA) {
552 +         break;
553 +      }
554 +   }
555 +   return bsr;
556 +}
557 +
558  static BSR *store_sessid(LEX *lc, BSR *bsr)
559  {
560     int token;
561 @@ -705,6 +741,13 @@
562     }
563  }
564  
565 +void dump_voladdr(BSR_VOLADDR *voladdr)
566 +{
567 +   if (voladdr) {
568 +      Pmsg2(-1, _("VolAddr    : %lld-%lld\n"), voladdr->saddr, voladdr->eaddr);
569 +      dump_voladdr(voladdr->next);
570 +   }
571 +}
572  
573  void dump_findex(BSR_FINDEX *FileIndex)
574  {
575 @@ -795,6 +838,7 @@
576     dump_sesstime(bsr->sesstime);
577     dump_volfile(bsr->volfile);
578     dump_volblock(bsr->volblock);
579 +   dump_voladdr(bsr->voladdr);
580     dump_client(bsr->client);
581     dump_jobid(bsr->JobId);
582     dump_job(bsr->job);
583 @@ -840,6 +884,7 @@
584     free_bsr_item((BSR *)bsr->sesstime);
585     free_bsr_item((BSR *)bsr->volfile);
586     free_bsr_item((BSR *)bsr->volblock);
587 +   free_bsr_item((BSR *)bsr->voladdr);
588     free_bsr_item((BSR *)bsr->JobId);
589     free_bsr_item((BSR *)bsr->job);
590     free_bsr_item((BSR *)bsr->FileIndex);
591 Index: src/stored/record.c
592 ===================================================================
593 --- src/stored/record.c (revision 8163)
594 +++ src/stored/record.c (working copy)
595 @@ -422,6 +422,10 @@
596     return true;
597  }
598  
599 +uint64_t get_record_address(DEV_RECORD *rec)
600 +{
601 +   return ((uint64_t)rec->File)<<32 | rec->Block;
602 +}
603  
604  /*
605   * Read a Record from the block
606 @@ -456,7 +460,6 @@
607        rec->File = ((DEVICE *)block->dev)->EndFile;
608     }   
609  
610 -
611     /*
612      * Get the header. There is always a full header,
613      * otherwise we find it in the next block.
614 Index: src/stored/bsr.h
615 ===================================================================
616 --- src/stored/bsr.h    (revision 8163)
617 +++ src/stored/bsr.h    (working copy)
618 @@ -106,6 +106,12 @@
619     bool done;                         /* local done */
620  };
621  
622 +struct BSR_VOLADDR {
623 +   BSR_VOLADDR *next;
624 +   uint64_t saddr;                   /* start address */
625 +   uint64_t eaddr;                   /* end address */
626 +   bool done;                        /* local done */
627 +};
628  
629  struct BSR_FINDEX {
630     BSR_FINDEX *next;
631 @@ -157,6 +163,7 @@
632     uint32_t      found;               /* count of restored files this bsr */
633     BSR_VOLFILE  *volfile;
634     BSR_VOLBLOCK *volblock;
635 +   BSR_VOLADDR  *voladdr;
636     BSR_SESSTIME *sesstime;
637     BSR_SESSID   *sessid;
638     BSR_JOBID    *JobId;
639 Index: src/stored/protos.h
640 ===================================================================
641 --- src/stored/protos.h (revision 8163)
642 +++ src/stored/protos.h (working copy)
643 @@ -183,7 +183,11 @@
644  void     position_bsr_block(BSR *bsr, DEV_BLOCK *block);
645  BSR     *find_next_bsr(BSR *root_bsr, DEVICE *dev);
646  bool     is_this_bsr_done(BSR *bsr, DEV_RECORD *rec);
647 +uint64_t get_bsr_start_addr(BSR *bsr, 
648 +                            uint32_t *file=NULL,
649 +                            uint32_t *block=NULL);
650  
651 +
652  /* From mount.c */
653  bool     mount_next_read_volume(DCR *dcr);
654  
655 @@ -203,6 +207,7 @@
656  DEV_RECORD *new_record();
657  void        free_record(DEV_RECORD *rec);
658  void        empty_record(DEV_RECORD *rec);
659 +uint64_t get_record_address(DEV_RECORD *rec);
660  
661  /* From read_record.c */
662  bool read_records(DCR *dcr,