2 * Routines to acquire and release a device for read/write
4 * Kern Sibbald, August MMII
9 Copyright (C) 2002-2006 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 amended 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 /* Forward referenced functions */
27 static void attach_dcr_to_dev(DCR *dcr);
30 /*********************************************************************
31 * Acquire device for reading.
32 * The drive should have previously been reserved by calling
33 * reserve_device_for_read(). We read the Volume label from the block and
34 * leave the block pointers just after the label.
36 * Returns: NULL if failed for any reason
39 bool acquire_device_for_read(DCR *dcr)
41 DEVICE *dev = dcr->dev;
44 bool tape_previously_mounted;
45 bool tape_initially_mounted;
47 bool try_autochanger = true;
52 Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
53 dev->block(BST_DOING_ACQUIRE);
55 if (dev->num_writers > 0) {
56 Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"),
57 dev->num_writers, jcr->JobId);
61 /* Find next Volume, if any */
64 Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
68 for (i=1; i<jcr->CurVolume; i++) {
72 goto get_out; /* should not happen */
74 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
75 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
76 dcr->VolCatInfo.Slot = vol->Slot;
79 * If the MediaType requested for this volume is not the
80 * same as the current drive, we attempt to find the same
81 * device that was used to write the orginal volume. If
82 * found, we switch to using that device.
84 Dmsg2(100, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
85 if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
89 DCR *dcr_save = jcr->dcr;
93 memset(&rctx, 0, sizeof(RCTX));
95 jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
96 rctx.any_drive = true;
97 rctx.device_name = vol->device;
99 memset(store, 0, sizeof(DIRSTORE));
100 store->name[0] = 0; /* No dir name */
101 bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
102 bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
103 bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
104 store->append = false;
108 * Note, if search_for_device() succeeds, we get a new_dcr,
109 * which we do not use except for the dev info.
111 stat = search_res_for_device(rctx);
112 release_msgs(jcr); /* release queued messages */
113 unlock_reservations();
115 DCR *new_dcr = jcr->read_dcr;
117 detach_dcr_from_dev(dcr); /* release old device */
118 /* Copy important info from the new dcr */
119 dev = dcr->dev = new_dcr->dev;
121 dcr->device = new_dcr->device;
122 dcr->max_job_spool_size = dcr->device->max_job_spool_size;
123 attach_dcr_to_dev(dcr);
124 new_dcr->VolumeName[0] = 0;
126 dev->block(BST_DOING_ACQUIRE);
127 Jmsg(jcr, M_INFO, 0, _("Media Type change. New device %s chosen.\n"),
129 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
130 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
131 dcr->VolCatInfo.Slot = vol->Slot;
132 bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
133 bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
134 } else if (stat == 0) { /* device busy */
135 Dmsg1(000, "Device %s is busy.\n", vol->device);
138 Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
147 init_device_wait_timers(dcr);
149 tape_previously_mounted = dev->can_read() || dev->can_append() ||
151 tape_initially_mounted = tape_previously_mounted;
154 /* Volume info is always needed because of VolParts */
155 Dmsg0(200, "dir_get_volume_info\n");
156 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
157 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
161 /* If not polling limit retries */
162 if (!dev->poll && retry++ > 10) {
165 dev->clear_labeled(); /* force reread of label */
166 if (job_canceled(jcr)) {
167 Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
168 goto get_out; /* error return */
171 autoload_device(dcr, 0, NULL);
174 * This code ensures that the device is ready for
175 * reading. If it is a file, it opens it.
176 * If it is a tape, it checks the volume name
178 Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
179 if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
180 Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
181 dev->print_name(), dcr->VolumeName, dev->bstrerror());
184 Dmsg1(100, "opened dev %s OK\n", dev->print_name());
186 /* Read Volume Label */
188 Dmsg0(200, "calling read-vol-label\n");
189 vol_label_status = read_dev_volume_label(dcr);
190 switch (vol_label_status) {
193 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
197 * Send error message generated by read_dev_volume_label()
198 * only we really had a tape mounted. This supresses superfluous
199 * error messages when nothing is mounted.
201 if (tape_previously_mounted) {
202 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
206 if (tape_initially_mounted) {
207 tape_initially_mounted = false;
210 /* If polling and got a previous bad name, ignore it */
211 if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
214 bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName));
218 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
220 tape_previously_mounted = true;
223 * If the device requires mount, close it, so the device can be ejected.
225 if (dev->requires_mount()) {
229 /* Call autochanger only once unless ask_sysop called */
230 if (try_autochanger) {
232 Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
233 dcr->VolumeName, dcr->VolCatInfo.Slot);
234 stat = autoload_device(dcr, 0, NULL);
236 try_autochanger = false;
237 continue; /* try reading volume mounted */
241 /* Mount a specific volume and no other */
242 Dmsg0(200, "calling dir_ask_sysop\n");
243 if (!dir_ask_sysop_to_mount_volume(dcr)) {
244 goto get_out; /* error return */
246 try_autochanger = true; /* permit using autochanger again */
247 continue; /* try reading again */
252 Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
259 set_jcr_job_status(jcr, JS_Running);
260 dir_send_job_status(jcr);
261 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
262 dcr->VolumeName, dev->print_name());
266 if (dcr->reserved_device) {
267 dev->reserved_device--;
268 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
269 dcr->reserved_device = false;
273 Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
279 * Acquire device for writing. We permit multiple writers.
280 * If this is the first one, we read the label.
282 * Returns: NULL if failed for any reason
284 * Note, normally reserve_device_for_append() is called
285 * before this routine.
287 DCR *acquire_device_for_append(DCR *dcr)
289 bool release = false;
290 bool recycle = false;
291 bool do_mount = false;
292 DEVICE *dev = dcr->dev;
295 init_device_wait_timers(dcr);
297 dev->block(BST_DOING_ACQUIRE);
298 Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":
299 (dev->is_dvd()?"DVD":"disk"));
302 * With the reservation system, this should not happen
304 if (dev->can_read()) {
305 Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
306 Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
310 if (dev->can_append()) {
311 Dmsg0(190, "device already in append.\n");
313 * Device already in append mode
315 * Check if we have the right Volume mounted
316 * OK if current volume info OK
317 * OK if next volume matches current volume
318 * otherwise mount desired volume obtained from
319 * dir_find_next_appendable_volume
320 * dev->VolHdr.VolumeName is what is in the drive
321 * dcr->VolumeName is what we pass into the routines, or
322 * get back from the subroutines.
324 bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
325 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
326 !(dir_find_next_appendable_volume(dcr) &&
327 strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
328 Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
330 /* Release volume reserved by dir_find_next_appendable_volume() */
331 if (dcr->VolumeName[0]) {
332 free_unused_volume(dcr);
334 if (dev->num_writers != 0) {
335 Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"),
336 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
337 Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",
338 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
341 /* Wrong tape mounted, release it, then fall through to get correct one */
342 Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
347 * At this point, the correct tape is already mounted, so
348 * we do not need to do mount_next_write_volume(), unless
349 * we need to recycle the tape.
351 recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
352 Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
353 if (recycle && dev->num_writers != 0) {
354 Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
355 " on device %s because it is in use by another job.\n"),
356 dev->VolHdr.VolumeName, dev->print_name());
359 if (dev->num_writers == 0) {
360 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
364 /* Not already in append mode, so mount the device */
365 Dmsg0(190, "Not in append mode, try mount.\n");
366 ASSERT(dev->num_writers == 0);
370 if (do_mount || recycle) {
371 Dmsg0(190, "Do mount_next_write_vol\n");
372 bool mounted = mount_next_write_volume(dcr, release);
374 if (!job_canceled(jcr)) {
375 /* Reduce "noise" -- don't print if job canceled */
376 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
378 Dmsg1(200, "Could not ready device %s for append.\n",
383 Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
386 dev->num_writers++; /* we are now a writer */
387 if (jcr->NumVolumes == 0) {
391 if (dcr->reserved_device) {
392 dev->reserved_device--;
393 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
394 dcr->reserved_device = false;
405 if (dcr->reserved_device) {
406 dev->reserved_device--;
407 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
408 dcr->reserved_device = false;
417 * This job is done, so release the device. From a Unix standpoint,
418 * the device remains open.
420 * Note, if we are spooling, we may enter with the device locked.
421 * However, in all cases, unlock the device when leaving.
424 bool release_device(DCR *dcr)
427 DEVICE *dev = dcr->dev;
430 /* lock only if not already locked by this thread */
431 if (!dcr->dev_locked) {
434 Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
436 /* if device is reserved, job never started, so release the reserve here */
437 if (dcr->reserved_device) {
438 dev->reserved_device--;
439 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
440 dcr->reserved_device = false;
443 if (dev->can_read()) {
444 dev->clear_read(); /* clear read bit */
446 /******FIXME**** send read volume usage statistics to director */
448 } else if (dev->num_writers > 0) {
450 * Note if WEOT is set, we are at the end of the tape
451 * and may not be positioned correctly, so the
452 * job_media_record and update_vol_info have already been
453 * done, which means we skip them here.
456 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
457 if (dev->is_labeled()) {
458 Dmsg0(100, "dir_create_jobmedia_record. Release\n");
459 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
460 Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
461 dcr->VolCatInfo.VolCatName, jcr->Job);
463 /* If no more writers, write an EOF */
464 if (!dev->num_writers && dev->can_write()) {
466 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
468 if (!dev->at_weot()) {
469 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
470 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
471 /* Note! do volume update before close, which zaps VolCatInfo */
472 Dmsg0(100, "dir_update_vol_info. Release0\n");
473 dir_update_volume_info(dcr, false); /* send Volume info to Director */
479 * If we reach here, it is most likely because the job
480 * has failed, since the device is not in read mode and
481 * there are no writers. It was probably reserved.
485 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
486 if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
487 dvd_remove_empty_part(dcr); /* get rid of any empty spool part */
491 /* Fire off Alert command and include any output */
492 if (!job_canceled(jcr) && dcr->device->alert_command) {
496 char line[MAXSTRING];
497 alert = get_pool_memory(PM_FNAME);
498 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
499 bpipe = open_bpipe(alert, 0, "r");
501 while (fgets(line, sizeof(line), bpipe->rfd)) {
502 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
504 status = close_bpipe(bpipe);
510 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
511 alert, be.strerror(status));
514 Dmsg1(400, "alert status=%d\n", status);
515 free_pool_memory(alert);
517 dcr->dev_locked = false; /* set no longer locked */
519 if (jcr->read_dcr == dcr) {
520 jcr->read_dcr = NULL;
522 if (jcr->dcr == dcr) {
530 * Create a new Device Control Record and attach
531 * it to the device (if this is a real job).
533 DCR *new_dcr(JCR *jcr, DEVICE *dev)
535 DCR *dcr = (DCR *)malloc(sizeof(DCR));
536 memset(dcr, 0, sizeof(DCR));
540 dcr->device = dev->device;
541 dcr->block = new_block(dev);
542 dcr->rec = new_record();
543 dcr->max_job_spool_size = dev->device->max_job_spool_size;
544 attach_dcr_to_dev(dcr);
551 * Search the dcrs list for the given dcr. If it is found,
552 * as it should be, then remove it. Also zap the jcr pointer
553 * to the dcr if it is the same one.
556 static void remove_dcr_from_dcrs(DCR *dcr)
562 int num = jcr->dcrs->size();
563 for (i=0; i < num; i++) {
564 ldcr = (DCR *)jcr->dcrs->get(i);
566 jcr->dcrs->remove(i);
567 if (jcr->dcr == dcr) {
576 static void attach_dcr_to_dev(DCR *dcr)
578 DEVICE *dev = dcr->dev;
581 if (!dcr->attached_to_dev && dev->is_open() && jcr && jcr->JobType != JT_SYSTEM) {
582 dev->attached_dcrs->append(dcr); /* attach dcr to device */
583 dcr->attached_to_dev = true;
587 void detach_dcr_from_dev(DCR *dcr)
589 DEVICE *dev = dcr->dev;
591 if (dcr->reserved_device) {
592 dcr->reserved_device = false;
594 dev->reserved_device--;
595 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
596 dcr->reserved_device = false;
597 /* If we set read mode in reserving, remove it */
598 if (dev->can_read()) {
601 if (dev->num_writers < 0) {
602 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
603 dev->num_writers = 0;
608 /* Detach this dcr only if attached */
609 if (dcr->attached_to_dev) {
610 dcr->dev->attached_dcrs->remove(dcr); /* detach dcr from device */
611 dcr->attached_to_dev = false;
612 // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
614 free_unused_volume(dcr); /* free unused vols attached to this dcr */
615 pthread_cond_broadcast(&dcr->dev->wait_next_vol);
616 pthread_cond_broadcast(&wait_device_release);
620 * Free up all aspects of the given dcr -- i.e. dechain it,
621 * release allocated memory, zap pointers, ...
623 void free_dcr(DCR *dcr)
626 detach_dcr_from_dev(dcr);
629 free_block(dcr->block);
632 free_record(dcr->rec);
635 dcr->jcr->dcr = NULL;