2 ===================================================================
3 --- src/dird/bsr.c (revision 8163)
4 +++ src/dird/bsr.c (working copy)
7 static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd)
9 + char ed1[50], ed2[50];
11 uint32_t total_count = 0;
12 uint32_t LastIndex = 0;
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);
20 - fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
21 - bsr->VolParams[i].EndFile);
23 - if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
24 - fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
26 - fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
27 - bsr->VolParams[i].EndBlock);
29 +// if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
30 +// fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile);
32 +// fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
33 +// bsr->VolParams[i].EndFile);
35 +// if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
36 +// fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
38 +// fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
39 +// bsr->VolParams[i].EndBlock);
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);
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);
53 - fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
54 - bsr->VolParams[i].EndFile);
56 - if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
57 - fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
59 - fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
60 - bsr->VolParams[i].EndBlock);
62 +// if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) {
63 +// fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile);
65 +// fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
66 +// bsr->VolParams[i].EndFile);
68 +// if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) {
69 +// fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock);
71 +// fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
72 +// bsr->VolParams[i].EndBlock);
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);
79 Index: src/cats/cats.h
80 ===================================================================
81 --- src/cats/cats.h (revision 8163)
82 +++ src/cats/cats.h (working copy)
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 */
92 Index: src/cats/sql_get.c
93 ===================================================================
94 --- src/cats/sql_get.c (revision 8163)
95 +++ src/cats/sql_get.c (working copy)
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)
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).
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.
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 @@
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
150 +static bool get_smallest_voladdr(BSR_VOLADDR *va, uint64_t *ret)
153 + uint64_t min_val=0;
155 + for (; va ; va = va->next) {
158 + min_val = MIN(min_val, va->saddr);
160 + min_val = va->saddr;
170 + * Get the smallest file number from this volfile part
171 + * Don't use "done" elements
173 +static bool get_smallest_volfile(BSR_VOLFILE *vf, uint32_t *ret)
176 + uint32_t min_val=0;
178 + for (; vf ; vf = vf->next) {
181 + min_val = MIN(min_val, vf->sfile);
183 + min_val = vf->sfile;
193 + * Get the smallest block number from this volblock part
194 + * Don't use "done" elements
196 +static bool get_smallest_volblock(BSR_VOLBLOCK *vb, uint32_t *ret)
199 + uint32_t min_val=0;
201 + for (; vb ; vb = vb->next) {
204 + min_val = MIN(min_val, vb->sblock);
206 + min_val = vb->sblock;
218 static BSR *find_smallest_volfile(BSR *found_bsr, BSR *bsr)
220 BSR *return_bsr = found_bsr;
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;
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) {
246 - /* Find the smallest file in the bsr */
248 - bsr_sfile = vf->sfile;
249 - while ( (vf=vf->next) ) {
250 - if (vf->sfile < bsr_sfile) {
251 - bsr_sfile = vf->sfile;
253 + if (!get_smallest_volfile(found_bsr->volfile, &found_bsr_sfile)) {
254 + return bsr; /* found_bsr seems to be done...*/
257 + if (!get_smallest_volfile(bsr->volfile, &bsr_sfile)) {
258 + return found_bsr; /* bsr seems to be done... */
261 /* if the bsr file is less than the found_bsr file, return bsr */
262 if (found_bsr_sfile > bsr_sfile) {
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;
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 */
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;
285 + if (!get_smallest_volblock(bsr->volblock, &bsr_sblock)) {
286 + return found_bsr; /* Should not be there */
289 /* Compare and return the smallest */
290 if (found_bsr_sblock > bsr_sblock) {
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);
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);
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);
311 - Dmsg3(dbglevel, "OK bsr Block=%u. bsr=%u,%u\n",
312 - rec->Block, bsr->volblock->sblock, bsr->volblock->eblock);
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 @@
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)
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.
333 return 1; /* no specification matches all */
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 */
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) {
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 */
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);
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) {
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);
377 +uint64_t get_bsr_start_addr(BSR *bsr, uint32_t *file, uint32_t *block)
379 + uint64_t bsr_addr = 0;
380 + uint32_t sfile = 0, sblock = 0;
383 + if (bsr->voladdr) {
384 + bsr_addr = bsr->voladdr->saddr;
385 + sfile = bsr_addr>>32;
386 + sblock = (uint32_t)bsr_addr;
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;
395 + if (file && block) {
407 +int cmp_device_bsr_position(DEVICE *dev, BSR *bsr)
409 + uint64_t bsr_addr = get_bsr_start_addr(bsr);
411 + /* TODO: replace by file_addr ? */
412 + uint64_t dev_addr = ((uint64_t dev->file)<<32) | dev->block_num;
414 + if (dev_addr > bsr_addr)
416 + else if (dev_addr == bsr_addr)
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
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);
436 + if (dev_addr > bsr_addr) {
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);
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);
458 DEVICE *dev = dcr->dev;
459 + uint32_t file, block;
461 * Now find and position to first file and block
463 @@ -376,11 +379,11 @@
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)) {
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);
479 Index: src/stored/parse_bsr.c
480 ===================================================================
481 --- src/stored/parse_bsr.c (revision 8163)
482 +++ src/stored/parse_bsr.c (working copy)
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);
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 @@
502 * Every bsr should have a volfile entry and a volblock entry
504 * if we are going to use positioning
506 for ( ; bsr; bsr=bsr->next) {
507 - if (!bsr->volfile || !bsr->volblock) {
508 + if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) {
516 static BSR *store_vol(LEX *lc, BSR *bsr)
524 + * Routine to handle Volume start/end address
526 +static BSR *store_voladdr(LEX *lc, BSR *bsr)
529 + BSR_VOLADDR *voladdr;
532 + token = lex_get_token(lc, T_PINT64_RANGE);
533 + if (token == T_ERROR) {
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;
544 + /* Add to end of chain */
545 + BSR_VOLADDR *bs = bsr->voladdr;
546 + for ( ;bs->next; bs=bs->next)
548 + bs->next = voladdr;
550 + token = lex_get_token(lc, T_ALL);
551 + if (token != T_COMMA) {
558 static BSR *store_sessid(LEX *lc, BSR *bsr)
565 +void dump_voladdr(BSR_VOLADDR *voladdr)
568 + Pmsg2(-1, _("VolAddr : %lld-%lld\n"), voladdr->saddr, voladdr->eaddr);
569 + dump_voladdr(voladdr->next);
573 void dump_findex(BSR_FINDEX *FileIndex)
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);
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)
599 +uint64_t get_record_address(DEV_RECORD *rec)
601 + return ((uint64_t)rec->File)<<32 | rec->Block;
605 * Read a Record from the block
607 rec->File = ((DEVICE *)block->dev)->EndFile;
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)
619 bool done; /* local done */
622 +struct BSR_VOLADDR {
624 + uint64_t saddr; /* start address */
625 + uint64_t eaddr; /* end address */
626 + bool done; /* local done */
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;
639 Index: src/stored/protos.h
640 ===================================================================
641 --- src/stored/protos.h (revision 8163)
642 +++ src/stored/protos.h (working copy)
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);
653 bool mount_next_read_volume(DCR *dcr);
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);
661 /* From read_record.c */
662 bool read_records(DCR *dcr,