From b25752e6272d65a7c1a93943d14e83b76dd70b83 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Thu, 24 Jul 2008 14:17:06 +0000 Subject: [PATCH] kes Implement console 'wait mount' command. Doesn't yet work. kes Implement timeout=nn on console 'wait mount timeout=nn' command. kes Break the do_swapping into do_unload, do_swapping, and do_load. It is much more logical that way. kes Implement a set_dcr_from_vol subroutine in acquire.c for reading volumes. This allows the dcr to be refreshed after being zapped when the wrong volume is mounted. This should fix bug #1126 -- During multiple tape restore, bacula does not ask for physical tape change, but rereads same tape git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@7429 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/dird/ua_cmds.c | 28 ++++++++++++++++ bacula/src/stored/acquire.c | 58 +++++++++++++++------------------ bacula/src/stored/dev.h | 2 ++ bacula/src/stored/mount.c | 30 ++++++++++++----- bacula/src/stored/read_record.c | 2 +- bacula/src/version.h | 4 +-- bacula/technotes-2.5 | 10 ++++++ 7 files changed, 91 insertions(+), 43 deletions(-) diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 84b2b90fbd..208d9095e8 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -1566,6 +1566,8 @@ static int status_handler(void *ctx, int num_fields, char **row) int wait_cmd(UAContext *ua, const char *cmd) { JCR *jcr; + int i; + time_t stop_time = 0; /* * no args @@ -1590,6 +1592,11 @@ int wait_cmd(UAContext *ua, const char *cmd) return 1; } + i = find_arg_with_value(ua, NT_("timeout")); + if (i > 0 && ua->argv[i]) { + stop_time = time(NULL) + str_to_int64(ua->argv[i]); + } + /* we have jobid, jobname or ujobid argument */ uint32_t jobid = 0 ; @@ -1627,6 +1634,27 @@ int wait_cmd(UAContext *ua, const char *cmd) free_jcr(jcr); } break; + /* Wait for a mount request */ + } else if (strcasecmp(ua->argk[i], "mount") == 0) { + for (bool waiting=false; !waiting; ) { + foreach_jcr(jcr) { + if (jcr->JobId != 0 && + (jcr->JobStatus == JS_WaitMedia || jcr->JobStatus == JS_WaitMount)) { + waiting = true; + break; + } + } + endeach_jcr(jcr); + if (waiting) { + break; + } + if (stop_time && (time(NULL) >= stop_time)) { + ua->warning_msg(_("Wait on mount timed out\n")); + return 1; + } + bmicrosleep(1, 0); + } + return 1; } } diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 15ce639176..2aba368092 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -38,6 +38,7 @@ /* Forward referenced functions */ static void attach_dcr_to_dev(DCR *dcr); +static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol); /********************************************************************* @@ -88,15 +89,9 @@ bool acquire_device_for_read(DCR *dcr) jcr->NumReadVolumes, jcr->CurReadVolume); goto get_out; /* should not happen */ } - /* - * Note, if we want to be able to work from a .bsr file only - * for disaster recovery, we must "simulate" reading the catalog - */ - bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName)); - bstrncpy(dcr->VolCatInfo.VolCatName, vol->VolumeName, sizeof(dcr->VolCatInfo.VolCatName)); - bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type)); - dcr->VolCatInfo.Slot = vol->Slot; - dcr->VolCatInfo.InChanger = vol->Slot > 0; + set_dcr_from_vol(dcr, vol); + + Dmsg2(100, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot); /* * If the MediaType requested for this volume is not the @@ -174,20 +169,12 @@ bool acquire_device_for_read(DCR *dcr) dev->clear_unload(); - if (reserve_volume(dcr, dcr->VolumeName) == NULL) { - Dmsg2(100, "Could not reserve volume %s on %s\n", dcr->VolumeName, - dcr->dev->print_name()); - Jmsg2(jcr, M_FATAL, 0, _("Could not reserve volume %s on %s\n"), dcr->VolumeName, - dcr->dev->print_name()); - goto get_out; - } if (dev->vol && dev->vol->is_swapping()) { dev->vol->set_slot(vol->Slot); Dmsg3(100, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->get_slot(), dev->vol->vol_name, dev->print_name()); } - init_device_wait_timers(dcr); tape_previously_mounted = dev->can_read() || dev->can_append() || @@ -217,7 +204,10 @@ bool acquire_device_for_read(DCR *dcr) goto get_out; /* error return */ } - dcr->do_swapping(false/*is_writing*/); + dcr->do_unload(); + dcr->do_swapping(false/*!is_writing*/); + dcr->do_load(false /*!is_writing*/); + set_dcr_from_vol(dcr, vol); /* refresh dcr with desired volume info */ /* * This code ensures that the device is ready for @@ -239,10 +229,12 @@ bool acquire_device_for_read(DCR *dcr) vol_label_status = read_dev_volume_label(dcr); switch (vol_label_status) { case VOL_OK: + Dmsg0(50, "Got correct volume.\n"); ok = true; dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */ break; /* got it */ case VOL_IO_ERROR: + Dmsg0(50, "IO Error\n"); /* * Send error message generated by read_dev_volume_label() * only we really had a tape mounted. This supresses superfluous @@ -253,13 +245,10 @@ bool acquire_device_for_read(DCR *dcr) } goto default_path; case VOL_NAME_ERROR: + Dmsg0(50, "Vol name error.\n"); if (dev->is_volume_to_unload()) { goto default_path; } -// if (tape_initially_mounted) { - tape_initially_mounted = false; -// goto default_path; -// } dev->set_unload(); /* force unload of unwanted tape */ if (!unload_autochanger(dcr, -1)) { /* at least free the device so we can re-open with correct volume */ @@ -270,6 +259,7 @@ bool acquire_device_for_read(DCR *dcr) default: Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); default_path: + Dmsg0(50, "default path\n"); tape_previously_mounted = true; /* @@ -289,15 +279,6 @@ default_path: try_autochanger = false; continue; /* try reading volume mounted */ } - /* Try closing and re-opening */ - dev->close(); - if (dev->open(dcr, OPEN_READ_ONLY) >= 0) { - continue; - } - if (!dev->poll) { - Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"), - dev->print_name(), dcr->VolumeName, dev->bstrerror()); - } } /* Mount a specific volume and no other */ @@ -305,7 +286,7 @@ default_path: if (!dir_ask_sysop_to_mount_volume(dcr, ST_READ)) { goto get_out; /* error return */ } - try_autochanger = true; /* permit using autochanger again */ + try_autochanger = true; /* permit trying the autochanger again */ continue; /* try reading again */ } /* end switch */ break; @@ -693,3 +674,16 @@ void free_dcr(DCR *dcr) } free(dcr); } + +static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol) +{ + /* + * Note, if we want to be able to work from a .bsr file only + * for disaster recovery, we must "simulate" reading the catalog + */ + bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName)); + bstrncpy(dcr->VolCatInfo.VolCatName, vol->VolumeName, sizeof(dcr->VolCatInfo.VolCatName)); + bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type)); + dcr->VolCatInfo.Slot = vol->Slot; + dcr->VolCatInfo.InChanger = vol->Slot > 0; +} diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 8e015497b5..399b453efb 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -552,6 +552,8 @@ public: int check_volume_label(bool &ask, bool &autochanger); void release_volume(); void do_swapping(bool is_writing); + bool do_unload(); + bool do_load(bool is_writing); bool is_tape_position_ok(); }; diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 8b8b27bded..efb76029d6 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -113,7 +113,9 @@ mount_next_vol: ask = true; /* ask operator to mount tape */ do_find = true; /* re-find a volume after unload */ } - do_swapping(true /*writing*/); + do_unload(); + do_swapping(true /*is_writing*/); + do_load(true /*is_writing*/); if (do_find && !find_a_volume()) { goto no_lock_bail_out; @@ -500,12 +502,30 @@ bool DCR::is_suitable_volume_mounted() return dir_get_volume_info(this, GET_VOL_INFO_FOR_WRITE); } -void DCR::do_swapping(bool is_writing) +bool DCR::do_unload() { if (dev->must_unload()) { Dmsg1(100, "must_unload release %s\n", dev->print_name()); release_volume(); } + return false; +} + +bool DCR::do_load(bool is_writing) +{ + if (dev->must_load()) { + Dmsg1(100, "Must load %s\n", dev->print_name()); + if (autoload_device(this, is_writing, NULL) > 0) { + dev->clear_load(); + return true; + } + return false; + } + return true; +} + +void DCR::do_swapping(bool is_writing) +{ /* * See if we are asked to swap the Volume from another device * if so, unload the other device here, and attach the @@ -528,12 +548,6 @@ void DCR::do_swapping(bool is_writing) } dev->swap_dev = NULL; } - if (dev->must_load()) { - Dmsg1(100, "Must load %s\n", dev->print_name()); - if (autoload_device(this, is_writing, NULL) > 0) { - dev->clear_load(); - } - } } diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c index 1ca911aa83..2072dbcefa 100644 --- a/bacula/src/stored/read_record.c +++ b/bacula/src/stored/read_record.c @@ -52,7 +52,7 @@ static bool try_repositioning(JCR *jcr, DEV_RECORD *rec, DCR *dcr); static char *rec_state_to_str(DEV_RECORD *rec); #endif -static const int dbglvl = 200; +static const int dbglvl = 500; bool read_records(DCR *dcr, bool record_cb(DCR *dcr, DEV_RECORD *rec), diff --git a/bacula/src/version.h b/bacula/src/version.h index da8c98e241..1c17e8af35 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,8 @@ #undef VERSION #define VERSION "2.5.2" -#define BDATE "22 July 2008" -#define LSMDATE "22Jul08" +#define BDATE "24 July 2008" +#define LSMDATE "24Jul08" #define PROG_COPYRIGHT "Copyright (C) %d-2008 Free Software Foundation Europe e.V.\n" #define BYEAR "2008" /* year for copyright messages in progs */ diff --git a/bacula/technotes-2.5 b/bacula/technotes-2.5 index 4c3ac71b83..556c585fa2 100644 --- a/bacula/technotes-2.5 +++ b/bacula/technotes-2.5 @@ -32,6 +32,16 @@ separator in console (!$%&'()*+,-/:;<>?[]^`{|}~) General: +24Jul08 +kes Implement console 'wait mount' command. Doesn't yet work. +kes Implement timeout=nn on console 'wait mount timeout=nn' command. +kes Break the do_swapping into do_unload, do_swapping, and + do_load. It is much more logical that way. +kes Implement a set_dcr_from_vol subroutine in acquire.c for + reading volumes. This allows the dcr to be refreshed after being + zapped when the wrong volume is mounted. + This should fix bug #1126 -- During multiple tape restore, bacula + does not ask for physical tape change, but rereads same tape 23Jul08 kes Apply patch submitted for bug #1107 with a small modification. This fixes a bug where bcopy copied too many records. -- 2.39.5