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 detach_dcr_from_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;
51 Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
52 dev->block(BST_DOING_ACQUIRE);
54 if (dev->num_writers > 0) {
55 Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"),
56 dev->num_writers, jcr->JobId);
60 /* Find next Volume, if any */
63 Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
67 for (i=1; i<jcr->CurVolume; i++) {
71 goto get_out; /* should not happen */
73 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
74 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
75 dcr->VolCatInfo.Slot = vol->Slot;
78 * If the MediaType requested for this volume is not the
79 * same as the current drive, we attempt to find the same
80 * device that was used to write the orginal volume. If
81 * found, we switch to using that device.
83 Dmsg2(100, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
84 if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
88 DCR *dcr_save = jcr->dcr;
91 memset(&rctx, 0, sizeof(RCTX));
93 jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
94 rctx.any_drive = true;
95 rctx.device_name = vol->device;
97 memset(store, 0, sizeof(DIRSTORE));
98 store->name[0] = 0; /* No dir name */
99 bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
100 bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
101 bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
102 store->append = false;
106 * Note, if search_for_device() succeeds, we get a new_dcr,
107 * which we do not use except for the dev info.
109 stat = search_res_for_device(rctx);
110 release_msgs(jcr); /* release queued messages */
112 DCR *new_dcr = jcr->read_dcr;
114 detach_dcr_from_dev(dcr); /* release old device */
115 /* Copy important info from the new dcr */
116 dev = dcr->dev = new_dcr->dev;
118 dcr->device = new_dcr->device;
119 dcr->max_job_spool_size = dcr->device->max_job_spool_size;
120 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
121 dev->attached_dcrs->append(dcr); /* attach dcr to device */
123 new_dcr->VolumeName[0] = 0;
125 dev->block(BST_DOING_ACQUIRE);
126 Jmsg(jcr, M_INFO, 0, _("Media Type change. New device %s chosen.\n"),
128 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
129 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
130 dcr->VolCatInfo.Slot = vol->Slot;
131 bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
132 bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
133 } else if (stat == 0) { /* device busy */
134 Dmsg1(000, "Device %s is busy.\n", vol->device);
137 Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
146 init_device_wait_timers(dcr);
148 tape_previously_mounted = dev->can_read() || dev->can_append() ||
150 tape_initially_mounted = tape_previously_mounted;
153 /* Volume info is always needed because of VolParts */
154 Dmsg0(200, "dir_get_volume_info\n");
155 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
156 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
159 for (i=0; i<5; i++) {
160 dev->clear_labeled(); /* force reread of label */
161 if (job_canceled(jcr)) {
162 Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
163 goto get_out; /* error return */
166 * This code ensures that the device is ready for
167 * reading. If it is a file, it opens it.
168 * If it is a tape, it checks the volume name
170 Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
171 if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
172 if (dev->dev_errno == EIO) { /* no tape loaded */
173 Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
174 dev->print_name(), dcr->VolumeName, dev->bstrerror());
178 Jmsg3(jcr, M_FATAL, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
179 dev->print_name(), dcr->VolumeName, dev->bstrerror());
182 Dmsg1(100, "opened dev %s OK\n", dev->print_name());
184 /* Read Volume Label */
186 Dmsg0(200, "calling read-vol-label\n");
187 vol_label_status = read_dev_volume_label(dcr);
188 switch (vol_label_status) {
191 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
195 * Send error message generated by read_dev_volume_label()
196 * only we really had a tape mounted. This supresses superfluous
197 * error messages when nothing is mounted.
199 if (tape_previously_mounted) {
200 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
204 if (tape_initially_mounted) {
205 tape_initially_mounted = false;
210 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
212 tape_previously_mounted = true;
215 * If the device requires mount, close it, so the device can be ejected.
217 if (dev->requires_mount()) {
221 /* Call autochanger only once unless ask_sysop called */
222 if (try_autochanger) {
224 Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
225 dcr->VolumeName, dcr->VolCatInfo.Slot);
226 stat = autoload_device(dcr, 0, NULL);
228 try_autochanger = false;
229 continue; /* try reading volume mounted */
233 /* Mount a specific volume and no other */
234 Dmsg0(200, "calling dir_ask_sysop\n");
235 if (!dir_ask_sysop_to_mount_volume(dcr)) {
236 goto get_out; /* error return */
238 try_autochanger = true; /* permit using autochanger again */
239 continue; /* try reading again */
244 Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
251 set_jcr_job_status(jcr, JS_Running);
252 dir_send_job_status(jcr);
253 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
254 dcr->VolumeName, dev->print_name());
258 if (dcr->reserved_device) {
259 dev->reserved_device--;
260 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
261 dcr->reserved_device = false;
265 Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
271 * Acquire device for writing. We permit multiple writers.
272 * If this is the first one, we read the label.
274 * Returns: NULL if failed for any reason
276 * Note, normally reserve_device_for_append() is called
277 * before this routine.
279 DCR *acquire_device_for_append(DCR *dcr)
281 bool release = false;
282 bool recycle = false;
283 bool do_mount = false;
284 DEVICE *dev = dcr->dev;
287 init_device_wait_timers(dcr);
289 dev->block(BST_DOING_ACQUIRE);
290 Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":
291 (dev->is_dvd()?"DVD":"disk"));
294 * With the reservation system, this should not happen
296 if (dev->can_read()) {
297 Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
298 Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
302 if (dev->can_append()) {
303 Dmsg0(190, "device already in append.\n");
305 * Device already in append mode
307 * Check if we have the right Volume mounted
308 * OK if current volume info OK
309 * OK if next volume matches current volume
310 * otherwise mount desired volume obtained from
311 * dir_find_next_appendable_volume
312 * dev->VolHdr.VolumeName is what is in the drive
313 * dcr->VolumeName is what we pass into the routines, or
314 * get back from the subroutines.
316 bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
317 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
318 !(dir_find_next_appendable_volume(dcr) &&
319 strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
320 Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
322 /* Release volume reserved by dir_find_next_appendable_volume() */
323 if (dcr->VolumeName[0]) {
324 free_unused_volume(dcr);
326 if (dev->num_writers != 0) {
327 Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"),
328 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
329 Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",
330 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
333 /* Wrong tape mounted, release it, then fall through to get correct one */
334 Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
339 * At this point, the correct tape is already mounted, so
340 * we do not need to do mount_next_write_volume(), unless
341 * we need to recycle the tape.
343 recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
344 Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
345 if (recycle && dev->num_writers != 0) {
346 Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
347 " on device %s because it is in use by another job.\n"),
348 dev->VolHdr.VolumeName, dev->print_name());
351 if (dev->num_writers == 0) {
352 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
356 /* Not already in append mode, so mount the device */
357 Dmsg0(190, "Not in append mode, try mount.\n");
358 ASSERT(dev->num_writers == 0);
362 if (do_mount || recycle) {
363 Dmsg0(190, "Do mount_next_write_vol\n");
364 bool mounted = mount_next_write_volume(dcr, release);
366 if (!job_canceled(jcr)) {
367 /* Reduce "noise" -- don't print if job canceled */
368 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
370 Dmsg1(200, "Could not ready device %s for append.\n",
377 dev->num_writers++; /* we are now a writer */
378 if (jcr->NumVolumes == 0) {
382 if (dcr->reserved_device) {
383 dev->reserved_device--;
384 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
385 dcr->reserved_device = false;
396 if (dcr->reserved_device) {
397 dev->reserved_device--;
398 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
399 dcr->reserved_device = false;
408 * This job is done, so release the device. From a Unix standpoint,
409 * the device remains open.
412 bool release_device(DCR *dcr)
415 DEVICE *dev = dcr->dev;
419 Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
421 /* if device is reserved, job never started, so release the reserve here */
422 if (dcr->reserved_device) {
423 dev->reserved_device--;
424 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
425 dcr->reserved_device = false;
428 if (dev->can_read()) {
429 dev->clear_read(); /* clear read bit */
431 /******FIXME**** send read volume usage statistics to director */
433 } else if (dev->num_writers > 0) {
435 * Note if WEOT is set, we are at the end of the tape
436 * and may not be positioned correctly, so the
437 * job_media_record and update_vol_info have already been
438 * done, which means we skip them here.
441 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
442 if (dev->is_labeled()) {
443 Dmsg0(100, "dir_create_jobmedia_record. Release\n");
444 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
445 Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
446 dcr->VolCatInfo.VolCatName, jcr->Job);
448 /* If no more writers, write an EOF */
449 if (!dev->num_writers && dev->can_write()) {
451 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
453 if (!dev->at_weot()) {
454 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
455 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
456 /* Note! do volume update before close, which zaps VolCatInfo */
457 Dmsg0(100, "dir_update_vol_info. Release0\n");
458 dir_update_volume_info(dcr, false); /* send Volume info to Director */
464 * If we reach here, it is most likely because the job
465 * has failed, since the device is not in read mode and
466 * there are no writers. It was probably reserved.
470 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
471 if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
475 /* Fire off Alert command and include any output */
476 if (!job_canceled(jcr) && dcr->device->alert_command) {
480 char line[MAXSTRING];
481 alert = get_pool_memory(PM_FNAME);
482 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
483 bpipe = open_bpipe(alert, 0, "r");
485 while (fgets(line, sizeof(line), bpipe->rfd)) {
486 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
488 status = close_bpipe(bpipe);
494 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
495 alert, be.strerror(status));
498 Dmsg1(400, "alert status=%d\n", status);
499 free_pool_memory(alert);
502 if (jcr->read_dcr == dcr) {
503 jcr->read_dcr = NULL;
505 if (jcr->dcr == dcr) {
513 * Create a new Device Control Record and attach
514 * it to the device (if this is a real job).
516 DCR *new_dcr(JCR *jcr, DEVICE *dev)
518 DCR *dcr = (DCR *)malloc(sizeof(DCR));
519 memset(dcr, 0, sizeof(DCR));
523 dcr->device = dev->device;
524 dcr->block = new_block(dev);
525 dcr->rec = new_record();
526 dcr->max_job_spool_size = dev->device->max_job_spool_size;
527 /* Attach this dcr only if dev is initialized */
528 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
529 dev->attached_dcrs->append(dcr); /* attach dcr to device */
530 // jcr->dcrs->append(dcr); /* put dcr in list for Job */
538 * Search the dcrs list for the given dcr. If it is found,
539 * as it should be, then remove it. Also zap the jcr pointer
540 * to the dcr if it is the same one.
543 static void remove_dcr_from_dcrs(DCR *dcr)
549 int num = jcr->dcrs->size();
550 for (i=0; i < num; i++) {
551 ldcr = (DCR *)jcr->dcrs->get(i);
553 jcr->dcrs->remove(i);
554 if (jcr->dcr == dcr) {
563 static void detach_dcr_from_dev(DCR *dcr)
565 DEVICE *dev = dcr->dev;
567 if (dcr->reserved_device) {
568 dcr->reserved_device = false;
570 dev->reserved_device--;
571 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
572 dcr->reserved_device = false;
573 /* If we set read mode in reserving, remove it */
574 if (dev->can_read()) {
577 if (dev->num_writers < 0) {
578 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
579 dev->num_writers = 0;
584 /* Detach this dcr only if the dev is initialized */
585 if (dcr->dev->fd != 0 && dcr->jcr && dcr->jcr->JobType != JT_SYSTEM) {
586 dcr->dev->attached_dcrs->remove(dcr); /* detach dcr from device */
587 // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
589 free_unused_volume(dcr); /* free unused vols attached to this dcr */
590 pthread_cond_broadcast(&dcr->dev->wait_next_vol);
591 pthread_cond_broadcast(&wait_device_release);
595 * Free up all aspects of the given dcr -- i.e. dechain it,
596 * release allocated memory, zap pointers, ...
598 void free_dcr(DCR *dcr)
601 detach_dcr_from_dev(dcr);
604 free_block(dcr->block);
607 free_record(dcr->rec);
610 dcr->jcr->dcr = NULL;