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 */
27 * Create a new Device Control Record and attach
28 * it to the device (if this is a real job).
30 DCR *new_dcr(JCR *jcr, DEVICE *dev)
32 if (jcr && jcr->dcr) {
35 DCR *dcr = (DCR *)malloc(sizeof(DCR));
36 memset(dcr, 0, sizeof(DCR));
43 dcr->device = dev->device;
45 dcr->block = new_block(dev);
46 dcr->rec = new_record();
48 dcr->max_job_spool_size = dev->device->max_job_spool_size;
49 /* Attach this dcr only if dev is initialized */
50 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
51 dev->attached_dcrs->append(dcr); /* attach dcr to device */
52 // jcr->dcrs->append(dcr); /* put dcr in list for Job */
58 * Search the dcrs list for the given dcr. If it is found,
59 * as it should be, then remove it. Also zap the jcr pointer
60 * to the dcr if it is the same one.
63 static void remove_dcr_from_dcrs(DCR *dcr)
69 int num = jcr->dcrs->size();
70 for (i=0; i < num; i++) {
71 ldcr = (DCR *)jcr->dcrs->get(i);
74 if (jcr->dcr == dcr) {
84 * Free up all aspects of the given dcr -- i.e. dechain it,
85 * release allocated memory, zap pointers, ...
87 void free_dcr(DCR *dcr)
90 DEVICE *dev = dcr->dev;
92 if (dcr->reserved_device) {
94 dev->reserved_device--;
95 Dmsg1(200, "=========== Dec reserve=%d\n", dev->reserved_device);
96 dcr->reserved_device = false;
97 if (dev->num_writers < 0) {
98 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
104 /* Detach this dcr only if the dev is initialized */
105 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
106 dev->attached_dcrs->remove(dcr); /* detach dcr from device */
107 // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
110 free_block(dcr->block);
113 free_record(dcr->rec);
116 dcr->jcr->dcr = NULL;
121 /*********************************************************************
122 * Acquire device for reading.
123 * The drive should have previously been reserved by calling
124 * reserve_device_for_read(). We read the Volume label from the block and
125 * leave the block pointers just after the label.
127 * Returns: NULL if failed for any reason
130 DCR *acquire_device_for_read(DCR *dcr)
132 DEVICE *dev = dcr->dev;
135 bool tape_previously_mounted;
136 bool tape_initially_mounted;
138 bool try_autochanger = true;
140 int vol_label_status;
142 dev->block(BST_DOING_ACQUIRE);
144 if (dev->num_writers > 0) {
145 Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"),
146 dev->num_writers, jcr->JobId);
150 /* Find next Volume, if any */
153 Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
157 for (i=1; i<jcr->CurVolume; i++) {
161 goto get_out; /* should not happen */
163 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
165 init_device_wait_timers(dcr);
167 tape_previously_mounted = dev->can_read() || dev->can_append() ||
169 tape_initially_mounted = tape_previously_mounted;
172 /* Volume info is always needed because of VolParts */
173 Dmsg0(200, "dir_get_volume_info\n");
174 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
175 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
178 dev->num_parts = dcr->VolCatInfo.VolCatParts;
180 for (i=0; i<5; i++) {
181 dev->clear_labeled(); /* force reread of label */
182 if (job_canceled(jcr)) {
183 Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
184 goto get_out; /* error return */
187 * This code ensures that the device is ready for
188 * reading. If it is a file, it opens it.
189 * If it is a tape, it checks the volume name
191 for ( ; !dev->is_open(); ) {
192 Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName);
193 if (open_dev(dev, dcr->VolumeName, OPEN_READ_ONLY) < 0) {
194 if (dev->dev_errno == EIO) { /* no tape loaded */
195 Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
196 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
200 /* If we have a dvd that requires mount,
201 * we need to try to open the label, so the info can be reported
202 * if a wrong volume has been mounted. */
203 if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) {
207 Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
208 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
211 Dmsg1(129, "open_dev %s OK\n", dev->print_name());
215 vol_label_status = read_dev_volume_label_guess(dcr, 0);
217 vol_label_status = read_dev_volume_label(dcr);
220 Dmsg0(200, "calling read-vol-label\n");
221 switch (vol_label_status) {
224 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
228 * Send error message generated by read_dev_volume_label()
229 * only we really had a tape mounted. This supresses superfluous
230 * error messages when nothing is mounted.
232 if (tape_previously_mounted) {
233 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
237 if (tape_initially_mounted) {
238 tape_initially_mounted = false;
243 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
245 tape_previously_mounted = true;
247 /* If the device requires mount, close it, so the device can be ejected.
248 * FIXME: This should perhaps be done for all devices. */
249 if (dev_cap(dev, CAP_REQMOUNT)) {
250 force_close_dev(dev);
253 /* Call autochanger only once unless ask_sysop called */
254 if (try_autochanger) {
256 Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
257 dcr->VolumeName, dcr->VolCatInfo.Slot);
258 stat = autoload_device(dcr, 0, NULL);
260 try_autochanger = false;
261 continue; /* try reading volume mounted */
265 /* Mount a specific volume and no other */
266 Dmsg0(200, "calling dir_ask_sysop\n");
267 if (!dir_ask_sysop_to_mount_volume(dcr)) {
268 goto get_out; /* error return */
270 try_autochanger = true; /* permit using autochanger again */
271 continue; /* try reading again */
276 Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
283 set_jcr_job_status(jcr, JS_Running);
284 dir_send_job_status(jcr);
285 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
286 dcr->VolumeName, dev->print_name());
299 * Acquire device for writing. We permit multiple writers.
300 * If this is the first one, we read the label.
302 * Returns: NULL if failed for any reason
304 * Note, normally reserve_device_for_append() is called
305 * before this routine.
307 DCR *acquire_device_for_append(DCR *dcr)
309 bool release = false;
310 bool recycle = false;
311 bool do_mount = false;
312 DEVICE *dev = dcr->dev;
315 init_device_wait_timers(dcr);
317 dev->block(BST_DOING_ACQUIRE);
318 Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":"disk");
320 if (dcr->reserved_device) {
321 dev->reserved_device--;
322 Dmsg1(200, "============ Dec reserve=%d\n", dev->reserved_device);
323 dcr->reserved_device = false;
327 * With the reservation system, this should not happen
329 if (dev->can_read()) {
330 Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
334 if (dev->can_append()) {
335 Dmsg0(190, "device already in append.\n");
337 * Device already in append mode
339 * Check if we have the right Volume mounted
340 * OK if current volume info OK
341 * OK if next volume matches current volume
342 * otherwise mount desired volume obtained from
343 * dir_find_next_appendable_volume
345 bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName));
346 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
347 !(dir_find_next_appendable_volume(dcr) &&
348 strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
349 Dmsg0(190, "Wrong tape mounted.\n");
350 if (dev->num_writers != 0 || dev->reserved_device) {
351 Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
354 /* Wrong tape mounted, release it, then fall through to get correct one */
355 Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
360 * At this point, the correct tape is already mounted, so
361 * we do not need to do mount_next_write_volume(), unless
362 * we need to recycle the tape.
364 recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
365 Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
366 if (recycle && dev->num_writers != 0) {
367 Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
368 " on device %s because it is in use by another job.\n"),
369 dev->VolHdr.VolName, dev->print_name());
372 if (dev->num_writers == 0) {
373 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
377 /* Not already in append mode, so mount the device */
378 Dmsg0(190, "Not in append mode, try mount.\n");
379 ASSERT(dev->num_writers == 0);
383 if (do_mount || recycle) {
384 Dmsg0(190, "Do mount_next_write_vol\n");
385 bool mounted = mount_next_write_volume(dcr, release);
387 if (!job_canceled(jcr)) {
388 /* Reduce "noise" -- don't print if job canceled */
389 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
396 dev->num_writers++; /* we are now a writer */
397 if (jcr->NumVolumes == 0) {
403 * If we jump here, it is an error return because
404 * rtn_dev will still be NULL
415 * This job is done, so release the device. From a Unix standpoint,
416 * the device remains open.
419 bool release_device(DCR *dcr)
422 DEVICE *dev = dcr->dev;
426 Dmsg1(100, "release_device device is %s\n", dev->is_tape()?"tape":"disk");
428 /* if device is reserved, job never started, so release the reserve here */
429 if (dcr->reserved_device) {
430 dev->reserved_device--;
431 Dmsg1(200, "========= Dec reserve=%d\n", dev->reserved_device);
432 dcr->reserved_device = false;
435 if (dev->can_read()) {
436 dev->clear_read(); /* clear read bit */
438 /******FIXME**** send read volume usage statistics to director */
440 } else if (dev->num_writers > 0) {
442 * Note if WEOT is set, we are at the end of the tape
443 * and may not be positioned correctly, so the
444 * job_media_record and update_vol_info have already been
445 * done, which means we skip them here.
448 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
449 if (dev->is_labeled()) {
450 Dmsg0(100, "dir_create_jobmedia_record. Release\n");
451 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
452 Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
453 dcr->VolCatInfo.VolCatName, jcr->Job);
455 /* If no more writers, write an EOF */
456 if (!dev->num_writers && dev->can_write()) {
458 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolName);
460 if (!dev->at_weot()) {
461 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
462 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
463 /* Note! do volume update before close, which zaps VolCatInfo */
464 Dmsg0(100, "dir_update_vol_info. Release0\n");
465 dir_update_volume_info(dcr, false); /* send Volume info to Director */
471 * If we reach here, it is most likely because the job
472 * has failed, since the device is not in read mode and
473 * there are no writers. It was probably reserved.
477 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
478 if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
479 offline_or_rewind_dev(dev);
483 /* Fire off Alert command and include any output */
484 if (!job_canceled(jcr) && dcr->device->alert_command) {
488 char line[MAXSTRING];
489 alert = get_pool_memory(PM_FNAME);
490 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
491 bpipe = open_bpipe(alert, 0, "r");
493 while (fgets(line, sizeof(line), bpipe->rfd)) {
494 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
496 status = close_bpipe(bpipe);
502 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
503 alert, be.strerror(status));
506 Dmsg1(400, "alert status=%d\n", status);
507 free_pool_memory(alert);
512 pthread_cond_broadcast(&wait_device_release);