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 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;
118 free_unused_volume(dcr); /* free unused vols attached to this dcr */
122 /*********************************************************************
123 * Acquire device for reading.
124 * The drive should have previously been reserved by calling
125 * reserve_device_for_read(). We read the Volume label from the block and
126 * leave the block pointers just after the label.
128 * Returns: NULL if failed for any reason
131 DCR *acquire_device_for_read(DCR *dcr)
133 DEVICE *dev = dcr->dev;
136 bool tape_previously_mounted;
137 bool tape_initially_mounted;
139 bool try_autochanger = true;
141 int vol_label_status;
143 dev->block(BST_DOING_ACQUIRE);
145 if (dev->num_writers > 0) {
146 Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"),
147 dev->num_writers, jcr->JobId);
151 /* Find next Volume, if any */
154 Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
158 for (i=1; i<jcr->CurVolume; i++) {
162 goto get_out; /* should not happen */
164 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
166 init_device_wait_timers(dcr);
168 tape_previously_mounted = dev->can_read() || dev->can_append() ||
170 tape_initially_mounted = tape_previously_mounted;
173 /* Volume info is always needed because of VolParts */
174 Dmsg0(200, "dir_get_volume_info\n");
175 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
176 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
179 for (i=0; i<5; i++) {
180 dev->clear_labeled(); /* force reread of label */
181 if (job_canceled(jcr)) {
182 Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
183 goto get_out; /* error return */
186 * This code ensures that the device is ready for
187 * reading. If it is a file, it opens it.
188 * If it is a tape, it checks the volume name
190 Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
191 if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
192 if (dev->dev_errno == EIO) { /* no tape loaded */
193 Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
194 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
199 /* If we have a dvd that requires mount,
200 * we need to try to open the label, so the info can be reported
201 * if a wrong volume has been mounted.
203 if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) {
208 Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
209 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
212 Dmsg1(100, "opened dev %s OK\n", dev->print_name());
214 /* Read Volume Label */
216 Dmsg0(200, "calling read-vol-label\n");
217 vol_label_status = read_dev_volume_label(dcr);
218 switch (vol_label_status) {
221 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
225 * Send error message generated by read_dev_volume_label()
226 * only we really had a tape mounted. This supresses superfluous
227 * error messages when nothing is mounted.
229 if (tape_previously_mounted) {
230 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
234 if (tape_initially_mounted) {
235 tape_initially_mounted = false;
240 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
242 tape_previously_mounted = true;
244 /* If the device requires mount, close it, so the device can be ejected.
245 * FIXME: This should perhaps be done for all devices. */
246 if (dev->requires_mount()) {
247 force_close_device(dev);
250 /* Call autochanger only once unless ask_sysop called */
251 if (try_autochanger) {
253 Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
254 dcr->VolumeName, dcr->VolCatInfo.Slot);
255 stat = autoload_device(dcr, 0, NULL);
257 try_autochanger = false;
258 continue; /* try reading volume mounted */
262 /* Mount a specific volume and no other */
263 Dmsg0(200, "calling dir_ask_sysop\n");
264 if (!dir_ask_sysop_to_mount_volume(dcr)) {
265 goto get_out; /* error return */
267 try_autochanger = true; /* permit using autochanger again */
268 continue; /* try reading again */
273 Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
280 set_jcr_job_status(jcr, JS_Running);
281 dir_send_job_status(jcr);
282 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
283 dcr->VolumeName, dev->print_name());
296 * Acquire device for writing. We permit multiple writers.
297 * If this is the first one, we read the label.
299 * Returns: NULL if failed for any reason
301 * Note, normally reserve_device_for_append() is called
302 * before this routine.
304 DCR *acquire_device_for_append(DCR *dcr)
306 bool release = false;
307 bool recycle = false;
308 bool do_mount = false;
309 DEVICE *dev = dcr->dev;
312 init_device_wait_timers(dcr);
314 dev->block(BST_DOING_ACQUIRE);
315 Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":
316 (dev->is_dvd()?"DVD":"disk"));
318 if (dcr->reserved_device) {
319 dev->reserved_device--;
320 Dmsg1(200, "Dec reserve=%d\n", dev->reserved_device);
321 dcr->reserved_device = false;
325 * With the reservation system, this should not happen
327 if (dev->can_read()) {
328 Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
329 Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
333 if (dev->can_append()) {
334 Dmsg0(190, "device already in append.\n");
336 * Device already in append mode
338 * Check if we have the right Volume mounted
339 * OK if current volume info OK
340 * OK if next volume matches current volume
341 * otherwise mount desired volume obtained from
342 * dir_find_next_appendable_volume
343 * dev->VolHdr.VolumeName is what is in the drive
344 * dcr->VolumeName is what we pass into the routines, or
345 * get back from the subroutines.
347 bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
348 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
349 !(dir_find_next_appendable_volume(dcr) &&
350 strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
351 Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
353 /* Release volume reserved by dir_find_next_appendable_volume() */
354 if (dcr->VolumeName[0]) {
355 free_unused_volume(dcr);
357 if (dev->num_writers != 0 || dev->reserved_device) {
358 Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"),
359 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
360 Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",
361 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
364 /* Wrong tape mounted, release it, then fall through to get correct one */
365 Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
370 * At this point, the correct tape is already mounted, so
371 * we do not need to do mount_next_write_volume(), unless
372 * we need to recycle the tape.
374 recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
375 Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
376 if (recycle && dev->num_writers != 0) {
377 Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
378 " on device %s because it is in use by another job.\n"),
379 dev->VolHdr.VolumeName, dev->print_name());
382 if (dev->num_writers == 0) {
383 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
387 /* Not already in append mode, so mount the device */
388 Dmsg0(190, "Not in append mode, try mount.\n");
389 ASSERT(dev->num_writers == 0);
393 if (do_mount || recycle) {
394 Dmsg0(190, "Do mount_next_write_vol\n");
395 bool mounted = mount_next_write_volume(dcr, release);
397 if (!job_canceled(jcr)) {
398 /* Reduce "noise" -- don't print if job canceled */
399 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
401 Dmsg1(200, "Could not ready device %s for append.\n",
408 dev->num_writers++; /* we are now a writer */
409 if (jcr->NumVolumes == 0) {
415 * If we jump here, it is an error return because
416 * rtn_dev will still be NULL
427 * This job is done, so release the device. From a Unix standpoint,
428 * the device remains open.
431 bool release_device(DCR *dcr)
434 DEVICE *dev = dcr->dev;
438 Dmsg1(100, "release_device device is %s\n", dev->is_tape()?"tape":"disk");
440 /* if device is reserved, job never started, so release the reserve here */
441 if (dcr->reserved_device) {
442 dev->reserved_device--;
443 Dmsg1(200, "Dec reserve=%d\n", dev->reserved_device);
444 dcr->reserved_device = false;
447 if (dev->can_read()) {
448 dev->clear_read(); /* clear read bit */
450 /******FIXME**** send read volume usage statistics to director */
452 } else if (dev->num_writers > 0) {
454 * Note if WEOT is set, we are at the end of the tape
455 * and may not be positioned correctly, so the
456 * job_media_record and update_vol_info have already been
457 * done, which means we skip them here.
460 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
461 if (dev->is_labeled()) {
462 Dmsg0(100, "dir_create_jobmedia_record. Release\n");
463 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
464 Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
465 dcr->VolCatInfo.VolCatName, jcr->Job);
467 /* If no more writers, write an EOF */
468 if (!dev->num_writers && dev->can_write()) {
470 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
472 if (!dev->at_weot()) {
473 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
474 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
475 /* Note! do volume update before close, which zaps VolCatInfo */
476 Dmsg0(100, "dir_update_vol_info. Release0\n");
477 dir_update_volume_info(dcr, false); /* send Volume info to Director */
483 * If we reach here, it is most likely because the job
484 * has failed, since the device is not in read mode and
485 * there are no writers. It was probably reserved.
489 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
490 if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
491 offline_or_rewind_dev(dev);
495 /* Fire off Alert command and include any output */
496 if (!job_canceled(jcr) && dcr->device->alert_command) {
500 char line[MAXSTRING];
501 alert = get_pool_memory(PM_FNAME);
502 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
503 bpipe = open_bpipe(alert, 0, "r");
505 while (fgets(line, sizeof(line), bpipe->rfd)) {
506 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
508 status = close_bpipe(bpipe);
514 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
515 alert, be.strerror(status));
518 Dmsg1(400, "alert status=%d\n", status);
519 free_pool_memory(alert);
524 pthread_cond_broadcast(&wait_device_release);