From: Kern Sibbald Date: Mon, 30 Jun 2008 12:56:49 +0000 (+0000) Subject: kes Generally clean up the manual tape loading code. The main X-Git-Tag: Release-2.4.1~34 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=53541bb4156d7ea5ba1f8994c5e92bf28e77079a;p=bacula%2Fbacula kes Generally clean up the manual tape loading code. The main conceptial change is that when a volume is marked to be unloaded, its volume name is retained, and it is only marked as unloaded when either the autoloader says it is unloaded or another tape is read on that drive. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/branches/Branch-2.4@7263 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/dird/autoprune.c b/bacula/src/dird/autoprune.c index df4cb5542d..38aab4f4a5 100644 --- a/bacula/src/dird/autoprune.c +++ b/bacula/src/dird/autoprune.c @@ -190,7 +190,7 @@ bool prune_volumes(JCR *jcr, bool InChanger, MEDIA_DBR *mr) */ if (ok && lmr.PoolId == mr->PoolId) { Dmsg2(050, "Vol=%s MediaId=%d purged.\n", lmr.VolumeName, (int)lmr.MediaId); - mr = &lmr; /* struct copy */ + memcpy(mr, &lmr, sizeof(lmr)); break; /* got a volume */ } /* diff --git a/bacula/src/dird/pythondir.c b/bacula/src/dird/pythondir.c index c17606e2f4..60a2fe2503 100644 --- a/bacula/src/dird/pythondir.c +++ b/bacula/src/dird/pythondir.c @@ -67,7 +67,7 @@ PyMethodDef JobMethods[] = { struct s_vars { const char *name; - char *fmt; + const char *fmt; }; /* Read-only variables */ diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index d54a476b3d..944d2f5547 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -1140,7 +1140,7 @@ static int bootstrap_cmd(JCR *jcr) } while (bnet_recv(dir) >= 0) { - Dmsg1(200, "filedmsg); + Dmsg1(200, "filedmsg); fputs(dir->msg, bs); } fclose(bs); diff --git a/bacula/src/filed/pythonfd.c b/bacula/src/filed/pythonfd.c index 130f494e11..be6f185dd5 100644 --- a/bacula/src/filed/pythonfd.c +++ b/bacula/src/filed/pythonfd.c @@ -72,7 +72,7 @@ ssize_t my_python_read(BFILE *bfd, void *buf, size_t count); struct s_vars { const char *name; - char *fmt; + const char *fmt; }; /* Read-only variables */ diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index 3032fc037e..3ce86e23f4 100644 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -600,7 +600,7 @@ void set_jcr_job_status(JCR *jcr, int JobStatus) * For a set of errors, ... keep the current status * so it isn't lost. For all others, set it. */ - Dmsg2(100, "OnEntry JobStatus=%c set=%c\n", jcr->JobStatus, JobStatus); + Dmsg2(200, "OnEntry JobStatus=%c set=%c\n", jcr->JobStatus, JobStatus); switch (jcr->JobStatus) { case JS_ErrorTerminated: case JS_FatalError: @@ -620,7 +620,7 @@ void set_jcr_job_status(JCR *jcr, int JobStatus) default: jcr->JobStatus = JobStatus; } - Dmsg2(100, "OnExit JobStatus=%c set=%c\n", jcr->JobStatus, JobStatus); + Dmsg2(200, "OnExit JobStatus=%c set=%c\n", jcr->JobStatus, JobStatus); } #ifdef TRACE_JCR_CHAIN diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 55489403b9..42f15bd765 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -70,6 +70,7 @@ bool acquire_device_for_read(DCR *dcr) dev->num_writers, jcr->JobId); goto get_out; } + dev->clear_unload(); /* Find next Volume, if any */ vol = jcr->VolList; @@ -194,8 +195,10 @@ bool acquire_device_for_read(DCR *dcr) /* Volume info is always needed because of VolParts */ - Dmsg0(200, "dir_get_volume_info\n"); + Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName); if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) { + Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n", + dcr->VolumeName, jcr->errmsg); Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); } dev->set_load(); /* set to load volume */ @@ -236,7 +239,7 @@ bool acquire_device_for_read(DCR *dcr) switch (vol_label_status) { case VOL_OK: ok = true; - memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); + dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */ break; /* got it */ case VOL_IO_ERROR: /* @@ -249,20 +252,20 @@ bool acquire_device_for_read(DCR *dcr) } goto default_path; case VOL_NAME_ERROR: - if (tape_initially_mounted) { - tape_initially_mounted = false; - goto default_path; - } - /* If polling and got a previous bad name, ignore it */ - if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) { + if (dev->is_volume_to_unload()) { goto default_path; - } else { - bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName)); } +// 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 */ dev->close(); } + dev->set_load(); + ASSERT(0); /* Fall through */ default: Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); @@ -288,7 +291,6 @@ default_path: } /* Try closing and re-opening */ dev->close(); - dev->clear_unload(); if (dev->open(dcr, OPEN_READ_ONLY) >= 0) { continue; } @@ -308,6 +310,7 @@ default_path: } /* end switch */ break; } /* end for loop */ + if (!ok) { Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s for reading.\n"), dev->print_name()); @@ -370,6 +373,8 @@ DCR *acquire_device_for_append(DCR *dcr) goto get_out; } + dev->clear_unload(); + /* * have_vol defines whether or not mount_next_write_volume should * ask the Director again about what Volume to use. diff --git a/bacula/src/stored/authenticate.c b/bacula/src/stored/authenticate.c index 49f6551fc5..0d2d9390a5 100644 --- a/bacula/src/stored/authenticate.c +++ b/bacula/src/stored/authenticate.c @@ -60,13 +60,13 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) if (rcode != R_DIRECTOR) { Dmsg1(dbglvl, "I only authenticate Directors, not %d\n", rcode); - Emsg1(M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode); + Jmsg1(jcr, M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode); return 0; } if (bs->msglen < 25 || bs->msglen > 500) { Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n", bs->who(), bs->msglen); - Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"), + Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"), bs->who(), bs->msglen); return 0; } @@ -77,7 +77,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) bs->msg[100] = 0; Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n", bs->who(), bs->msg); - Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"), + Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"), bs->who(), bs->msg); return 0; } @@ -90,7 +90,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) if (!director) { Dmsg2(dbglvl, "Connection from unknown Director %s at %s rejected.\n", dirname, bs->who()); - Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n" + Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n" "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"), dirname, bs->who()); free_pool_memory(dirname); @@ -123,7 +123,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) } if (!auth_success) { - Emsg0(M_FATAL, 0, _("Incorrect password given by Director.\n" + Jmsg0(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n" "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n")); auth_success = false; goto auth_fatal; @@ -131,7 +131,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) /* Verify that the remote host is willing to meet our TLS requirements */ if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) { - Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not" + Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" " advertise required TLS support.\n")); auth_success = false; goto auth_fatal; @@ -139,7 +139,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) /* Verify that we are willing to meet the remote host's requirements */ if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) { - Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); + Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); auth_success = false; goto auth_fatal; } @@ -147,7 +147,7 @@ static int authenticate(int rcode, BSOCK *bs, JCR* jcr) if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { /* Engage TLS! Full Speed Ahead! */ if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) { - Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n")); + Jmsg0(jcr, M_FATAL, 0, _("TLS negotiation failed.\n")); auth_success = false; goto auth_fatal; } @@ -179,7 +179,7 @@ int authenticate_director(JCR *jcr) if (!authenticate(R_DIRECTOR, dir, jcr)) { dir->fsend("%s", Dir_sorry); Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who()); - Emsg1(M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who()); + Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who()); bmicrosleep(5, 0); return 0; } diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index 6bb750d95c..a8afe572c4 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -377,7 +377,9 @@ bool unload_autochanger(DCR *dcr, int loaded) free_volume(dev); /* Free any volume associated with this drive */ free_pool_memory(changer); } - dev->clear_unload(); + if (ok) { + dev->clear_unload(); + } return ok; } @@ -495,7 +497,9 @@ bool unload_dev(DCR *dcr, DEVICE *dev) Dmsg2(100, "Slot %d unloaded %s\n", dev->get_slot(), dev->print_name()); dev->set_slot(0); /* nothing loaded */ } - dev->clear_unload(); + if (ok) { + dev->clear_unload(); + } unlock_changer(dcr); dev->dunlock(); diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 7d11452ccc..c6f9046508 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -1829,6 +1829,16 @@ void DEVICE::clrerror(int func) #endif } +/* + * Set to unload the current volume in the drive + */ +void DEVICE::set_unload() +{ + if (!m_unload && VolHdr.VolumeName[0] != 0) { + m_unload = true; + memcpy(UnloadVolName, VolHdr.VolumeName, sizeof(UnloadVolName)); + } +} /* * Clear volume header @@ -2379,7 +2389,6 @@ void init_device_wait_timers(DCR *dcr) dev->rem_wait_sec = dev->wait_sec; dev->num_wait = 0; dev->poll = false; - dev->BadVolName[0] = 0; jcr->min_wait = 60 * 60; jcr->max_wait = 24 * 60 * 60; diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index fbfa735b68..ca2968fddb 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -279,9 +279,10 @@ public: char pool_name[MAX_NAME_LENGTH]; /* pool name */ char pool_type[MAX_NAME_LENGTH]; /* pool type */ - /* Device wait times ***FIXME*** look at durations */ - char BadVolName[MAX_NAME_LENGTH]; /* Last wrong Volume mounted */ + char UnloadVolName[MAX_NAME_LENGTH]; /* Last wrong Volume mounted */ bool poll; /* set to poll Volume */ + + /* Device wait times ***FIXME*** look at durations */ int min_wait; int max_wait; int max_num_wait; @@ -363,7 +364,8 @@ public: void set_part_spooled(int val) { if (val) state |= ST_PART_SPOOLED; \ else state &= ~ST_PART_SPOOLED; }; - void set_unload() { m_unload = true; }; + bool is_volume_to_unload() const { \ + return m_unload && strcmp(VolHdr.VolumeName, UnloadVolName) == 0; }; void set_load() { m_load = true; }; void inc_reserved() { m_num_reserved++; } void set_mounted(int val) { if (val) state |= ST_MOUNTED; \ @@ -380,13 +382,14 @@ public: void clear_media() { state &= ~ST_MEDIA; }; void clear_short_block() { state &= ~ST_SHORT; }; void clear_freespace_ok() { state &= ~ST_FREESPACE_OK; }; - void clear_unload() { m_unload = false; }; + void clear_unload() { m_unload = false; UnloadVolName[0] = 0; }; void clear_load() { m_load = false; }; char *bstrerror(void) { return errmsg; }; char *print_errmsg() { return errmsg; }; int32_t get_slot() const { return m_slot; }; + void set_unload(); /* in dev.c */ void clear_volhdr(); /* in dev.c */ void close(); /* in dev.c */ void close_part(DCR *dcr); /* in dev.c */ @@ -533,6 +536,7 @@ public: void mark_volume_in_error(); void mark_volume_not_inchanger(); int try_autolabel(bool opened); + bool find_a_volume(); bool is_suitable_volume_mounted(); bool is_eod_valid(); int check_volume_label(bool &ask, bool &autochanger); diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index d5c981bbd6..da90a41fb0 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -168,6 +168,10 @@ int read_dev_volume_label(DCR *dcr) } free_record(record); /* finished reading Volume record */ + if (!dev->is_volume_to_unload()) { + dev->clear_unload(); + } + if (!ok) { if (forge_on || jcr->ignore_label_errors) { dev->set_labeled(); /* set has Bacula label */ @@ -212,15 +216,6 @@ int read_dev_volume_label(DCR *dcr) } dev->set_labeled(); /* set has Bacula label */ - Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName); - Dmsg2(100, "=== dcr->dev=%p dev=%p\n", dcr->dev, dev); - if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) { - Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"), - dev->VolHdr.VolumeName, dev->print_name()); - stat = VOL_NAME_ERROR; - goto bail_out; - } - Dmsg2(100, "=== dcr->dev=%p dev=%p\n", dcr->dev, dev); /* Compare Volume Names */ Dmsg2(130, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName); @@ -237,10 +232,9 @@ int read_dev_volume_label(DCR *dcr) } Dmsg0(150, "return VOL_NAME_ERROR\n"); stat = VOL_NAME_ERROR; - volume_unused(dcr); /* mark volume "released" */ goto bail_out; } - Dmsg1(130, "Copy vol_name=%s\n", dev->VolHdr.VolumeName); + if (debug_level >= 10) { dump_volume_label(dev); @@ -253,11 +247,19 @@ int read_dev_volume_label(DCR *dcr) stat = read_ansi_ibm_label(dcr); /* If we want a label and didn't find it, return error */ if (stat != VOL_OK) { - volume_unused(dcr); /* mark volume "released" */ goto bail_out; } } } + + Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName); + if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) { + Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"), + dev->VolHdr.VolumeName, dev->print_name()); + stat = VOL_NAME_ERROR; + goto bail_out; + } + empty_block(block); return VOL_OK; diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index e4f7cf7ada..b6f0f02e6f 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -96,6 +96,7 @@ mount_next_vol: goto no_lock_bail_out; } lock_volumes(); + Dmsg1(150, "Continue after dir_ask_sysop_to_mount. must_load=%d\n", dev->must_load()); } if (job_canceled(jcr)) { Jmsg(jcr, M_FATAL, 0, _("Job %d canceled.\n"), jcr->JobId); @@ -108,34 +109,10 @@ mount_next_vol: } do_swapping(true /*writing*/); - if (!is_suitable_volume_mounted()) { - bool have_vol = false; - /* Do we have a candidate volume? */ - if (dev->vol) { - bstrncpy(VolumeName, dev->vol->vol_name, sizeof(VolumeName)); - have_vol = dir_get_volume_info(this, GET_VOL_INFO_FOR_WRITE); - } - /* - * Get Director's idea of what tape we should have mounted. - * in dcr->VolCatInfo - */ - if (!have_vol) { - Dmsg0(200, "Before dir_find_next_appendable_volume.\n"); - while (!dir_find_next_appendable_volume(dcr)) { - Dmsg0(200, "not dir_find_next\n"); - if (job_canceled(jcr)) { - goto bail_out; - } - unlock_volumes(); - if (!dir_ask_sysop_to_create_appendable_volume(dcr)) { - goto no_lock_bail_out; - } - lock_volumes(); - Dmsg0(200, "Again dir_find_next_append...\n"); - } - goto mount_next_vol; - } + if (retry < 2 && !find_a_volume()) { + goto no_lock_bail_out; } + if (job_canceled(jcr)) { goto bail_out; } @@ -169,21 +146,21 @@ mount_next_vol: * we will fail, recurse and ask the operator the next time. */ if (!dev->must_unload() && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) { - Dmsg0(150, "(1)Ask=0\n"); + Dmsg0(250, "(1)Ask=0\n"); ask = false; /* don't ask SYSOP this time */ } /* Don't ask if not removable */ if (!dev->is_removable()) { - Dmsg0(150, "(2)Ask=0\n"); + Dmsg0(250, "(2)Ask=0\n"); ask = false; } - Dmsg2(150, "Ask=%d autochanger=%d\n", ask, autochanger); + Dmsg2(250, "Ask=%d autochanger=%d\n", ask, autochanger); if (ask) { unlock_volumes(); if (!dir_ask_sysop_to_mount_volume(dcr, ST_APPEND)) { Dmsg0(150, "Error return ask_sysop ...\n"); - goto no_lock_bail_out; /* error return */ + goto no_lock_bail_out; } lock_volumes(); } @@ -229,30 +206,22 @@ mount_next_vol: if (try_autolabel(false) == try_read_vol) { break; /* created a new volume label */ } + Dmsg0(50, "set_unload\n"); dev->set_unload(); /* force ask sysop */ ask = true; + Dmsg0(150, "goto mount_next_vol\n"); goto mount_next_vol; -#ifdef xxx - /* If DVD, ignore the error, very often you cannot open the device - * (when there is no DVD, or when the one inserted is a wrong one) */ - if (dev->poll || dev->is_dvd()) { - goto mount_next_vol; - } else { - Jmsg2(jcr, M_ERROR, 0, _("Could not open device %s: ERR=%s\n"), - dev->print_name(), dev->print_errmsg()); - goto bail_out; - } -#endif } /* * Now check the volume label to make sure we have the right tape mounted */ read_volume: - switch (check_volume_label(ask, autochanger)) { case check_next_vol: + Dmsg0(50, "set_unload\n"); dev->set_unload(); /* want a different Volume */ + Dmsg0(150, "goto mount_next_vol\n"); goto mount_next_vol; case check_read_vol: goto read_volume; @@ -298,6 +267,7 @@ read_volume: goto mount_next_vol; } if (!is_eod_valid()) { + Dmsg0(150, "goto mount_next_vol\n"); goto mount_next_vol; } @@ -324,6 +294,45 @@ no_lock_bail_out: return false; } +/* + * This routine is meant to be called once the first pass + * to ensure that we have a candidate volume to mount. + * Otherwise, we ask the sysop to created one. + */ +bool DCR::find_a_volume() +{ + DCR *dcr = this; + if (!is_suitable_volume_mounted()) { + bool have_vol = false; + /* Do we have a candidate volume? */ + if (dev->vol) { + bstrncpy(VolumeName, dev->vol->vol_name, sizeof(VolumeName)); + have_vol = dir_get_volume_info(this, GET_VOL_INFO_FOR_WRITE); + } + /* + * Get Director's idea of what tape we should have mounted. + * in dcr->VolCatInfo + */ + if (!have_vol) { + Dmsg0(200, "Before dir_find_next_appendable_volume.\n"); + while (!dir_find_next_appendable_volume(dcr)) { + Dmsg0(200, "not dir_find_next\n"); + if (job_canceled(jcr)) { + unlock_volumes(); + return false; + } + unlock_volumes(); + if (!dir_ask_sysop_to_create_appendable_volume(dcr)) { + return false; + } + lock_volumes(); + Dmsg0(150, "Again dir_find_next_append...\n"); + } + } + } + return true; +} + int DCR::check_volume_label(bool &ask, bool &autochanger) { int vol_label_status; @@ -357,6 +366,12 @@ int DCR::check_volume_label(bool &ask, bool &autochanger) VOLUME_CAT_INFO dcrVolCatInfo, devVolCatInfo; char saveVolumeName[MAX_NAME_LENGTH]; + Dmsg1(150, "Vol NAME Error Name=%s\n", VolumeName); + if (dev->is_volume_to_unload()) { + ask = true; + goto check_next_volume; + } + /* If not removable, Volume is broken */ if (!dev->is_removable()) { Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"), @@ -365,13 +380,6 @@ int DCR::check_volume_label(bool &ask, bool &autochanger) goto check_next_volume; } - Dmsg1(150, "Vol NAME Error Name=%s\n", VolumeName); - /* If polling and got a previous bad name, ignore it */ - if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) { - ask = true; - Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n", VolumeName); - goto check_next_volume; - } /* * OK, we got a different volume mounted. First save the * requested Volume info (dcr) structure, then query if @@ -398,7 +406,7 @@ int DCR::check_volume_label(bool &ask, bool &autochanger) mark_volume_not_inchanger(); } dev->VolCatInfo = devVolCatInfo; /* structure assignment */ - bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName)); + dev->set_unload(); /* unload this volume */ Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n" " Current Volume \"%s\" not acceptable because:\n" " %s"), @@ -416,6 +424,13 @@ int DCR::check_volume_label(bool &ask, bool &autochanger) */ Dmsg1(150, "Got new Volume name=%s\n", VolumeName); dev->VolCatInfo = VolCatInfo; /* structure assignment */ + Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName); + if (reserve_volume(this, dev->VolHdr.VolumeName) == NULL) { + Jmsg2(jcr, M_WARNING, 0, _("Could not reserve volume %s on %s\n"), + dev->VolHdr.VolumeName, dev->print_name()); + ask = true; + goto check_next_volume; + } break; /* got a Volume */ /* * At this point, we assume we have a blank tape mounted. @@ -483,9 +498,8 @@ bool DCR::is_suitable_volume_mounted() void DCR::do_swapping(bool is_writing) { if (dev->must_unload()) { - Dmsg1(100, "swapping: unloading %s\n", dev->print_name()); + Dmsg1(100, "must_unload release %s\n", dev->print_name()); release_volume(); - dev->clear_unload(); } /* * See if we are asked to swap the Volume from another device @@ -509,7 +523,7 @@ void DCR::do_swapping(bool is_writing) dev->swap_dev = NULL; } if (dev->must_load()) { - Dmsg1(100, "swapping: must load %s\n", dev->print_name()); + Dmsg1(100, "Must load %s\n", dev->print_name()); if (autoload_device(this, is_writing, NULL) > 0) { dev->clear_load(); } @@ -653,6 +667,7 @@ void DCR::mark_volume_in_error() Dmsg0(150, "dir_update_vol_info. Set Error.\n"); dir_update_volume_info(this, false, false); volume_unused(this); + Dmsg0(50, "set_unload\n"); dev->set_unload(); /* must get a new volume */ } @@ -691,7 +706,6 @@ void DCR::release_volume() dev->block_num = dev->file = 0; dev->EndBlock = dev->EndFile = 0; memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo)); -// memset(&VolCatInfo, 0, sizeof(VolCatInfo)); dev->clear_volhdr(); /* Force re-read of label */ dev->clear_labeled(); @@ -708,7 +722,8 @@ void DCR::release_volume() if (dev->is_open()) { dev->offline_or_rewind(); } - dev->set_unload(); +// Dmsg0(50, "set_unload\n"); +// dev->set_unload(); Dmsg0(190, "release_volume\n"); } diff --git a/bacula/src/stored/pythonsd.c b/bacula/src/stored/pythonsd.c index 9bcfc1b8f4..1db1aa5423 100644 --- a/bacula/src/stored/pythonsd.c +++ b/bacula/src/stored/pythonsd.c @@ -59,7 +59,7 @@ PyMethodDef JobMethods[] = { struct s_vars { const char *name; - char *fmt; + const char *fmt; }; static struct s_vars getvars[] = { diff --git a/bacula/src/stored/reserve.c b/bacula/src/stored/reserve.c index 175062fc14..929ba8e86a 100644 --- a/bacula/src/stored/reserve.c +++ b/bacula/src/stored/reserve.c @@ -349,7 +349,6 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName) } Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n", jid(), vol->vol_name, vol->vol_name); free_volume(dev); -// volume_unused(dcr); dev->set_unload(); /* have to unload current volume */ debug_list_volumes("reserve_vol free"); } @@ -390,7 +389,6 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName) Dmsg4(dbglvl, "==== jid=%u Swap vol=%s from dev=%s to %s\n", jid(), VolumeName, vol->dev->print_name(), dev->print_name()); free_volume(dev); /* free any volume attached to our drive */ -// volume_unused(dcr); dev->set_unload(); /* Unload any volume that is on our drive */ dcr->dev = vol->dev; /* temp point to other dev */ slot = get_autochanger_loaded_slot(dcr); /* get slot on other drive */ diff --git a/bacula/src/stored/wait.c b/bacula/src/stored/wait.c index 53fa5eba0f..b443fd335f 100644 --- a/bacula/src/stored/wait.c +++ b/bacula/src/stored/wait.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2007 Free Software Foundation Europe e.V. + Copyright (C) 2000-2008 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. diff --git a/bacula/src/version.h b/bacula/src/version.h index 4d29dc13dc..02f67816ba 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,8 @@ #undef VERSION #define VERSION "2.4.1" -#define BDATE "26 June 2008" -#define LSMDATE "26Jun08" +#define BDATE "30 June 2008" +#define LSMDATE "30Jun08" #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.3 b/bacula/technotes-2.3 index a379e5efd4..0c97381262 100644 --- a/bacula/technotes-2.3 +++ b/bacula/technotes-2.3 @@ -1,6 +1,12 @@ Technical notes on version 2.2 General: +27Jun08 +kes Generally clean up the manual tape loading code. The main + conceptial change is that when a volume is marked to be unloaded, + its volume name is retained, and it is only marked as unloaded + when either the autoloader says it is unloaded or another tape + is read on that drive. 26Jun08 kes Fix a recycling problem with two autochangers reported in bug #1106. This may also (unlikely) fix a second recycling bug as