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 dev->block(BST_DOING_ACQUIRE);
53 if (dev->num_writers > 0) {
54 Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"),
55 dev->num_writers, jcr->JobId);
59 /* Find next Volume, if any */
62 Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
66 for (i=1; i<jcr->CurVolume; i++) {
70 goto get_out; /* should not happen */
72 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
73 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
74 dcr->VolCatInfo.Slot = vol->Slot;
77 * If the MediaType requested for this volume is not the
78 * same as the current drive, we attempt to find the same
79 * device that was used to write the orginal volume. If
80 * found, we switch to using that device.
82 Dmsg2(100, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
83 if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
87 memset(&rctx, 0, sizeof(RCTX));
89 jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
90 rctx.any_drive = true;
91 rctx.device_name = vol->device;
93 memset(store, 0, sizeof(DIRSTORE));
94 store->name[0] = 0; /* No dir name */
95 bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
96 bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
97 bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
98 store->append = false;
102 * Note, if search_for_device() succeeds, we get a new_dcr,
103 * which we do not use except for the dev info.
105 stat = search_res_for_device(rctx);
106 release_msgs(jcr); /* release queued messages */
108 DCR *new_dcr = jcr->read_dcr;
110 detach_dcr_from_dev(dcr); /* release old device */
111 /* Copy important info from the new dcr */
112 dev = dcr->dev = new_dcr->dev;
114 dcr->device = new_dcr->device;
115 dcr->max_job_spool_size = dcr->device->max_job_spool_size;
116 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
117 dev->attached_dcrs->append(dcr); /* attach dcr to device */
119 new_dcr->VolumeName[0] = 0;
121 dev->block(BST_DOING_ACQUIRE);
122 Jmsg(jcr, M_INFO, 0, _("Media Type change. New device %s chosen.\n"),
124 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
125 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
126 dcr->VolCatInfo.Slot = vol->Slot;
127 bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
128 bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
129 } else if (stat == 0) { /* device busy */
130 Dmsg1(000, "Device %s is busy.\n", vol->device);
133 Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
139 init_device_wait_timers(dcr);
141 tape_previously_mounted = dev->can_read() || dev->can_append() ||
143 tape_initially_mounted = tape_previously_mounted;
146 /* Volume info is always needed because of VolParts */
147 Dmsg0(200, "dir_get_volume_info\n");
148 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
149 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
152 for (i=0; i<5; i++) {
153 dev->clear_labeled(); /* force reread of label */
154 if (job_canceled(jcr)) {
155 Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
156 goto get_out; /* error return */
159 * This code ensures that the device is ready for
160 * reading. If it is a file, it opens it.
161 * If it is a tape, it checks the volume name
163 Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
164 if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
165 if (dev->dev_errno == EIO) { /* no tape loaded */
166 Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
167 dev->print_name(), dcr->VolumeName, dev->bstrerror());
171 Jmsg3(jcr, M_FATAL, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
172 dev->print_name(), dcr->VolumeName, dev->bstrerror());
175 Dmsg1(100, "opened dev %s OK\n", dev->print_name());
177 /* Read Volume Label */
179 Dmsg0(200, "calling read-vol-label\n");
180 vol_label_status = read_dev_volume_label(dcr);
181 switch (vol_label_status) {
184 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
188 * Send error message generated by read_dev_volume_label()
189 * only we really had a tape mounted. This supresses superfluous
190 * error messages when nothing is mounted.
192 if (tape_previously_mounted) {
193 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
197 if (tape_initially_mounted) {
198 tape_initially_mounted = false;
203 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
205 tape_previously_mounted = true;
208 * If the device requires mount, close it, so the device can be ejected.
210 if (dev->requires_mount()) {
214 /* Call autochanger only once unless ask_sysop called */
215 if (try_autochanger) {
217 Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
218 dcr->VolumeName, dcr->VolCatInfo.Slot);
219 stat = autoload_device(dcr, 0, NULL);
221 try_autochanger = false;
222 continue; /* try reading volume mounted */
226 /* Mount a specific volume and no other */
227 Dmsg0(200, "calling dir_ask_sysop\n");
228 if (!dir_ask_sysop_to_mount_volume(dcr)) {
229 goto get_out; /* error return */
231 try_autochanger = true; /* permit using autochanger again */
232 continue; /* try reading again */
237 Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
244 set_jcr_job_status(jcr, JS_Running);
245 dir_send_job_status(jcr);
246 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
247 dcr->VolumeName, dev->print_name());
251 if (dcr->reserved_device) {
252 dev->reserved_device--;
253 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
254 dcr->reserved_device = false;
263 * Acquire device for writing. We permit multiple writers.
264 * If this is the first one, we read the label.
266 * Returns: NULL if failed for any reason
268 * Note, normally reserve_device_for_append() is called
269 * before this routine.
271 DCR *acquire_device_for_append(DCR *dcr)
273 bool release = false;
274 bool recycle = false;
275 bool do_mount = false;
276 DEVICE *dev = dcr->dev;
279 init_device_wait_timers(dcr);
281 dev->block(BST_DOING_ACQUIRE);
282 Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":
283 (dev->is_dvd()?"DVD":"disk"));
286 * With the reservation system, this should not happen
288 if (dev->can_read()) {
289 Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
290 Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
294 if (dev->can_append()) {
295 Dmsg0(190, "device already in append.\n");
297 * Device already in append mode
299 * Check if we have the right Volume mounted
300 * OK if current volume info OK
301 * OK if next volume matches current volume
302 * otherwise mount desired volume obtained from
303 * dir_find_next_appendable_volume
304 * dev->VolHdr.VolumeName is what is in the drive
305 * dcr->VolumeName is what we pass into the routines, or
306 * get back from the subroutines.
308 bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
309 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
310 !(dir_find_next_appendable_volume(dcr) &&
311 strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
312 Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
314 /* Release volume reserved by dir_find_next_appendable_volume() */
315 if (dcr->VolumeName[0]) {
316 free_unused_volume(dcr);
318 if (dev->num_writers != 0) {
319 Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"),
320 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
321 Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",
322 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
325 /* Wrong tape mounted, release it, then fall through to get correct one */
326 Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
331 * At this point, the correct tape is already mounted, so
332 * we do not need to do mount_next_write_volume(), unless
333 * we need to recycle the tape.
335 recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
336 Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
337 if (recycle && dev->num_writers != 0) {
338 Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
339 " on device %s because it is in use by another job.\n"),
340 dev->VolHdr.VolumeName, dev->print_name());
343 if (dev->num_writers == 0) {
344 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
348 /* Not already in append mode, so mount the device */
349 Dmsg0(190, "Not in append mode, try mount.\n");
350 ASSERT(dev->num_writers == 0);
354 if (do_mount || recycle) {
355 Dmsg0(190, "Do mount_next_write_vol\n");
356 bool mounted = mount_next_write_volume(dcr, release);
358 if (!job_canceled(jcr)) {
359 /* Reduce "noise" -- don't print if job canceled */
360 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
362 Dmsg1(200, "Could not ready device %s for append.\n",
369 dev->num_writers++; /* we are now a writer */
370 if (jcr->NumVolumes == 0) {
374 if (dcr->reserved_device) {
375 dev->reserved_device--;
376 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
377 dcr->reserved_device = false;
388 if (dcr->reserved_device) {
389 dev->reserved_device--;
390 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
391 dcr->reserved_device = false;
400 * This job is done, so release the device. From a Unix standpoint,
401 * the device remains open.
404 bool release_device(DCR *dcr)
407 DEVICE *dev = dcr->dev;
411 Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
413 /* if device is reserved, job never started, so release the reserve here */
414 if (dcr->reserved_device) {
415 dev->reserved_device--;
416 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
417 dcr->reserved_device = false;
420 if (dev->can_read()) {
421 dev->clear_read(); /* clear read bit */
423 /******FIXME**** send read volume usage statistics to director */
425 } else if (dev->num_writers > 0) {
427 * Note if WEOT is set, we are at the end of the tape
428 * and may not be positioned correctly, so the
429 * job_media_record and update_vol_info have already been
430 * done, which means we skip them here.
433 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
434 if (dev->is_labeled()) {
435 Dmsg0(100, "dir_create_jobmedia_record. Release\n");
436 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
437 Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
438 dcr->VolCatInfo.VolCatName, jcr->Job);
440 /* If no more writers, write an EOF */
441 if (!dev->num_writers && dev->can_write()) {
443 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
445 if (!dev->at_weot()) {
446 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
447 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
448 /* Note! do volume update before close, which zaps VolCatInfo */
449 Dmsg0(100, "dir_update_vol_info. Release0\n");
450 dir_update_volume_info(dcr, false); /* send Volume info to Director */
456 * If we reach here, it is most likely because the job
457 * has failed, since the device is not in read mode and
458 * there are no writers. It was probably reserved.
462 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
463 if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
467 /* Fire off Alert command and include any output */
468 if (!job_canceled(jcr) && dcr->device->alert_command) {
472 char line[MAXSTRING];
473 alert = get_pool_memory(PM_FNAME);
474 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
475 bpipe = open_bpipe(alert, 0, "r");
477 while (fgets(line, sizeof(line), bpipe->rfd)) {
478 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
480 status = close_bpipe(bpipe);
486 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
487 alert, be.strerror(status));
490 Dmsg1(400, "alert status=%d\n", status);
491 free_pool_memory(alert);
494 if (jcr->read_dcr == dcr) {
495 jcr->read_dcr = NULL;
497 if (jcr->dcr == dcr) {
505 * Create a new Device Control Record and attach
506 * it to the device (if this is a real job).
508 DCR *new_dcr(JCR *jcr, DEVICE *dev)
510 DCR *dcr = (DCR *)malloc(sizeof(DCR));
511 memset(dcr, 0, sizeof(DCR));
515 dcr->device = dev->device;
516 dcr->block = new_block(dev);
517 dcr->rec = new_record();
518 dcr->max_job_spool_size = dev->device->max_job_spool_size;
519 /* Attach this dcr only if dev is initialized */
520 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
521 dev->attached_dcrs->append(dcr); /* attach dcr to device */
522 // jcr->dcrs->append(dcr); /* put dcr in list for Job */
530 * Search the dcrs list for the given dcr. If it is found,
531 * as it should be, then remove it. Also zap the jcr pointer
532 * to the dcr if it is the same one.
535 static void remove_dcr_from_dcrs(DCR *dcr)
541 int num = jcr->dcrs->size();
542 for (i=0; i < num; i++) {
543 ldcr = (DCR *)jcr->dcrs->get(i);
545 jcr->dcrs->remove(i);
546 if (jcr->dcr == dcr) {
555 static void detach_dcr_from_dev(DCR *dcr)
557 DEVICE *dev = dcr->dev;
559 if (dcr->reserved_device) {
560 dcr->reserved_device = false;
562 dev->reserved_device--;
563 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
564 dcr->reserved_device = false;
565 /* If we set read mode in reserving, remove it */
566 if (dev->can_read()) {
569 if (dev->num_writers < 0) {
570 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
571 dev->num_writers = 0;
576 /* Detach this dcr only if the dev is initialized */
577 if (dcr->dev->fd != 0 && dcr->jcr && dcr->jcr->JobType != JT_SYSTEM) {
578 dcr->dev->attached_dcrs->remove(dcr); /* detach dcr from device */
579 // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
581 free_unused_volume(dcr); /* free unused vols attached to this dcr */
582 pthread_cond_broadcast(&dcr->dev->wait_next_vol);
583 pthread_cond_broadcast(&wait_device_release);
587 * Free up all aspects of the given dcr -- i.e. dechain it,
588 * release allocated memory, zap pointers, ...
590 void free_dcr(DCR *dcr)
593 detach_dcr_from_dev(dcr);
596 free_block(dcr->block);
599 free_record(dcr->rec);
602 dcr->jcr->dcr = NULL;