2 * Routines to acquire and release a device for read/write
4 * Kern Sibbald, August MMII
9 Copyright (C) 2002-2005 Kern Sibbald
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 version 2 as ammended with additional clauses defined in the
14 file LICENSE in the main source directory.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 the file LICENSE for additional details.
23 #include "bacula.h" /* pull in global headers */
24 #include "stored.h" /* pull in Storage Deamon headers */
26 static int can_reserve_drive(DCR *dcr);
29 * Create a new Device Control Record and attach
30 * it to the device (if this is a real job).
32 DCR *new_dcr(JCR *jcr, DEVICE *dev)
34 if (jcr && jcr->dcr) {
37 DCR *dcr = (DCR *)malloc(sizeof(DCR));
38 memset(dcr, 0, sizeof(DCR));
45 dcr->device = dev->device;
47 dcr->block = new_block(dev);
48 dcr->rec = new_record();
50 dcr->max_job_spool_size = dev->device->max_job_spool_size;
51 /* Attach this dcr only if dev is initialized */
52 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
53 dev->attached_dcrs->append(dcr); /* attach dcr to device */
54 // jcr->dcrs->append(dcr); /* put dcr in list for Job */
60 * Search the dcrs list for the given dcr. If it is found,
61 * as it should be, then remove it. Also zap the jcr pointer
62 * to the dcr if it is the same one.
65 static void remove_dcr_from_dcrs(DCR *dcr)
71 int num = jcr->dcrs->size();
72 for (i=0; i < num; i++) {
73 ldcr = (DCR *)jcr->dcrs->get(i);
76 if (jcr->dcr == dcr) {
86 * Free up all aspects of the given dcr -- i.e. dechain it,
87 * release allocated memory, zap pointers, ...
89 void free_dcr(DCR *dcr)
92 DEVICE *dev = dcr->dev;
95 * If we reserved the device, we must decrement the
98 if (dcr->reserved_device) {
101 if (dev->num_writers < 0) {
102 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
103 dev->num_writers = 0;
104 dcr->reserved_device = false;
109 /* Detach this dcr only if the dev is initialized */
110 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
111 dev->attached_dcrs->remove(dcr); /* detach dcr from device */
112 // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
115 free_block(dcr->block);
118 free_record(dcr->rec);
121 dcr->jcr->dcr = NULL;
128 * We "reserve" the drive by setting the ST_READ bit. No one else
129 * should touch the drive until that is cleared.
130 * This allows the DIR to "reserve" the device before actually
133 bool reserve_device_for_read(DCR *dcr)
135 DEVICE *dev = dcr->dev;
141 dev->block(BST_DOING_ACQUIRE);
143 if (device_is_unmounted(dev)) {
144 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
149 if (dev->is_busy()) {
150 Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
165 /*********************************************************************
166 * Acquire device for reading.
167 * The drive should have previously been reserved by calling
168 * reserve_device_for_read(). We read the Volume label from the block and
169 * leave the block pointers just after the label.
171 * Returns: NULL if failed for any reason
174 DCR *acquire_device_for_read(DCR *dcr)
176 DEVICE *dev = dcr->dev;
179 bool tape_previously_mounted;
180 bool tape_initially_mounted;
182 bool try_autochanger = true;
184 int vol_label_status;
186 dev->block(BST_DOING_ACQUIRE);
188 if (dev->num_writers > 0) {
189 Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"),
190 dev->num_writers, jcr->JobId);
194 /* Find next Volume, if any */
197 Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
201 for (i=1; i<jcr->CurVolume; i++) {
205 goto get_out; /* should not happen */
207 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
209 init_device_wait_timers(dcr);
211 tape_previously_mounted = dev->can_read() || dev->can_append() ||
213 tape_initially_mounted = tape_previously_mounted;
216 /* Volume info is always needed because of VolParts */
217 Dmsg0(200, "dir_get_volume_info\n");
218 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
219 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
222 dev->num_parts = dcr->VolCatInfo.VolCatParts;
224 for (i=0; i<5; i++) {
225 dev->clear_labeled(); /* force reread of label */
226 if (job_canceled(jcr)) {
227 Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
228 goto get_out; /* error return */
231 * This code ensures that the device is ready for
232 * reading. If it is a file, it opens it.
233 * If it is a tape, it checks the volume name
235 for ( ; !dev->is_open(); ) {
236 Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName);
237 if (open_dev(dev, dcr->VolumeName, OPEN_READ_ONLY) < 0) {
238 if (dev->dev_errno == EIO) { /* no tape loaded */
239 Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
240 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
244 /* If we have a dvd that requires mount,
245 * we need to try to open the label, so the info can be reported
246 * if a wrong volume has been mounted. */
247 if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) {
251 Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
252 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
255 Dmsg1(129, "open_dev %s OK\n", dev->print_name());
259 vol_label_status = read_dev_volume_label_guess(dcr, 0);
261 vol_label_status = read_dev_volume_label(dcr);
264 Dmsg0(200, "calling read-vol-label\n");
265 switch (vol_label_status) {
268 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
272 * Send error message generated by read_dev_volume_label()
273 * only we really had a tape mounted. This supresses superfluous
274 * error messages when nothing is mounted.
276 if (tape_previously_mounted) {
277 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
281 if (tape_initially_mounted) {
282 tape_initially_mounted = false;
287 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
289 tape_previously_mounted = true;
291 /* If the device requires mount, close it, so the device can be ejected.
292 * FIXME: This should perhaps be done for all devices. */
293 if (dev_cap(dev, CAP_REQMOUNT)) {
294 force_close_dev(dev);
297 /* Call autochanger only once unless ask_sysop called */
298 if (try_autochanger) {
300 Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
301 dcr->VolumeName, dcr->VolCatInfo.Slot);
302 stat = autoload_device(dcr, 0, NULL);
304 try_autochanger = false;
305 continue; /* try reading volume mounted */
309 /* Mount a specific volume and no other */
310 Dmsg0(200, "calling dir_ask_sysop\n");
311 if (!dir_ask_sysop_to_mount_volume(dcr)) {
312 goto get_out; /* error return */
314 try_autochanger = true; /* permit using autochanger again */
315 continue; /* try reading again */
320 Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
327 set_jcr_job_status(jcr, JS_Running);
328 dir_send_job_status(jcr);
329 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
330 dcr->VolumeName, dev->print_name());
342 * We reserve the device for appending by incrementing the
343 * reserved_device. We do virtually all the same work that
344 * is done in acquire_device_for_append(), but we do
345 * not attempt to mount the device. This routine allows
346 * the DIR to reserve multiple devices before *really*
347 * starting the job. It also permits the SD to refuse
348 * certain devices (not up, ...).
350 * Note, in reserving a device, if the device is for the
351 * same pool and the same pool type, then it is acceptable.
352 * The Media Type has already been checked. If we are
353 * the first tor reserve the device, we put the pool
354 * name and pool type in the device record.
356 bool reserve_device_for_append(DCR *dcr)
359 DEVICE *dev = dcr->dev;
364 dev->block(BST_DOING_ACQUIRE);
366 if (dev->can_read()) {
367 Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
371 if (device_is_unmounted(dev)) {
372 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
376 Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
378 if (can_reserve_drive(dcr) != 1) {
379 Mmsg1(jcr->errmsg, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
383 dev->reserved_device++;
384 dcr->reserved_device = true;
393 * Returns: 1 if drive can be reserved
394 * 0 if we should wait
397 static int can_reserve_drive(DCR *dcr)
399 DEVICE *dev = dcr->dev;
402 * First handle the case that the drive is not yet in append mode
404 if (!dev->can_append() && dev->num_writers == 0) {
405 /* Now check if there are any reservations on the drive */
406 if (dev->reserved_device) {
407 /* Yes, now check if we want the same Pool and pool type */
408 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
409 strcmp(dev->pool_type, dcr->pool_type) == 0) {
410 /* OK, compatible device */
412 /* Drive not suitable for us */
416 /* Device is available but not yet reserved, reserve it for us */
417 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
418 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
420 return 1; /* reserve drive */
424 * Check if device in append mode with no writers (i.e. available)
426 if (dev->can_append() && dev->num_writers == 0) {
427 /* Device is available but not yet reserved, reserve it for us */
428 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
429 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
434 * Now check if the device is in append mode with writers (i.e.
435 * available if pool is the same).
437 if (dev->can_append() || dev->num_writers > 0) {
438 Dmsg0(190, "device already in append.\n");
439 /* Yes, now check if we want the same Pool and pool type */
440 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
441 strcmp(dev->pool_type, dcr->pool_type) == 0) {
442 /* OK, compatible device */
444 /* Drive not suitable for us */
445 Jmsg(jcr, M_WARNING, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
449 Pmsg0(000, "Logic error!!!! Should not get here.\n");
450 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
451 return -1; /* error, should not get here */
453 return 1; /* reserve drive */
457 * Acquire device for writing. We permit multiple writers.
458 * If this is the first one, we read the label.
460 * Returns: NULL if failed for any reason
462 * Note, normally reserve_device_for_append() is called
463 * before this routine.
465 DCR *acquire_device_for_append(DCR *dcr)
467 bool release = false;
468 bool recycle = false;
469 bool do_mount = false;
470 DEVICE *dev = dcr->dev;
473 init_device_wait_timers(dcr);
475 dev->block(BST_DOING_ACQUIRE);
476 Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":"disk");
478 if (dcr->reserved_device) {
479 dev->reserved_device--;
480 dcr->reserved_device = false;
484 * With the reservation system, this should not happen
486 if (dev->can_read()) {
487 Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
491 if (dev->can_append()) {
492 Dmsg0(190, "device already in append.\n");
494 * Device already in append mode
496 * Check if we have the right Volume mounted
497 * OK if current volume info OK
498 * OK if next volume matches current volume
499 * otherwise mount desired volume obtained from
500 * dir_find_next_appendable_volume
502 bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName));
503 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
504 !(dir_find_next_appendable_volume(dcr) &&
505 strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
506 Dmsg0(190, "Wrong tape mounted.\n");
507 if (dev->num_writers != 0 || dev->reserved_device) {
508 Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
511 /* Wrong tape mounted, release it, then fall through to get correct one */
512 Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
517 * At this point, the correct tape is already mounted, so
518 * we do not need to do mount_next_write_volume(), unless
519 * we need to recycle the tape.
521 recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
522 Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
523 if (recycle && dev->num_writers != 0) {
524 Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
525 " on device %s because it is in use by another job.\n"),
526 dev->VolHdr.VolName, dev->print_name());
529 if (dev->num_writers == 0) {
530 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
534 /* Not already in append mode, so mount the device */
535 Dmsg0(190, "Not in append mode, try mount.\n");
536 ASSERT(dev->num_writers == 0);
540 if (do_mount || recycle) {
541 Dmsg0(190, "Do mount_next_write_vol\n");
542 bool mounted = mount_next_write_volume(dcr, release);
544 if (!job_canceled(jcr)) {
545 /* Reduce "noise" -- don't print if job canceled */
546 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
553 dev->num_writers++; /* we are now a writer */
554 if (jcr->NumVolumes == 0) {
560 * If we jump here, it is an error return because
561 * rtn_dev will still be NULL
572 * This job is done, so release the device. From a Unix standpoint,
573 * the device remains open.
576 bool release_device(DCR *dcr)
579 DEVICE *dev = dcr->dev;
583 Dmsg1(100, "release_device device is %s\n", dev->is_tape()?"tape":"disk");
585 /* if device is reserved, job never started, so release the reserve here */
586 if (dcr->reserved_device) {
587 dev->reserved_device--;
588 dcr->reserved_device = false;
591 if (dev->can_read()) {
592 dev->clear_read(); /* clear read bit */
594 /******FIXME**** send read volume usage statistics to director */
596 } else if (dev->num_writers > 0) {
598 * Note if WEOT is set, we are at the end of the tape
599 * and may not be positioned correctly, so the
600 * job_media_record and update_vol_info have already been
601 * done, which means we skip them here.
604 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
605 if (dev->is_labeled()) {
606 Dmsg0(100, "dir_create_jobmedia_record. Release\n");
607 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
608 Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
609 dcr->VolCatInfo.VolCatName, jcr->Job);
611 /* If no more writers, write an EOF */
612 if (!dev->num_writers && dev->can_write()) {
614 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolName);
616 if (!dev->at_weot()) {
617 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
618 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
619 /* Note! do volume update before close, which zaps VolCatInfo */
620 Dmsg0(100, "dir_update_vol_info. Release0\n");
621 dir_update_volume_info(dcr, false); /* send Volume info to Director */
627 * If we reach here, it is most likely because the job
628 * has failed, since the device is not in read mode and
629 * there are no writers. It was probably reserved.
633 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
634 if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
635 offline_or_rewind_dev(dev);
639 /* Fire off Alert command and include any output */
640 if (!job_canceled(jcr) && dcr->device->alert_command) {
644 char line[MAXSTRING];
645 alert = get_pool_memory(PM_FNAME);
646 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
647 bpipe = open_bpipe(alert, 0, "r");
649 while (fgets(line, sizeof(line), bpipe->rfd)) {
650 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
652 status = close_bpipe(bpipe);
658 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
659 alert, be.strerror(status));
662 Dmsg1(400, "alert status=%d\n", status);
663 free_pool_memory(alert);
668 pthread_cond_broadcast(&wait_device_release);