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 * This code ensures that the device is ready for
172 * reading. If it is a file, it opens it.
173 * If it is a tape, it checks the volume name
175 Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
176 if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
177 if (dev->dev_errno == EIO) { /* no tape loaded */
178 Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
179 dev->print_name(), dcr->VolumeName, dev->bstrerror());
183 Jmsg3(jcr, M_FATAL, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
184 dev->print_name(), dcr->VolumeName, dev->bstrerror());
187 Dmsg1(100, "opened dev %s OK\n", dev->print_name());
189 /* Read Volume Label */
191 Dmsg0(200, "calling read-vol-label\n");
192 vol_label_status = read_dev_volume_label(dcr);
193 switch (vol_label_status) {
196 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
200 * Send error message generated by read_dev_volume_label()
201 * only we really had a tape mounted. This supresses superfluous
202 * error messages when nothing is mounted.
204 if (tape_previously_mounted) {
205 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
209 if (tape_initially_mounted) {
210 tape_initially_mounted = false;
213 /* If polling and got a previous bad name, ignore it */
214 if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
217 bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName));
221 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
223 tape_previously_mounted = true;
226 * If the device requires mount, close it, so the device can be ejected.
228 if (dev->requires_mount()) {
232 /* Call autochanger only once unless ask_sysop called */
233 if (try_autochanger) {
235 Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
236 dcr->VolumeName, dcr->VolCatInfo.Slot);
237 stat = autoload_device(dcr, 0, NULL);
239 try_autochanger = false;
240 continue; /* try reading volume mounted */
244 /* Mount a specific volume and no other */
245 Dmsg0(200, "calling dir_ask_sysop\n");
246 if (!dir_ask_sysop_to_mount_volume(dcr)) {
247 goto get_out; /* error return */
249 try_autochanger = true; /* permit using autochanger again */
250 continue; /* try reading again */
255 Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
262 set_jcr_job_status(jcr, JS_Running);
263 dir_send_job_status(jcr);
264 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
265 dcr->VolumeName, dev->print_name());
269 if (dcr->reserved_device) {
270 dev->reserved_device--;
271 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
272 dcr->reserved_device = false;
276 Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
282 * Acquire device for writing. We permit multiple writers.
283 * If this is the first one, we read the label.
285 * Returns: NULL if failed for any reason
287 * Note, normally reserve_device_for_append() is called
288 * before this routine.
290 DCR *acquire_device_for_append(DCR *dcr)
292 bool release = false;
293 bool recycle = false;
294 bool do_mount = false;
295 DEVICE *dev = dcr->dev;
298 init_device_wait_timers(dcr);
300 dev->block(BST_DOING_ACQUIRE);
301 Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":
302 (dev->is_dvd()?"DVD":"disk"));
305 * With the reservation system, this should not happen
307 if (dev->can_read()) {
308 Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
309 Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
313 if (dev->can_append()) {
314 Dmsg0(190, "device already in append.\n");
316 * Device already in append mode
318 * Check if we have the right Volume mounted
319 * OK if current volume info OK
320 * OK if next volume matches current volume
321 * otherwise mount desired volume obtained from
322 * dir_find_next_appendable_volume
323 * dev->VolHdr.VolumeName is what is in the drive
324 * dcr->VolumeName is what we pass into the routines, or
325 * get back from the subroutines.
327 bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
328 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
329 !(dir_find_next_appendable_volume(dcr) &&
330 strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
331 Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
333 /* Release volume reserved by dir_find_next_appendable_volume() */
334 if (dcr->VolumeName[0]) {
335 free_unused_volume(dcr);
337 if (dev->num_writers != 0) {
338 Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"),
339 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
340 Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",
341 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
344 /* Wrong tape mounted, release it, then fall through to get correct one */
345 Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
350 * At this point, the correct tape is already mounted, so
351 * we do not need to do mount_next_write_volume(), unless
352 * we need to recycle the tape.
354 recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
355 Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
356 if (recycle && dev->num_writers != 0) {
357 Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
358 " on device %s because it is in use by another job.\n"),
359 dev->VolHdr.VolumeName, dev->print_name());
362 if (dev->num_writers == 0) {
363 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
367 /* Not already in append mode, so mount the device */
368 Dmsg0(190, "Not in append mode, try mount.\n");
369 ASSERT(dev->num_writers == 0);
373 if (do_mount || recycle) {
374 Dmsg0(190, "Do mount_next_write_vol\n");
375 bool mounted = mount_next_write_volume(dcr, release);
377 if (!job_canceled(jcr)) {
378 /* Reduce "noise" -- don't print if job canceled */
379 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
381 Dmsg1(200, "Could not ready device %s for append.\n",
386 Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
389 dev->num_writers++; /* we are now a writer */
390 if (jcr->NumVolumes == 0) {
394 if (dcr->reserved_device) {
395 dev->reserved_device--;
396 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
397 dcr->reserved_device = false;
408 if (dcr->reserved_device) {
409 dev->reserved_device--;
410 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
411 dcr->reserved_device = false;
420 * This job is done, so release the device. From a Unix standpoint,
421 * the device remains open.
424 bool release_device(DCR *dcr)
427 DEVICE *dev = dcr->dev;
431 Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
433 /* if device is reserved, job never started, so release the reserve here */
434 if (dcr->reserved_device) {
435 dev->reserved_device--;
436 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
437 dcr->reserved_device = false;
440 if (dev->can_read()) {
441 dev->clear_read(); /* clear read bit */
443 /******FIXME**** send read volume usage statistics to director */
445 } else if (dev->num_writers > 0) {
447 * Note if WEOT is set, we are at the end of the tape
448 * and may not be positioned correctly, so the
449 * job_media_record and update_vol_info have already been
450 * done, which means we skip them here.
453 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
454 if (dev->is_labeled()) {
455 Dmsg0(100, "dir_create_jobmedia_record. Release\n");
456 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
457 Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
458 dcr->VolCatInfo.VolCatName, jcr->Job);
460 /* If no more writers, write an EOF */
461 if (!dev->num_writers && dev->can_write()) {
463 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
465 if (!dev->at_weot()) {
466 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
467 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
468 /* Note! do volume update before close, which zaps VolCatInfo */
469 Dmsg0(100, "dir_update_vol_info. Release0\n");
470 dir_update_volume_info(dcr, false); /* send Volume info to Director */
476 * If we reach here, it is most likely because the job
477 * has failed, since the device is not in read mode and
478 * there are no writers. It was probably reserved.
482 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
483 if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
484 dvd_remove_empty_part(dcr); /* get rid of any empty spool part */
488 /* Fire off Alert command and include any output */
489 if (!job_canceled(jcr) && dcr->device->alert_command) {
493 char line[MAXSTRING];
494 alert = get_pool_memory(PM_FNAME);
495 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
496 bpipe = open_bpipe(alert, 0, "r");
498 while (fgets(line, sizeof(line), bpipe->rfd)) {
499 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
501 status = close_bpipe(bpipe);
507 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
508 alert, be.strerror(status));
511 Dmsg1(400, "alert status=%d\n", status);
512 free_pool_memory(alert);
515 if (jcr->read_dcr == dcr) {
516 jcr->read_dcr = NULL;
518 if (jcr->dcr == dcr) {
526 * Create a new Device Control Record and attach
527 * it to the device (if this is a real job).
529 DCR *new_dcr(JCR *jcr, DEVICE *dev)
531 DCR *dcr = (DCR *)malloc(sizeof(DCR));
532 memset(dcr, 0, sizeof(DCR));
536 dcr->device = dev->device;
537 dcr->block = new_block(dev);
538 dcr->rec = new_record();
539 dcr->max_job_spool_size = dev->device->max_job_spool_size;
540 attach_dcr_to_dev(dcr);
547 * Search the dcrs list for the given dcr. If it is found,
548 * as it should be, then remove it. Also zap the jcr pointer
549 * to the dcr if it is the same one.
552 static void remove_dcr_from_dcrs(DCR *dcr)
558 int num = jcr->dcrs->size();
559 for (i=0; i < num; i++) {
560 ldcr = (DCR *)jcr->dcrs->get(i);
562 jcr->dcrs->remove(i);
563 if (jcr->dcr == dcr) {
572 static void attach_dcr_to_dev(DCR *dcr)
574 DEVICE *dev = dcr->dev;
577 if (!dcr->attached_to_dev && dev->is_open() && jcr && jcr->JobType != JT_SYSTEM) {
578 dev->attached_dcrs->append(dcr); /* attach dcr to device */
579 dcr->attached_to_dev = true;
583 void detach_dcr_from_dev(DCR *dcr)
585 DEVICE *dev = dcr->dev;
587 if (dcr->reserved_device) {
588 dcr->reserved_device = false;
590 dev->reserved_device--;
591 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
592 dcr->reserved_device = false;
593 /* If we set read mode in reserving, remove it */
594 if (dev->can_read()) {
597 if (dev->num_writers < 0) {
598 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
599 dev->num_writers = 0;
604 /* Detach this dcr only if attached */
605 if (dcr->attached_to_dev) {
606 dcr->dev->attached_dcrs->remove(dcr); /* detach dcr from device */
607 dcr->attached_to_dev = false;
608 // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
610 free_unused_volume(dcr); /* free unused vols attached to this dcr */
611 pthread_cond_broadcast(&dcr->dev->wait_next_vol);
612 pthread_cond_broadcast(&wait_device_release);
616 * Free up all aspects of the given dcr -- i.e. dechain it,
617 * release allocated memory, zap pointers, ...
619 void free_dcr(DCR *dcr)
622 detach_dcr_from_dev(dcr);
625 free_block(dcr->block);
628 free_record(dcr->rec);
631 dcr->jcr->dcr = NULL;