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 */
};
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]);
*/
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;
}
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);
}
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);
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;
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;
/*
* ***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.
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);
}
/*
- * ***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
* 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)
{
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;
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",
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;
}
}
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;
+}
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);
{"exclude", store_exclude},
{"volfile", store_volfile},
{"volblock", store_volblock},
+ {"voladdr", store_voladdr},
{"stream", store_stream},
{"slot", store_slot},
{"device", store_device},
{
/*
* 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;
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)
{
}
}
+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)
{
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);
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);
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);
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,
* 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;
{
BSR *bsr = NULL;
DEVICE *dev = dcr->dev;
+ uint32_t file, block;
/*
* Now find and position to first file and block
* on this tape.
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;
return true;
}
+uint64_t get_record_address(DEV_RECORD *rec)
+{
+ return ((uint64_t)rec->File)<<32 | rec->Block;
+}
/*
* Read a Record from the block
rec->File = ((DEVICE *)block->dev)->EndFile;
}
-
/*
* Get the header. There is always a full header,
* otherwise we find it in the next block.
mixed priorities
General:
+18Dec08
+ebl Replace File:Block in BSR by Address to fix #1190
16Dec08
kes Correct missing return in Darwin code.
15Dec08