2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Volume management functions for Storage Daemon
33 * Split from reserve.c October 2008
35 * Version $Id: reserve.c 7380 2008-07-14 10:42:59Z kerns $
42 const int dbglvl = 50;
44 static dlist *vol_list = NULL;
45 static brwlock_t vol_list_lock;
47 /* Forward referenced functions */
48 static void free_vol_item(VOLRES *vol);
51 static int my_compare(void *item1, void *item2)
53 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
56 bool is_vol_list_empty()
58 return vol_list->empty();
61 int vol_list_lock_count = 0;
63 void init_vol_list_lock()
66 if ((errstat=rwl_init(&vol_list_lock)) != 0) {
68 Emsg1(M_ABORT, 0, _("Unable to initialize volume list lock. ERR=%s\n"),
69 be.bstrerror(errstat));
73 void term_vol_list_lock()
75 rwl_destroy(&vol_list_lock);
81 * This allows a given thread to recursively call to lock_volumes()
86 vol_list_lock_count++;
87 if ((errstat=rwl_writelock(&vol_list_lock)) != 0) {
89 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
90 errstat, be.bstrerror(errstat));
94 void _unlock_volumes()
97 vol_list_lock_count--;
98 if ((errstat=rwl_writeunlock(&vol_list_lock)) != 0) {
100 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
101 errstat, be.bstrerror(errstat));
105 dlist *dup_vol_list(JCR *jcr)
107 dlist *temp_vol_list;
111 Dmsg0(dbglvl, "lock volumes\n");
114 * Create a temporary copy of the volume list. We do this,
115 * to avoid having the volume list locked during the
116 * call to reserve_device(), which would cause a deadlock.
117 * Note, we may want to add an update counter on the vol_list
118 * so that if it is modified while we are traversing the copy
119 * we can take note and act accordingly (probably redo the
120 * search at least a few times).
122 Dmsg0(dbglvl, "duplicate vol list\n");
123 temp_vol_list = New(dlist(vol, &vol->link));
124 foreach_dlist(vol, vol_list) {
126 VOLRES *tvol = (VOLRES *)malloc(sizeof(VOLRES));
127 memset(tvol, 0, sizeof(VOLRES));
128 tvol->vol_name = bstrdup(vol->vol_name);
129 tvol->dev = vol->dev;
130 nvol = (VOLRES *)temp_vol_list->binary_insert(tvol, my_compare);
132 tvol->dev = NULL; /* don't zap dev entry */
134 Pmsg0(000, "Logic error. Duplicating vol list hit duplicate.\n");
135 Jmsg(jcr, M_WARNING, 0, "Logic error. Duplicating vol list hit duplicate.\n");
138 Dmsg0(dbglvl, "unlock volumes\n");
140 return temp_vol_list;
143 void free_temp_vol_list(dlist *temp_vol_list)
145 dlist *save_vol_list;
148 save_vol_list = vol_list;
149 vol_list = temp_vol_list;
150 free_volume_list(); /* release temp_vol_list */
151 vol_list = save_vol_list;
152 Dmsg0(dbglvl, "deleted temp vol list\n");
153 Dmsg0(dbglvl, "unlock volumes\n");
155 debug_list_volumes("after free temp table");
160 * List Volumes -- this should be moved to status.c
167 void debug_list_volumes(const char *imsg)
170 POOL_MEM msg(PM_MESSAGE);
173 foreach_dlist(vol, vol_list) {
175 Mmsg(msg, "List %s: %s in_use=%d on device %s\n", imsg,
176 vol->vol_name, vol->is_in_use(), vol->dev->print_name());
178 Mmsg(msg, "List %s: %s in_use=%d no dev\n", imsg, vol->vol_name,
181 Dmsg1(dbglvl, "%s", msg.c_str());
189 * List Volumes -- this should be moved to status.c
191 void list_volumes(void sendit(const char *msg, int len, void *sarg), void *arg)
194 POOL_MEM msg(PM_MESSAGE);
198 foreach_dlist(vol, vol_list) {
199 DEVICE *dev = vol->dev;
201 len = Mmsg(msg, "%s on device %s\n", vol->vol_name, dev->print_name());
202 sendit(msg.c_str(), len, arg);
203 len = Mmsg(msg, " Reader=%d writers=%d devres=%d volinuse=%d\n",
204 dev->can_read()?1:0, dev->num_writers, dev->num_reserved(),
206 sendit(msg.c_str(), len, arg);
208 len = Mmsg(msg, "%s no device. volinuse= %d\n", vol->vol_name,
210 sendit(msg.c_str(), len, arg);
217 * Create a Volume item to put in the Volume list
218 * Ensure that the device points to it.
220 static VOLRES *new_vol_item(DCR *dcr, const char *VolumeName)
223 vol = (VOLRES *)malloc(sizeof(VOLRES));
224 memset(vol, 0, sizeof(VOLRES));
225 vol->vol_name = bstrdup(VolumeName);
227 Dmsg3(dbglvl, "new Vol=%s at %p dev=%s\n",
228 VolumeName, vol->vol_name, vol->dev->print_name());
232 static void free_vol_item(VOLRES *vol)
247 * Put a new Volume entry in the Volume list. This
248 * effectively reserves the volume so that it will
249 * not be mounted again.
251 * If the device has any current volume associated with it,
252 * and it is a different Volume, and the device is not busy,
253 * we release the old Volume item and insert the new one.
255 * It is assumed that the device is free and locked so that
256 * we can change the device structure.
258 * Some details of the Volume list handling:
260 * 1. The Volume list entry must be attached to the drive (rather than
261 * attached to a job as it currently is. I.e. the drive that "owns"
262 * the volume (in use, mounted)
263 * must point to the volume (still to be maintained in a list).
265 * 2. The Volume is entered in the list when a drive is reserved.
267 * 3. When a drive is in use, the device code must appropriately update the
268 * volume name as it changes (currently the list is static -- an entry is
269 * removed when the Volume is no longer reserved, in use or mounted).
270 * The new code must keep the same list entry as long as the drive
271 * has any volume associated with it but the volume name in the list
272 * must be updated when the drive has a different volume mounted.
274 * 4. A job that has reserved a volume, can un-reserve the volume, and if the
275 * volume is not mounted, and not reserved, and not in use, it will be
276 * removed from the list.
278 * 5. If a job wants to reserve a drive with a different Volume from the one on
279 * the drive, it can re-use the drive for the new Volume.
281 * 6. If a job wants a Volume that is in a different drive, it can either use the
282 * other drive or take the volume, only if the other drive is not in use or
285 * One nice aspect of this is that the reserve use count and the writer use count
286 * already exist and are correctly programmed and will need no changes -- use
287 * counts are always very tricky.
289 * The old code had a concept of "reserving" a Volume, but was changed
290 * to reserving and using a drive. A volume is must be attached to (owned by) a
291 * drive and can move from drive to drive or be unused given certain specific
292 * conditions of the drive. The key is that the drive must "own" the Volume.
293 * The old code had the job (dcr) owning the volume (more or less). The job was
294 * to change the insertion and removal of the volumes from the list to be based
295 * on the drive rather than the job.
297 * Return: VOLRES entry on success
298 * NULL volume busy on another drive
300 VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
303 DEVICE * volatile dev = dcr->dev;
307 Dmsg2(dbglvl, "enter reserve_volume=%s drive=%s\n", VolumeName,
308 dcr->dev->print_name());
310 * We lock the reservations system here to ensure
311 * when adding a new volume that no newly scheduled
312 * job can reserve it.
315 debug_list_volumes("begin reserve_volume");
317 * First, remove any old volume attached to this device as it
322 Dmsg4(dbglvl, "Vol attached=%s, newvol=%s volinuse=%d on %s\n",
323 vol->vol_name, VolumeName, vol->is_in_use(), dev->print_name());
325 * Make sure we don't remove the current volume we are inserting
326 * because it was probably inserted by another job, or it
327 * is not being used and is marked as not reserved.
329 if (strcmp(vol->vol_name, VolumeName) == 0) {
330 Dmsg2(dbglvl, "=== set reserved vol=%s dev=%s\n", VolumeName,
331 vol->dev->print_name());
332 goto get_out; /* Volume already on this device */
334 /* Don't release a volume if it was reserved by someone other than us */
335 if (vol->is_in_use() && !dcr->reserved_volume) {
336 Dmsg1(dbglvl, "Cannot free vol=%s. It is reserved.\n", vol->vol_name);
337 vol = NULL; /* vol in use */
340 Dmsg2(dbglvl, "reserve_vol free vol=%s at %p\n", vol->vol_name, vol->vol_name);
342 Dmsg0(50, "set_unload\n");
343 dev->set_unload(); /* have to unload current volume */
344 debug_list_volumes("reserve_vol free");
348 /* Create a new Volume entry */
349 nvol = new_vol_item(dcr, VolumeName);
352 * Now try to insert the new Volume
354 vol = (VOLRES *)vol_list->binary_insert(nvol, my_compare);
356 Dmsg2(dbglvl, "Found vol=%s dev-same=%d\n", vol->vol_name, dev==vol->dev);
358 * At this point, a Volume with this name already is in the list,
359 * so we simply release our new Volume entry. Note, this should
360 * only happen if we are moving the volume from one drive to another.
362 Dmsg2(dbglvl, "reserve_vol free-tmp vol=%s at %p\n",
363 vol->vol_name, vol->vol_name);
365 * Clear dev pointer so that free_vol_item() doesn't
366 * take away our volume.
368 nvol->dev = NULL; /* don't zap dev entry */
372 * Check if we are trying to use the Volume on a different drive
374 * vol->dev is where the Volume we want is
376 if (dev != vol->dev) {
377 /* Caller wants to switch Volume to another device */
378 if (!vol->dev->is_busy() && !vol->is_swapping()) {
380 Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n",
381 VolumeName, vol->dev->print_name(), dev->print_name());
382 free_volume(dev); /* free any volume attached to our drive */
383 Dmsg0(50, "set_unload\n");
384 dev->set_unload(); /* Unload any volume that is on our drive */
385 dcr->dev = vol->dev; /* temp point to other dev */
386 slot = get_autochanger_loaded_slot(dcr); /* get slot on other drive */
387 dcr->dev = dev; /* restore dev */
388 vol->set_slot(slot); /* save slot */
389 vol->dev->set_unload(); /* unload the other drive */
390 vol->set_swapping(); /* swap from other drive */
391 dev->swap_dev = vol->dev; /* remember to get this vol */
392 dev->set_load(); /* then reload on our drive */
393 vol->dev->vol = NULL; /* remove volume from other drive */
394 vol->dev = dev; /* point the Volume at our drive */
395 dev->vol = vol; /* point our drive at the Volume */
397 Dmsg3(dbglvl, "==== Swap not possible Vol busy vol=%s from dev=%s to %s\n",
398 VolumeName, vol->dev->print_name(), dev->print_name());
399 vol = NULL; /* device busy */
406 dev->vol = vol; /* point to newly inserted volume */
411 Dmsg2(dbglvl, "=== set in_use. vol=%s dev=%s\n", vol->vol_name,
412 vol->dev->print_name());
414 dcr->reserved_volume = true;
415 bstrncpy(dcr->VolumeName, vol->vol_name, sizeof(dcr->VolumeName));
417 debug_list_volumes("end new volume");
423 * Switch from current device to given device
427 void switch_device(DCR *dcr, DEVICE *dev)
432 memcpy(&save_dcr, dcr, sizeof(save_dcr));
433 clean_device(dcr); /* clean up the dcr */
435 dcr->dev = dev; /* get new device pointer */
436 Jmsg(dcr->jcr, M_INFO, 0, _("Device switch. New device %s chosen.\n"),
437 dcr->dev->print_name());
439 bstrncpy(dcr->VolumeName, save_dcr.VolumeName, sizeof(dcr->VolumeName));
440 bstrncpy(dcr->media_type, save_dcr.media_type, sizeof(dcr->media_type));
441 dcr->VolCatInfo.Slot = save_dcr.VolCatInfo.Slot;
442 bstrncpy(dcr->pool_name, save_dcr.pool_name, sizeof(dcr->pool_name));
443 bstrncpy(dcr->pool_type, save_dcr.pool_type, sizeof(dcr->pool_type));
444 bstrncpy(dcr->dev_name, dev->dev_name, sizeof(dcr->dev_name));
446 // dcr->set_reserved();
453 * Search for a Volume name in the Volume list.
455 * Returns: VOLRES entry on success
456 * NULL if the Volume is not in the list
458 VOLRES *find_volume(const char *VolumeName)
461 /* Do not lock reservations here */
463 vol.vol_name = bstrdup(VolumeName);
464 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
466 Dmsg2(dbglvl, "find_vol=%s found=%d\n", VolumeName, fvol!=NULL);
467 debug_list_volumes("find_volume");
473 * Free a Volume from the Volume list if it is no longer used
474 * Note, for tape drives we want to remember where the Volume
475 * was when last used, so rather than free the volume entry,
476 * we simply mark it "not reserved" so when the drive is really
477 * needed for another volume, we can reuse it.
479 * Returns: true if the Volume found and "removed" from the list
480 * false if the Volume is not in the list or is in use
482 bool volume_unused(DCR *dcr)
484 DEVICE *dev = dcr->dev;
487 Dmsg1(dbglvl, "vol_unused: no vol on %s\n", dev->print_name());
488 debug_list_volumes("null vol cannot unreserve_volume");
491 if (dev->vol->is_swapping()) {
492 Dmsg1(dbglvl, "vol_unused: vol being swapped on %s\n", dev->print_name());
493 Dmsg1(dbglvl, "=== clear in_use vol=%s\n", dev->vol->vol_name);
494 dev->vol->clear_in_use();
495 debug_list_volumes("swapping vol cannot free_volume");
500 * If this is a tape, we do not free the volume, rather we wait
501 * until the autoloader unloads it, or until another tape is
502 * explicitly read in this drive. This allows the SD to remember
503 * where the tapes are or last were.
505 Dmsg4(dbglvl, "=== set not reserved vol=%s num_writers=%d dev_reserved=%d dev=%s\n",
506 dev->vol->vol_name, dev->num_writers, dev->num_reserved(), dev->print_name());
507 Dmsg1(dbglvl, "=== clear in_use vol=%s\n", dev->vol->vol_name);
508 dev->vol->clear_in_use();
509 if (dev->is_tape() || dev->is_autochanger()) {
513 * Note, this frees the volume reservation entry, but the
514 * file descriptor remains open with the OS.
516 return free_volume(dev);
521 * Unconditionally release the volume entry
523 bool free_volume(DEVICE *dev)
527 if (dev->vol == NULL) {
528 Dmsg1(dbglvl, "No vol on dev %s\n", dev->print_name());
533 /* Don't free a volume while it is being swapped */
534 if (!vol->is_swapping()) {
535 Dmsg1(dbglvl, "=== clear in_use vol=%s\n", dev->vol->vol_name);
537 vol_list->remove(vol);
538 Dmsg2(dbglvl, "=== remove volume %s dev=%s\n", vol->vol_name, dev->print_name());
540 debug_list_volumes("free_volume");
547 /* Create the Volume list */
548 void create_volume_list()
551 if (vol_list == NULL) {
552 vol_list = New(dlist(vol, &vol->link));
556 /* Release all Volumes from the list */
557 void free_volume_list()
564 foreach_dlist(vol, vol_list) {
566 Dmsg2(dbglvl, "free vol_list Volume=%s dev=%s\n", vol->vol_name, vol->dev->print_name());
568 Dmsg1(dbglvl, "free vol_list Volume=%s No dev\n", vol->vol_name);
571 vol->vol_name = NULL;
578 bool DCR::can_i_use_volume()
584 vol = find_volume(VolumeName);
586 Dmsg1(dbglvl, "Vol=%s not in use.\n", VolumeName);
587 goto get_out; /* vol not in list */
589 ASSERT(vol->dev != NULL);
591 if (dev == vol->dev) { /* same device OK */
592 Dmsg1(dbglvl, "Vol=%s on same dev.\n", VolumeName);
595 Dmsg3(dbglvl, "Vol=%s on %s we have %s\n", VolumeName,
596 vol->dev->print_name(), dev->print_name());
598 /* ***FIXME*** check this ... */
599 if (!vol->dev->is_busy()) {
600 Dmsg2(dbglvl, "Vol=%s dev=%s not busy.\n", VolumeName, vol->dev->print_name());
603 Dmsg2(dbglvl, "Vol=%s dev=%s busy.\n", VolumeName, vol->dev->print_name());
605 Dmsg2(dbglvl, "Vol=%s in use by %s.\n", VolumeName, vol->dev->print_name());