X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Freserve.c;h=8d92efc5346fbac06e0395cdbc03f89f9ebb0c68;hb=0dfe1e722e6d2f70a4d0f562f60a5db48038c16b;hp=9c7960e684cfe06fe5b5afdc8c527ef1d69ffaca;hpb=3083e1a976968f66a025c160566112a49123721a;p=bacula%2Fbacula diff --git a/bacula/src/stored/reserve.c b/bacula/src/stored/reserve.c index 9c7960e684..8d92efc534 100644 --- a/bacula/src/stored/reserve.c +++ b/bacula/src/stored/reserve.c @@ -53,6 +53,7 @@ static bool reserve_device_for_append(DCR *dcr, RCTX &rctx); static bool use_storage_cmd(JCR *jcr); static void queue_reserve_message(JCR *jcr); static void pop_reserve_messages(JCR *jcr); +//void switch_device(DCR *dcr, DEVICE *dev); /* Requests from the Director daemon */ static char use_storage[] = "use storage=%127s media_type=%127s " @@ -177,10 +178,11 @@ static void debug_list_volumes(const char *imsg) lock_volumes(); foreach_dlist(vol, vol_list) { if (vol->dev) { - Mmsg(msg, "List %s: %s rel=%d on device %s\n", imsg, - vol->vol_name, vol->released, vol->dev->print_name()); + Mmsg(msg, "List %s: %s in_use=%d on device %s\n", imsg, + vol->vol_name, vol->is_in_use(), vol->dev->print_name()); } else { - Mmsg(msg, "List %s: %s rel=%d no dev\n", imsg, vol->vol_name, vol->released); + Mmsg(msg, "List %s: %s in_use=%d no dev\n", imsg, vol->vol_name, + vol->is_in_use()); } Dmsg1(dbglvl, "%s", msg.c_str()); } @@ -196,7 +198,6 @@ static void debug_list_volumes(const char *imsg) } #endif -// Dmsg2(dbglvl, "List from %s: %d volumes\n", imsg, count); unlock_volumes(); } @@ -216,11 +217,13 @@ void list_volumes(void sendit(const char *msg, int len, void *sarg), void *arg) if (dev) { len = Mmsg(msg, "%s on device %s\n", vol->vol_name, dev->print_name()); sendit(msg.c_str(), len, arg); - len = Mmsg(msg, " Reader=%d writers=%d reserved=%d released=%d\n", - dev->can_read()?1:0, dev->num_writers, dev->reserved_device, vol->released); + len = Mmsg(msg, " Reader=%d writers=%d devres=%d volinuse=%d\n", + dev->can_read()?1:0, dev->num_writers, dev->num_reserved(), + vol->is_in_use()); sendit(msg.c_str(), len, arg); } else { - len = Mmsg(msg, "%s no device. released=%d\n", vol->vol_name, vol->released); + len = Mmsg(msg, "%s no device. volinuse= %d\n", vol->vol_name, + vol->is_in_use()); sendit(msg.c_str(), len, arg); } } @@ -245,14 +248,18 @@ static VOLRES *new_vol_item(DCR *dcr, const char *VolumeName) static void free_vol_item(VOLRES *vol) { + DEVICE *dev = NULL; + free(vol->vol_name); if (vol->dev) { - vol->dev->vol = NULL; + dev = vol->dev; } free(vol); + if (dev) { + dev->vol = NULL; + } } - /* * Put a new Volume entry in the Volume list. This * effectively reserves the volume so that it will @@ -269,7 +276,7 @@ static void free_vol_item(VOLRES *vol) * * 1. The Volume list entry must be attached to the drive (rather than * attached to a job as it currently is. I.e. the drive that "owns" - * the volume (reserved, in use, mounted) + * the volume (in use, mounted) * must point to the volume (still to be maintained in a list). * * 2. The Volume is entered in the list when a drive is reserved. @@ -310,11 +317,12 @@ static void free_vol_item(VOLRES *vol) VOLRES *reserve_volume(DCR *dcr, const char *VolumeName) { VOLRES *vol, *nvol; - DEVICE *dev = dcr->dev; + DEVICE * volatile dev = dcr->dev; ASSERT(dev != NULL); - Dmsg1(dbglvl, "enter reserve_volume %s\n", VolumeName); + Dmsg2(dbglvl, "enter reserve_volume=%s drive=%s\n", VolumeName, + dcr->dev->print_name()); /* * We lock the reservations system here to ensure * when adding a new volume that no newly scheduled @@ -328,20 +336,29 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName) */ if (dev->vol) { vol = dev->vol; - Dmsg4(dbglvl, "Vol attached=%s, newvol=%s release=%d on %s\n", - vol->vol_name, VolumeName, vol->released, dev->print_name()); + Dmsg4(dbglvl, "Vol attached=%s, newvol=%s volinuse=%d on %s\n", + vol->vol_name, VolumeName, vol->is_in_use(), dev->print_name()); /* * Make sure we don't remove the current volume we are inserting * because it was probably inserted by another job, or it - * is not being used and is marked as released. + * is not being used and is marked as not reserved. */ if (strcmp(vol->vol_name, VolumeName) == 0) { - Dmsg1(dbglvl, "=== OK, vol=%s on device. set not released.\n", VolumeName); + Dmsg2(dbglvl, "=== set reserved vol=%s dev=%s\n", VolumeName, + vol->dev->print_name()); + vol->set_in_use(); /* retake vol if released previously */ + dcr->reserved_volume = true; /* reserved volume */ goto get_out; /* Volume already on this device */ } else { + /* Don't release a volume if it was reserved by someone other than us */ + if (vol->is_in_use() && !dcr->reserved_volume) { + Dmsg1(dbglvl, "Cannot free vol=%s. It is reserved.\n", vol->vol_name); + vol = NULL; /* vol in use */ + goto get_out; + } Dmsg2(dbglvl, "reserve_vol free vol=%s at %p\n", vol->vol_name, vol->vol_name); - unload_autochanger(dcr, -1); /* unload the volume */ free_volume(dev); + dev->set_unload(); /* have to unload current volume */ debug_list_volumes("reserve_vol free"); } } @@ -366,35 +383,44 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName) * Clear dev pointer so that free_vol_item() doesn't * take away our volume. */ - nvol->dev = NULL; /* don't zap dev entry */ + nvol->dev = NULL; /* don't zap dev entry */ free_vol_item(nvol); /* Check if we are trying to use the Volume on a different drive */ if (dev != vol->dev) { /* Caller wants to switch Volume to another device */ - if (!vol->dev->is_busy()) { - /* OK to move it -- I'm not sure this will work */ - Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", VolumeName, - vol->dev->print_name(), dev->print_name()); - vol->dev->vol = NULL; /* take vol from old drive */ - vol->dev->VolHdr.VolumeName[0] = 0; - vol->dev = dev; /* point vol at new drive */ - dev->vol = vol; /* point dev at vol */ - dev->VolHdr.VolumeName[0] = 0; + if (!vol->dev->is_busy() && !vol->is_swapping()) { + Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", + VolumeName, vol->dev->print_name(), dev->print_name()); + free_volume(dev); /* free any volume attached to our drive */ + vol->dev->set_unload(); /* unload our drive */ + vol->set_swapping(); /* swap from other drive */ + dev->swap_dev = vol->dev; /* remember to get this vol */ + vol->dev->set_load(); /* then reload on our drive */ + vol->dev->vol = NULL; /* remove volume from other drive */ + vol->dev = dev; /* point it at our drive */ + dev->vol = vol; /* point our drive at it */ + Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", + VolumeName, vol->dev->print_name(), dev->print_name()); } else { - Dmsg3(dbglvl, "Volume busy could not swap vol=%s from dev=%s to %s\n", + Dmsg3(dbglvl, "==== Swap not possible Vol busy vol=%s from dev=%s to %s\n", VolumeName, vol->dev->print_name(), dev->print_name()); - vol = NULL; /* device busy */ + vol = NULL; /* device busy */ goto get_out; } + } else { + dev->vol = vol; } + } else { + dev->vol = vol; /* point to newly inserted volume */ } - dev->vol = vol; get_out: if (vol) { - Dmsg1(dbglvl, "=== set not released. vol=%s\n", vol->vol_name); - vol->released = false; + Dmsg2(dbglvl, "=== set in_use. vol=%s dev=%s\n", vol->vol_name, + vol->dev->print_name()); + vol->set_in_use(); + dcr->reserved_volume = true; } debug_list_volumes("end new volume"); unlock_volumes(); @@ -405,9 +431,9 @@ get_out: * Switch from current device to given device * (not yet used) */ +#ifdef xxx void switch_device(DCR *dcr, DEVICE *dev) { - // lock_reservations(); DCR save_dcr; dev->dlock(); @@ -423,13 +449,13 @@ void switch_device(DCR *dcr, DEVICE *dev) dcr->VolCatInfo.Slot = save_dcr.VolCatInfo.Slot; bstrncpy(dcr->pool_name, save_dcr.pool_name, sizeof(dcr->pool_name)); bstrncpy(dcr->pool_type, save_dcr.pool_type, sizeof(dcr->pool_type)); - bstrncpy(dcr->dev_name, save_dcr.dev_name, sizeof(dcr->dev_name)); + bstrncpy(dcr->dev_name, dev->dev_name, sizeof(dcr->dev_name)); - dev->reserved_device++; - dcr->reserved_device = true; +// dcr->set_reserved(); dev->dunlock(); } +#endif /* * Search for a Volume name in the Volume list. @@ -437,50 +463,66 @@ void switch_device(DCR *dcr, DEVICE *dev) * Returns: VOLRES entry on success * NULL if the Volume is not in the list */ -VOLRES *find_volume(DCR *dcr) +VOLRES *find_volume(const char *VolumeName) { VOLRES vol, *fvol; /* Do not lock reservations here */ lock_volumes(); - vol.vol_name = bstrdup(dcr->VolumeName); + vol.vol_name = bstrdup(VolumeName); fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare); free(vol.vol_name); - Dmsg2(dbglvl, "find_vol=%s found=%d\n", dcr->VolumeName, fvol!=NULL); + Dmsg2(dbglvl, "find_vol=%s found=%d\n", VolumeName, fvol!=NULL); debug_list_volumes("find_volume"); unlock_volumes(); return fvol; } +void DCR::set_reserved() +{ + m_reserved = true; + Dmsg2(dbglvl, "Inc reserve=%d dev=%s\n", dev->num_reserved(), dev->print_name()); + dev->inc_reserved(); +} + +void DCR::clear_reserved() +{ + if (m_reserved) { + m_reserved = false; + dev->dec_reserved(); + Dmsg2(dbglvl, "Dec reserve=%d dev=%s\n", dev->num_reserved(), dev->print_name()); + } +} + /* * Remove any reservation from a drive and tell the system * that the volume is unused at least by us. */ -void unreserve_device(DCR *dcr) +void DCR::unreserve_device() { - DEVICE *dev = dcr->dev; - if (dcr->reserved_device) { - dcr->reserved_device = false; - dev->reserved_device--; - Dmsg2(dbglvl, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); - dcr->reserved_device = false; + lock_volumes(); + if (is_reserved()) { + clear_reserved(); + reserved_volume = false; /* If we set read mode in reserving, remove it */ if (dev->can_read()) { dev->clear_read(); } if (dev->num_writers < 0) { - Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers); + Jmsg1(jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers); dev->num_writers = 0; } + if (dev->num_reserved() == 0 && dev->num_writers == 0) { + volume_unused(this); + } } - - volume_unused(dcr); + unlock_volumes(); } /* * Free a Volume from the Volume list if it is no longer used * Note, for tape drives we want to remember where the Volume * was when last used, so rather than free the volume entry, - * we simply mark it "released" so when the drive is really + * we simply mark it "not reserved" so when the drive is really * needed for another volume, we can reuse it. * * Returns: true if the Volume found and "removed" from the list @@ -490,19 +532,26 @@ bool volume_unused(DCR *dcr) { DEVICE *dev = dcr->dev; - if (dev->vol == NULL) { + if (!dev->vol) { Dmsg1(dbglvl, "vol_unused: no vol on %s\n", dev->print_name()); debug_list_volumes("null vol cannot unreserve_volume"); return false; } + if (dev->vol->is_swapping()) { + Dmsg1(dbglvl, "vol_unused: vol being swapped on %s\n", dev->print_name()); + debug_list_volumes("swapping vol cannot unreserve_volume"); + return false; + } +#ifdef xxx if (dev->is_busy()) { Dmsg1(dbglvl, "vol_unused: busy on %s\n", dev->print_name()); debug_list_volumes("dev busy cannot unreserve_volume"); return false; } +#endif #ifdef xxx - if (dev->num_writers > 0 || dev->reserved_device > 0) { + if (dev->num_writers > 0 || dev->num_reserved() > 0) { ASSERT(0); } #endif @@ -513,9 +562,9 @@ bool volume_unused(DCR *dcr) * explicitly read in this drive. This allows the SD to remember * where the tapes are or last were. */ - Dmsg3(dbglvl, "=== mark released vol=%s num_writers=%d reserved=%d\n", - dev->vol->vol_name, dev->num_writers, dev->reserved_device); - dev->vol->released = true; + Dmsg4(dbglvl, "=== set not reserved vol=%s num_writers=%d dev_reserved=%d dev=%s\n", + dev->vol->vol_name, dev->num_writers, dev->num_reserved(), dev->print_name()); + dev->vol->clear_in_use(); if (dev->is_tape() || dev->is_autochanger()) { return true; } else { @@ -546,7 +595,7 @@ bool free_volume(DEVICE *dev) free_vol_item(vol); debug_list_volumes("free_volume"); unlock_volumes(); - return vol != NULL; + return true; } @@ -581,30 +630,40 @@ void free_volume_list() unlock_volumes(); } -bool is_volume_in_use(DCR *dcr) +bool DCR::can_i_use_volume() { - VOLRES *vol = find_volume(dcr); + bool rtn = true; + VOLRES *vol; + + lock_volumes(); + vol = find_volume(VolumeName); if (!vol) { - Dmsg1(dbglvl, "Vol=%s not in use.\n", dcr->VolumeName); - return false; /* vol not in list */ + Dmsg1(dbglvl, "Vol=%s not in use.\n", VolumeName); + goto get_out; /* vol not in list */ } ASSERT(vol->dev != NULL); - if (dcr->dev == vol->dev) { /* same device OK */ - Dmsg1(dbglvl, "Vol=%s on same dev.\n", dcr->VolumeName); - return false; + if (dev == vol->dev) { /* same device OK */ + Dmsg1(dbglvl, "Vol=%s on same dev.\n", VolumeName); + goto get_out; } else { - Dmsg3(dbglvl, "Vol=%s on %s we have %s\n", dcr->VolumeName, - vol->dev->print_name(), dcr->dev->print_name()); + Dmsg3(dbglvl, "Vol=%s on %s we have %s\n", VolumeName, + vol->dev->print_name(), dev->print_name()); } + /* ***FIXME*** check this ... */ if (!vol->dev->is_busy()) { - Dmsg2(dbglvl, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name()); - return false; + Dmsg2(dbglvl, "Vol=%s dev=%s not busy.\n", VolumeName, vol->dev->print_name()); + goto get_out; } else { - Dmsg2(dbglvl, "Vol=%s dev=%s busy.\n", dcr->VolumeName, vol->dev->print_name()); + Dmsg2(dbglvl, "Vol=%s dev=%s busy.\n", VolumeName, vol->dev->print_name()); } - Dmsg2(dbglvl, "Vol=%s in use by %s.\n", dcr->VolumeName, vol->dev->print_name()); - return true; + Dmsg2(dbglvl, "Vol=%s in use by %s.\n", VolumeName, vol->dev->print_name()); + rtn = false; + +get_out: + unlock_volumes(); + return rtn; + } @@ -732,9 +791,6 @@ static bool use_storage_cmd(JCR *jcr) rctx.PreferMountedVols = false; rctx.exact_match = false; rctx.autochanger_only = true; - Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n", - rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device, - rctx.autochanger_only, rctx.any_drive); if ((ok = find_suitable_device_for_job(jcr, rctx))) { break; } @@ -747,9 +803,6 @@ static bool use_storage_cmd(JCR *jcr) rctx.try_low_use_drive = false; } rctx.autochanger_only = false; - Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n", - rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device, - rctx.autochanger_only, rctx.any_drive); if ((ok = find_suitable_device_for_job(jcr, rctx))) { break; } @@ -762,25 +815,16 @@ static bool use_storage_cmd(JCR *jcr) rctx.PreferMountedVols = true; rctx.exact_match = true; rctx.autochanger_only = false; - Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n", - rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device, - rctx.autochanger_only, rctx.any_drive); if ((ok = find_suitable_device_for_job(jcr, rctx))) { break; } /* Look for any mounted drive */ rctx.exact_match = false; - Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n", - rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device, - rctx.autochanger_only, rctx.any_drive); if ((ok = find_suitable_device_for_job(jcr, rctx))) { break; } /* Try any drive */ rctx.any_drive = true; - Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n", - rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device, - rctx.autochanger_only, rctx.any_drive); if ((ok = find_suitable_device_for_job(jcr, rctx))) { break; } @@ -855,6 +899,10 @@ static bool is_vol_in_autochanger(RCTX &rctx, VOLRES *vol) /* * Search for a device suitable for this job. + * Note, this routine sets sets rctx.suitable_device if any + * device exists within the SD. The device may not be actually + * useable. + * It also returns if it finds a useable device. */ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx) { @@ -869,9 +917,9 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx) } else { dirstore = jcr->read_store; } - Dmsg4(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n", - rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device, - rctx.autochanger_only); + Dmsg5(dbglvl, "Start find_suit_dev PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n", + rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device, + rctx.autochanger_only, rctx.any_drive); /* * If the appropriate conditions of this if are met, namely that @@ -985,7 +1033,7 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx) debug_list_volumes("=== After free temp table\n"); } if (ok) { - Dmsg1(dbglvl, "got vol %s from in-use vols list\n", rctx.VolumeName); + Dmsg1(dbglvl, "OK dev found. Vol=%s from in-use vols list\n", rctx.VolumeName); return true; } @@ -1006,16 +1054,21 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx) ok = true; break; } else if (stat == 0) { /* device busy */ - Dmsg1(dbglvl, "Suitable device=%s, busy: not use\n", device_name); + Dmsg1(dbglvl, "No usable device=%s, busy: not use\n", device_name); } else { /* otherwise error */ - Dmsg0(dbglvl, "No suitable device found.\n"); + Dmsg0(dbglvl, "No usable device found.\n"); } } if (ok) { break; } } + if (ok) { + Dmsg1(dbglvl, "OK dev found. Vol=%s\n", rctx.VolumeName); + } else { + Dmsg0(dbglvl, "Leave find_suit_dev: no dev found.\n"); + } return ok; } @@ -1044,10 +1097,10 @@ int search_res_for_device(RCTX &rctx) /* Debug code */ if (rctx.store->append == SD_APPEND) { Dmsg2(dbglvl, "Device %s reserved=%d for append.\n", - rctx.device->hdr.name, rctx.jcr->dcr->dev->reserved_device); + rctx.device->hdr.name, rctx.jcr->dcr->dev->num_reserved()); } else { Dmsg2(dbglvl, "Device %s reserved=%d for read.\n", - rctx.device->hdr.name, rctx.jcr->read_dcr->dev->reserved_device); + rctx.device->hdr.name, rctx.jcr->read_dcr->dev->num_reserved()); } return stat; } @@ -1067,10 +1120,10 @@ int search_res_for_device(RCTX &rctx) /* Debug code */ if (rctx.store->append == SD_APPEND) { Dmsg2(dbglvl, "Device %s reserved=%d for append.\n", - rctx.device->hdr.name, rctx.jcr->dcr->dev->reserved_device); + rctx.device->hdr.name, rctx.jcr->dcr->dev->num_reserved()); } else { Dmsg2(dbglvl, "Device %s reserved=%d for read.\n", - rctx.device->hdr.name, rctx.jcr->read_dcr->dev->reserved_device); + rctx.device->hdr.name, rctx.jcr->read_dcr->dev->num_reserved()); } return stat; } @@ -1138,11 +1191,19 @@ static int reserve_device(RCTX &rctx) rctx.jcr->dcr = dcr; Dmsg5(dbglvl, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n", - dcr->dev->reserved_device, + dcr->dev->num_reserved(), dcr->dev_name, dcr->media_type, dcr->pool_name, ok); Dmsg3(dbglvl, "Vol=%s num_writers=%d, have_vol=%d\n", rctx.VolumeName, dcr->dev->num_writers, rctx.have_volume); - if (!rctx.have_volume) { + if (rctx.have_volume) { + Dmsg0(dbglvl, "Call reserve_volume\n"); + if (reserve_volume(dcr, rctx.VolumeName)) { + Dmsg1(dbglvl, "Reserved vol=%s\n", rctx.VolumeName); + } else { + Dmsg1(dbglvl, "Could not reserve vol=%s\n", rctx.VolumeName); + goto bail_out; + } + } else { dcr->any_volume = true; Dmsg0(dbglvl, "no vol, call find_next_appendable_vol.\n"); if (dir_find_next_appendable_volume(dcr)) { @@ -1151,6 +1212,8 @@ static int reserve_device(RCTX &rctx) Dmsg1(dbglvl, "looking for Volume=%s\n", rctx.VolumeName); } else { Dmsg0(dbglvl, "No next volume found\n"); + rctx.have_volume = false; + rctx.VolumeName[0] = 0; /* * If there is at least one volume that is valid and in use, * but we get here, check if we are running with prefers @@ -1158,16 +1221,16 @@ static int reserve_device(RCTX &rctx) * non-used drive and our one and only volume is mounted * elsewhere, so we bail out and retry using that drive. */ - if (dcr->volume_in_use && !rctx.PreferMountedVols) { + if (dcr->found_in_use() && !rctx.PreferMountedVols) { rctx.PreferMountedVols = true; if (dcr->VolumeName[0]) { - volume_unused(dcr); + dcr->unreserve_device(); } goto bail_out; } /* * Note. Under some circumstances, the Director can hand us - * a Volume name that is no the same as the one on the current + * a Volume name that is not the same as the one on the current * drive, and in that case, the call above to find the next * volume will fail because in attempting to reserve the Volume * the code will realize that we already have a tape mounted, @@ -1178,12 +1241,10 @@ static int reserve_device(RCTX &rctx) */ if (dcr->dev->num_writers != 0) { if (dcr->VolumeName[0]) { - volume_unused(dcr); + dcr->unreserve_device(); } goto bail_out; } - rctx.have_volume = false; - rctx.VolumeName[0] = 0; } } } else { @@ -1191,7 +1252,7 @@ static int reserve_device(RCTX &rctx) if (ok) { rctx.jcr->read_dcr = dcr; Dmsg5(dbglvl, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n", - dcr->dev->reserved_device, + dcr->dev->num_reserved(), dcr->dev_name, dcr->media_type, dcr->pool_name, ok); } } @@ -1214,7 +1275,6 @@ static int reserve_device(RCTX &rctx) bail_out: rctx.have_volume = false; rctx.VolumeName[0] = 0; -// free_dcr(dcr); Dmsg0(dbglvl, "Not OK.\n"); return 0; } @@ -1246,7 +1306,7 @@ static bool reserve_device_for_read(DCR *dcr) if (dev->is_busy()) { Dmsg4(dbglvl, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(), - dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device); + dev->state & ST_READ?1:0, dev->num_writers, dev->num_reserved()); Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"), jcr->JobId, dev->print_name()); queue_reserve_message(jcr); @@ -1256,9 +1316,7 @@ static bool reserve_device_for_read(DCR *dcr) dev->clear_append(); dev->set_read(); ok = true; - dev->reserved_device++; - Dmsg3(dbglvl, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, dev->print_name(), dev); - dcr->reserved_device = true; + dcr->set_reserved(); bail_out: dev->dunlock(); @@ -1317,10 +1375,7 @@ static bool reserve_device_for_append(DCR *dcr, RCTX &rctx) goto bail_out; } - dev->reserved_device++; - Dmsg3(dbglvl, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, - dev->print_name(), dev); - dcr->reserved_device = true; + dcr->set_reserved(); ok = true; bail_out: @@ -1344,7 +1399,7 @@ static int is_pool_ok(DCR *dcr) Mmsg(jcr->errmsg, _( "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"), (uint32_t)jcr->JobId, dcr->pool_name, dev->pool_name, - dev->reserved_device, dev->print_name()); + dev->num_reserved(), dev->print_name()); queue_reserve_message(jcr); Dmsg2(dbglvl, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n", dev->pool_name, dcr->pool_name); @@ -1357,12 +1412,16 @@ static bool is_max_jobs_ok(DCR *dcr) DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; - Dmsg4(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Vol=%s\n", + Dmsg5(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Status=%s Vol=%s\n", dcr->VolCatInfo.VolCatMaxJobs, - dcr->VolCatInfo.VolCatJobs, dev->reserved_device, + dcr->VolCatInfo.VolCatJobs, dev->num_reserved(), + dcr->VolCatInfo.VolCatStatus, dcr->VolumeName); + if (strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0) { + return true; + } if (dcr->VolCatInfo.VolCatMaxJobs > 0 && dcr->VolCatInfo.VolCatMaxJobs <= - (dcr->VolCatInfo.VolCatJobs + dev->reserved_device)) { + (dcr->VolCatInfo.VolCatJobs + dev->num_reserved())) { /* Max Job Vols depassed or already reserved */ Mmsg(jcr->errmsg, _("3610 JobId=%u Volume max jobs exceeded on drive %s.\n"), (uint32_t)jcr->JobId, dev->print_name()); @@ -1408,13 +1467,13 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx) /* If he wants a free drive, but this one is busy, no go */ if (!rctx.PreferMountedVols && dev->is_busy()) { /* Save least used drive */ - if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) { - rctx.num_writers = dev->num_writers + dev->reserved_device; + if ((dev->num_writers + dev->num_reserved()) < rctx.num_writers) { + rctx.num_writers = dev->num_writers + dev->num_reserved(); rctx.low_use_drive = dev; Dmsg2(dbglvl, "set low use drive=%s num_writers=%d\n", dev->print_name(), rctx.num_writers); } else { - Dmsg1(dbglvl, "not low use num_writers=%d\n", dev->num_writers+dev->reserved_device); + Dmsg1(dbglvl, "not low use num_writers=%d\n", dev->num_writers+dev->num_reserved()); } Dmsg0(dbglvl, "failed: !prefMnt && busy.\n"); Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"), @@ -1455,7 +1514,7 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx) dev->VolHdr.VolumeName, dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName); return 0; } - if (is_volume_in_use(dcr)) { + if (!dcr->can_i_use_volume()) { return 0; /* fail if volume on another drive */ } } @@ -1476,7 +1535,7 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx) */ if (dev->num_writers == 0) { /* Now check if there are any reservations on the drive */ - if (dev->reserved_device) { + if (dev->num_reserved()) { return is_pool_ok(dcr); } else if (dev->can_append()) { if (is_pool_ok(dcr)) { @@ -1484,6 +1543,7 @@ static int can_reserve_drive(DCR *dcr, RCTX &rctx) } else { /* Changing pool, unload old tape if any in drive */ Dmsg0(dbglvl, "OK dev: num_writers=0, not reserved, pool change, unload changer\n"); + /* ***FIXME*** use set_unload() */ unload_autochanger(dcr, 0); } }