From bb8d43499bf377a6feb669e43574a27f1e953438 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 28 Aug 2002 21:10:33 +0000 Subject: [PATCH] Correct restore across volumes + document git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@125 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/dird/ua_server.c | 1 + bacula/src/lib/bnet.c | 6 +- bacula/src/stored/bextract.c | 133 +++++++++++++++++--------------- bacula/src/stored/bls.c | 106 +++++++++++++------------ bacula/src/stored/mount.c | 2 +- bacula/src/stored/read.c | 82 +++++++++++--------- bacula/src/stored/stored_conf.c | 2 +- 7 files changed, 178 insertions(+), 154 deletions(-) diff --git a/bacula/src/dird/ua_server.c b/bacula/src/dird/ua_server.c index a5aa833240..a2af20fc7a 100644 --- a/bacula/src/dird/ua_server.c +++ b/bacula/src/dird/ua_server.c @@ -80,6 +80,7 @@ static void *connect_thread(void *arg) pthread_detach(pthread_self()); + /* ****FIXME**** put # 5 on config parameter */ bnet_thread_server(UA_port, 5, &ua_workq, handle_UA_client_request); return NULL; } diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 312edad2c7..80b1a53cda 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -281,7 +281,6 @@ bnet_send(BSOCK *bsock) bsock->b_errno = errno; } if (rc < 0) { - /************FIXME********* use Pmsg() **/ Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who, bsock->host, bsock->port, bnet_strerror(bsock)); } else { @@ -348,11 +347,12 @@ static uint32_t *bget_host_ip(void *jcr, char *host) } else { /******FIXME***** use gethostbyname_r or mutex ****/ if ((hp = gethostbyname(host)) == NULL) { - Pmsg2(0, "gethostbyname() for %s failed: ERR=%s\n", host, strerror(errno)); + Jmsg2(jcr, M_ERROR, 0, "gethostbyname() for %s failed: ERR=%s\n", + host, strerror(errno)); return NULL; } if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) { - Jmsg2(jcr, M_WARNING, 0, _("gethostbyname() network address length error.\n\ + Jmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\ Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length); return NULL; } diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index f34ed12978..a0d2417686 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -34,7 +34,7 @@ static void do_extract(char *fname, char *prefix); static void print_ls_output(char *fname, char *link, int type, struct stat *statp); - +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec); static DEVICE *dev = NULL; static int ofd = -1; @@ -155,6 +155,30 @@ int main (int argc, char *argv[]) } return 0; } + +/* + * Device got an error, attempt to analyse it + */ +static void display_error_status() +{ + uint32_t status; + + Emsg0(M_ERROR, 0, dev->errmsg); + status_dev(dev, &status); + Dmsg1(20, "Device status: %x\n", status); + if (status & MT_EOD) + Emsg0(M_ERROR_TERM, 0, "Unexpected End of Data\n"); + else if (status & MT_EOT) + Emsg0(M_ERROR_TERM, 0, "Unexpected End of Tape\n"); + else if (status & MT_EOF) + Emsg0(M_ERROR_TERM, 0, "Unexpected End of File\n"); + else if (status & MT_DR_OPEN) + Emsg0(M_ERROR_TERM, 0, "Tape Door is Open\n"); + else if (!(status & MT_ONLINE)) + Emsg0(M_ERROR_TERM, 0, "Unexpected Tape is Off-line\n"); + else + Emsg2(M_ERROR_TERM, 0, "Read error on Record Header %s: %s\n", dev_name(dev), strerror(errno)); +} static void do_extract(char *devname, char *where) @@ -228,13 +252,18 @@ static void do_extract(char *devname, char *where) for ( ;; ) { if (!read_block_from_device(dev, block)) { - uint32_t status; Dmsg1(500, "Main read record failed. rem=%d\n", rec->remainder); if (dev->state & ST_EOT) { + DEV_RECORD *record; if (!mount_next_read_volume(jcr, dev, block)) { break; } - continue; + record = new_record(); + read_block_from_device(dev, block); + read_record_from_block(block, record); + get_session_record(dev, record, &sessrec); + free_record(record); + goto next_record; } if (dev->state & ST_EOF) { continue; /* try again */ @@ -242,75 +271,25 @@ static void do_extract(char *devname, char *where) if (dev->state & ST_SHORT) { continue; } - Pmsg0(0, "Read Record got a bad record\n"); - status_dev(dev, &status); - Dmsg1(20, "Device status: %x\n", status); - if (status & MT_EOD) - Emsg0(M_ERROR_TERM, 0, "Unexpected End of Data\n"); - else if (status & MT_EOT) - Emsg0(M_ERROR_TERM, 0, "Unexpected End of Tape\n"); - else if (status & MT_EOF) - Emsg0(M_ERROR_TERM, 0, "Unexpected End of File\n"); - else if (status & MT_DR_OPEN) - Emsg0(M_ERROR_TERM, 0, "Tape Door is Open\n"); - else if (!(status & MT_ONLINE)) - Emsg0(M_ERROR_TERM, 0, "Unexpected Tape is Off-line\n"); - else - Emsg3(M_ERROR_TERM, 0, "Read error %d on Record Header %s: %s\n", - status, dev_name(dev), strerror(errno)); + display_error_status(); } +next_record: for (rec->state=0; !is_block_empty(rec); ) { if (!read_record_from_block(block, rec)) { break; } - /* This is no longer used */ - if (rec->VolSessionId == 0 && rec->VolSessionTime == 0) { - Emsg0(M_ERROR, 0, "Zero header record. This shouldn't happen.\n"); - break; /* END OF FILE */ + if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ + Dmsg0(40, "Get EOM LABEL\n"); + rec->remainder = 0; + break; /* yes, get out */ } - /* - * Check for Start or End of Session Record - * - */ + /* Some sort of label? */ if (rec->FileIndex < 0) { - char *rtype; - memset(&sessrec, 0, sizeof(sessrec)); - switch (rec->FileIndex) { - case PRE_LABEL: - rtype = "Fresh Volume Label"; - break; - case VOL_LABEL: - rtype = "Volume Label"; - unser_volume_label(dev, rec); - break; - case SOS_LABEL: - rtype = "Begin Session"; - unser_session_label(&sessrec, rec); - break; - case EOS_LABEL: - rtype = "End Session"; - break; - case EOM_LABEL: - rtype = "End of Media"; - break; - default: - rtype = "Unknown"; - break; - } - if (debug_level > 0) { - printf("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", - rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); - } - - Dmsg1(40, "Got label = %d\n", rec->FileIndex); - if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ - Dmsg0(40, "Get EOM LABEL\n"); - break; /* yes, get out */ - } - continue; /* ignore other labels */ + get_session_record(dev, rec, &sessrec); + continue; } /* end if label record */ /* Is this the file we want? */ @@ -529,6 +508,36 @@ static void print_ls_output(char *fname, char *link, int type, struct stat *stat fputs(buf, stdout); } +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec) +{ + char *rtype; + memset(sessrec, 0, sizeof(sessrec)); + switch (rec->FileIndex) { + case PRE_LABEL: + rtype = "Fresh Volume Label"; + break; + case VOL_LABEL: + rtype = "Volume Label"; + unser_volume_label(dev, rec); + break; + case SOS_LABEL: + rtype = "Begin Session"; + unser_session_label(sessrec, rec); + break; + case EOS_LABEL: + rtype = "End Session"; + break; + case EOM_LABEL: + rtype = "End of Media"; + break; + default: + rtype = "Unknown"; + break; + } + Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", + rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); +} + /* Dummies to replace askdir.c */ int dir_get_volume_info(JCR *jcr) { return 1;} int dir_find_next_appendable_volume(JCR *jcr) { return 1;} diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index f8c40a3d00..9c4c20f106 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -34,6 +34,7 @@ static void do_ls(char *fname); static void print_ls_output(char *fname, char *link, int type, struct stat *statp); static void do_setup(char *infname); static void do_close(); +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec); static DEVICE *dev; static int default_tape = FALSE; @@ -244,7 +245,7 @@ static void do_setup(char *infname) *p = 0; } } - Dmsg2(10, "Device=%s, Vol=%s.\n", infname, VolName); + Dmsg2(000, "Device=%s, Vol=%s.\n", infname, VolName); dev = init_dev(NULL, infname); if (!dev) { Emsg1(M_FATAL, 0, "Cannot open %s\n", infname); @@ -263,7 +264,7 @@ static void do_setup(char *infname) NumVolumes = 0; CurVolume = 1; for (p = VolName; p && *p; ) { - p = strchr(p, '^'); + p = strchr(p, '|'); if (p) { *p++ = 0; } @@ -488,10 +489,22 @@ Warning, this Volume is a continuation of Volume %s\n", if (!read_block_from_device(dev, block)) { Dmsg0(20, "!read_record()\n"); if (dev->state & ST_EOT) { + DEV_RECORD *record; + Dmsg3(000, "EOT. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), + block->BlockNumber, rec->remainder); if (!mount_next_volume(infname)) { + Dmsg3(000, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), + block->BlockNumber, rec->remainder); break; } - continue; + Dmsg3(000, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), + block->BlockNumber, rec->remainder); + record = new_record(); + read_block_from_device(dev, block); + read_record_from_block(block, record); + get_session_record(dev, record, &sessrec); + free_record(record); + goto next_record; } if (dev->state & ST_EOF) { Emsg1(M_INFO, 0, "Got EOF on device %s\n", dev_name(dev)); @@ -509,12 +522,12 @@ Warning, this Volume is a continuation of Volume %s\n", Dmsg2(10, "Block: %d blen=%d\n", block->BlockNumber, block->block_len); } +next_record: record = 0; for (rec->state=0; !is_block_empty(rec); ) { if (!read_record_from_block(block, rec)) { Dmsg3(10, "!read-break. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), block->BlockNumber, rec->remainder); -// rec->remainder = 0; break; } Dmsg3(10, "read-OK. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), @@ -537,56 +550,16 @@ Warning, this Volume is a continuation of Volume %s\n", rec->data_len); } - /* - * Check for End of File record (all zeros) - * NOTE: this no longer exists - */ - if (rec->VolSessionId == 0 && rec->VolSessionTime == 0) { - Emsg0(M_ERROR_TERM, 0, "Zero VolSessionId and VolSessionTime. This shouldn't happen\n"); + if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ + Dmsg0(40, "Get EOM LABEL\n"); + rec->remainder = 0; + break; /* yes, get out */ } - /* - * Check for Start or End of Session Record - * - */ + /* Some sort of label? */ if (rec->FileIndex < 0) { - char *rtype; - memset(&sessrec, 0, sizeof(sessrec)); - switch (rec->FileIndex) { - case PRE_LABEL: - rtype = "Fresh Volume Label"; - break; - case VOL_LABEL: - rtype = "Volume Label"; - unser_volume_label(dev, rec); - break; - case SOS_LABEL: - rtype = "Begin Session"; - unser_session_label(&sessrec, rec); - break; - case EOS_LABEL: - rtype = "End Session"; - break; - case EOM_LABEL: - rtype = "End of Media"; - break; - default: - rtype = "Unknown"; - break; - } - if (debug_level > 0) { - printf("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", - rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); - } - - Dmsg1(40, "Got label = %d\n", rec->FileIndex); - if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ - Dmsg0(100, "EOM LABEL break\n"); - rec->remainder = 0; - break; /* yes, get out */ - } - rec->remainder = 0; - continue; /* we don't want record, read next one */ + get_session_record(dev, rec, &sessrec); + continue; } /* end if label record */ /* @@ -684,6 +657,37 @@ static void print_ls_output(char *fname, char *link, int type, struct stat *stat fputs(buf, stdout); } +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec) +{ + char *rtype; + memset(sessrec, 0, sizeof(sessrec)); + switch (rec->FileIndex) { + case PRE_LABEL: + rtype = "Fresh Volume Label"; + break; + case VOL_LABEL: + rtype = "Volume Label"; + unser_volume_label(dev, rec); + break; + case SOS_LABEL: + rtype = "Begin Session"; + unser_session_label(sessrec, rec); + break; + case EOS_LABEL: + rtype = "End Session"; + break; + case EOM_LABEL: + rtype = "End of Media"; + break; + default: + rtype = "Unknown"; + break; + } + Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", + rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); +} + + /* Dummies to replace askdir.c */ int dir_get_volume_info(JCR *jcr) { return 1;} int dir_find_next_appendable_volume(JCR *jcr) { return 1;} diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index fea18a03c1..70879769f2 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -379,7 +379,7 @@ int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) for (int i=1; iCurVolume; i++) { vol = vol->next; } - strcpy(jcr->VolumeName, vol->VolumeName); + pm_strcpy(&jcr->VolumeName, vol->VolumeName); Dmsg1(400, "There is another volume %s.\n", jcr->VolumeName); close_dev(dev); diff --git a/bacula/src/stored/read.c b/bacula/src/stored/read.c index 35e2abe626..b4037e813d 100644 --- a/bacula/src/stored/read.c +++ b/bacula/src/stored/read.c @@ -29,6 +29,7 @@ #include "stored.h" /* Forward referenced subroutines */ +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec); /* Variables used by Child process */ /* Global statistics */ @@ -113,10 +114,15 @@ int do_read_data(JCR *jcr) if (!read_block_from_device(dev, block)) { Dmsg1(500, "Main read record failed. rem=%d\n", rec->remainder); if (dev->state & ST_EOT) { + DEV_RECORD *record; if (!mount_next_read_volume(jcr, dev, block)) { break; } - continue; + record = new_record(); + read_block_from_device(dev, block); + read_record_from_block(block, record); + get_session_record(dev, record, &sessrec); + free_record(record); } if (dev->state & ST_EOF) { Dmsg0(90, "Got End of File. Trying again ...\n"); @@ -139,45 +145,19 @@ int do_read_data(JCR *jcr) * get all the data. */ + if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ + Dmsg0(40, "Get EOM LABEL\n"); + rec->remainder = 0; + break; /* yes, get out */ + } + /* Some sort of label? */ if (rec->FileIndex < 0) { - char *rtype; - memset(&sessrec, 0, sizeof(sessrec)); - switch (rec->FileIndex) { - case PRE_LABEL: - rtype = "Fresh Volume Label"; - break; - case VOL_LABEL: - rtype = "Volume Label"; - unser_volume_label(dev, rec); - break; - case SOS_LABEL: - rtype = "Begin Session"; - unser_session_label(&sessrec, rec); - break; - case EOS_LABEL: - rtype = "End Session"; - break; - case EOM_LABEL: - rtype = "End of Media"; - break; - default: - rtype = "Unknown"; - break; - } - Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", - rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); - - Dmsg1(40, "Got label = %d\n", rec->FileIndex); - if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ - Dmsg0(40, "Get EOM LABEL\n"); - rec->remainder = 0; - break; /* yes, get out */ - } - rec->remainder = 0; - continue; /* ignore other labels */ + get_session_record(dev, rec, &sessrec); + continue; } /* end if label record */ + /* Match BSR against current record */ if (jcr->bsr) { if (!match_bsr(jcr->bsr, rec, &dev->VolHdr, &sessrec)) { @@ -246,3 +226,33 @@ int do_read_data(JCR *jcr) Dmsg0(30, "Done reading.\n"); return ok ? 1 : 0; } + +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec) +{ + char *rtype; + memset(sessrec, 0, sizeof(sessrec)); + switch (rec->FileIndex) { + case PRE_LABEL: + rtype = "Fresh Volume Label"; + break; + case VOL_LABEL: + rtype = "Volume Label"; + unser_volume_label(dev, rec); + break; + case SOS_LABEL: + rtype = "Begin Session"; + unser_session_label(sessrec, rec); + break; + case EOS_LABEL: + rtype = "End Session"; + break; + case EOM_LABEL: + rtype = "End of Media"; + break; + default: + rtype = "Unknown"; + break; + } + Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", + rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); +} diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index c42bf4c392..2ea9e4881b 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -61,7 +61,7 @@ static struct res_items store_items[] = { {"workingdirectory", store_dir, ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0}, {"piddirectory", store_dir, ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0}, {"subsysdirectory", store_dir, ITEM(res_store.subsys_directory), 0, ITEM_REQUIRED, 0}, - {"maximumconcurrentjobs", store_int, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 1}, + {"maximumconcurrentjobs", store_pint, ITEM(res_store.max_concurrent_jobs), 0, ITEM_DEFAULT, 2}, {NULL, NULL, 0, 0, 0, 0} }; -- 2.39.5