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 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 */
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 DCR *dcr = (DCR *)malloc(sizeof(DCR));
33 memset(dcr, 0, sizeof(DCR));
37 dcr->device = dev->device;
38 dcr->block = new_block(dev);
39 dcr->rec = new_record();
40 dcr->max_job_spool_size = dev->device->max_job_spool_size;
41 /* Attach this dcr only if dev is initialized */
42 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
43 dev->attached_dcrs->append(dcr); /* attach dcr to device */
44 // jcr->dcrs->append(dcr); /* put dcr in list for Job */
52 * Search the dcrs list for the given dcr. If it is found,
53 * as it should be, then remove it. Also zap the jcr pointer
54 * to the dcr if it is the same one.
57 static void remove_dcr_from_dcrs(DCR *dcr)
63 int num = jcr->dcrs->size();
64 for (i=0; i < num; i++) {
65 ldcr = (DCR *)jcr->dcrs->get(i);
68 if (jcr->dcr == dcr) {
78 * Free up all aspects of the given dcr -- i.e. dechain it,
79 * release allocated memory, zap pointers, ...
81 void free_dcr(DCR *dcr)
84 DEVICE *dev = dcr->dev;
86 if (dcr->reserved_device) {
88 dev->reserved_device--;
89 Dmsg1(100, "Dec reserve=%d\n", dev->reserved_device);
90 dcr->reserved_device = false;
91 if (dev->num_writers < 0) {
92 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
98 /* Detach this dcr only if the dev is initialized */
99 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
100 dev->attached_dcrs->remove(dcr); /* detach dcr from device */
101 // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
104 free_block(dcr->block);
107 free_record(dcr->rec);
110 dcr->jcr->dcr = NULL;
112 free_unused_volume(dcr); /* free unused vols attached to this dcr */
116 /*********************************************************************
117 * Acquire device for reading.
118 * The drive should have previously been reserved by calling
119 * reserve_device_for_read(). We read the Volume label from the block and
120 * leave the block pointers just after the label.
122 * Returns: NULL if failed for any reason
125 DCR *acquire_device_for_read(DCR *dcr)
127 DEVICE *dev = dcr->dev;
130 bool tape_previously_mounted;
131 bool tape_initially_mounted;
133 bool try_autochanger = true;
135 int vol_label_status;
137 dev->block(BST_DOING_ACQUIRE);
139 if (dev->num_writers > 0) {
140 Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"),
141 dev->num_writers, jcr->JobId);
145 /* Find next Volume, if any */
148 Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
152 for (i=1; i<jcr->CurVolume; i++) {
156 goto get_out; /* should not happen */
158 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
160 init_device_wait_timers(dcr);
162 tape_previously_mounted = dev->can_read() || dev->can_append() ||
164 tape_initially_mounted = tape_previously_mounted;
167 /* Volume info is always needed because of VolParts */
168 Dmsg0(200, "dir_get_volume_info\n");
169 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
170 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
173 for (i=0; i<5; i++) {
174 dev->clear_labeled(); /* force reread of label */
175 if (job_canceled(jcr)) {
176 Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
177 goto get_out; /* error return */
180 * This code ensures that the device is ready for
181 * reading. If it is a file, it opens it.
182 * If it is a tape, it checks the volume name
184 Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
185 if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
186 if (dev->dev_errno == EIO) { /* no tape loaded */
187 Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
188 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
192 Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
193 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
196 Dmsg1(100, "opened dev %s OK\n", dev->print_name());
198 /* Read Volume Label */
200 Dmsg0(200, "calling read-vol-label\n");
201 vol_label_status = read_dev_volume_label(dcr);
202 switch (vol_label_status) {
205 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
209 * Send error message generated by read_dev_volume_label()
210 * only we really had a tape mounted. This supresses superfluous
211 * error messages when nothing is mounted.
213 if (tape_previously_mounted) {
214 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
218 if (tape_initially_mounted) {
219 tape_initially_mounted = false;
224 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
226 tape_previously_mounted = true;
228 /* If the device requires mount, close it, so the device can be ejected.
229 * FIXME: This should perhaps be done for all devices. */
230 if (dev->requires_mount()) {
231 force_close_device(dev);
234 /* Call autochanger only once unless ask_sysop called */
235 if (try_autochanger) {
237 Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
238 dcr->VolumeName, dcr->VolCatInfo.Slot);
239 stat = autoload_device(dcr, 0, NULL);
241 try_autochanger = false;
242 continue; /* try reading volume mounted */
246 /* Mount a specific volume and no other */
247 Dmsg0(200, "calling dir_ask_sysop\n");
248 if (!dir_ask_sysop_to_mount_volume(dcr)) {
249 goto get_out; /* error return */
251 try_autochanger = true; /* permit using autochanger again */
252 continue; /* try reading again */
257 Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
264 set_jcr_job_status(jcr, JS_Running);
265 dir_send_job_status(jcr);
266 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
267 dcr->VolumeName, dev->print_name());
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",
385 dev->num_writers++; /* we are now a writer */
386 if (jcr->NumVolumes == 0) {
392 * If we jump here, it is an error return because
393 * rtn_dev will still be NULL
400 if (dcr->reserved_device) {
401 dev->reserved_device--;
402 Dmsg1(100, "Dec reserve=%d\n", dev->reserved_device);
403 dcr->reserved_device = false;
411 * This job is done, so release the device. From a Unix standpoint,
412 * the device remains open.
415 bool release_device(DCR *dcr)
418 DEVICE *dev = dcr->dev;
420 bool was_reading = false;
423 Dmsg1(100, "release_device device is %s\n", dev->is_tape()?"tape":"disk");
425 /* if device is reserved, job never started, so release the reserve here */
426 if (dcr->reserved_device) {
427 dev->reserved_device--;
428 Dmsg1(100, "Dec reserve=%d\n", dev->reserved_device);
429 dcr->reserved_device = false;
432 if (dev->can_read()) {
433 dev->clear_read(); /* clear read bit */
436 /******FIXME**** send read volume usage statistics to director */
438 } else if (dev->num_writers > 0) {
440 * Note if WEOT is set, we are at the end of the tape
441 * and may not be positioned correctly, so the
442 * job_media_record and update_vol_info have already been
443 * done, which means we skip them here.
446 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
447 if (dev->is_labeled()) {
448 Dmsg0(100, "dir_create_jobmedia_record. Release\n");
449 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
450 Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
451 dcr->VolCatInfo.VolCatName, jcr->Job);
453 /* If no more writers, write an EOF */
454 if (!dev->num_writers && dev->can_write()) {
456 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
458 if (!dev->at_weot()) {
459 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
460 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
461 /* Note! do volume update before close, which zaps VolCatInfo */
462 Dmsg0(100, "dir_update_vol_info. Release0\n");
463 dir_update_volume_info(dcr, false); /* send Volume info to Director */
469 * If we reach here, it is most likely because the job
470 * has failed, since the device is not in read mode and
471 * there are no writers. It was probably reserved.
475 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
476 if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
477 offline_or_rewind_dev(dev);
481 /* Fire off Alert command and include any output */
482 if (!job_canceled(jcr) && dcr->device->alert_command) {
486 char line[MAXSTRING];
487 alert = get_pool_memory(PM_FNAME);
488 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
489 bpipe = open_bpipe(alert, 0, "r");
491 while (fgets(line, sizeof(line), bpipe->rfd)) {
492 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
494 status = close_bpipe(bpipe);
500 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
501 alert, be.strerror(status));
504 Dmsg1(400, "alert status=%d\n", status);
505 free_pool_memory(alert);
510 jcr->read_dcr = NULL;
514 pthread_cond_broadcast(&wait_device_release);