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 */
27 /*********************************************************************
28 * Acquire device for reading.
29 * The drive should have previously been reserved by calling
30 * reserve_device_for_read(). We read the Volume label from the block and
31 * leave the block pointers just after the label.
33 * Returns: NULL if failed for any reason
36 DCR *acquire_device_for_read(DCR *dcr)
38 DEVICE *dev = dcr->dev;
41 bool tape_previously_mounted;
42 bool tape_initially_mounted;
44 bool try_autochanger = true;
48 dev->block(BST_DOING_ACQUIRE);
50 if (dev->num_writers > 0) {
51 Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"),
52 dev->num_writers, jcr->JobId);
56 /* Find next Volume, if any */
59 Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
63 for (i=1; i<jcr->CurVolume; i++) {
67 goto get_out; /* should not happen */
69 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
70 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
71 dcr->VolCatInfo.Slot = vol->Slot;
72 Dmsg4(100, "===== Vol=%s MT=%s Slt=%d Dev-MT=%s\n", dcr->VolumeName,
73 dcr->media_type, vol->Slot, dev->device->media_type);
75 if (strcmp(dcr->media_type, dev->device->media_type) != 0) {
76 Dmsg2(000, "Wrong MT have=%s want=%s\n", dev->device->media_type,
78 Dmsg1(000, "New storage=%s\n", vol->storage);
81 init_device_wait_timers(dcr);
83 tape_previously_mounted = dev->can_read() || dev->can_append() ||
85 tape_initially_mounted = tape_previously_mounted;
88 /* Volume info is always needed because of VolParts */
89 Dmsg0(200, "dir_get_volume_info\n");
90 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
91 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
95 dev->clear_labeled(); /* force reread of label */
96 if (job_canceled(jcr)) {
97 Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
98 goto get_out; /* error return */
101 * This code ensures that the device is ready for
102 * reading. If it is a file, it opens it.
103 * If it is a tape, it checks the volume name
105 Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
106 if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
107 if (dev->dev_errno == EIO) { /* no tape loaded */
108 Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
109 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
113 Jmsg3(jcr, M_FATAL, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
114 dev->print_name(), dcr->VolumeName, strerror_dev(dev));
117 Dmsg1(100, "opened dev %s OK\n", dev->print_name());
119 /* Read Volume Label */
121 Dmsg0(200, "calling read-vol-label\n");
122 vol_label_status = read_dev_volume_label(dcr);
123 switch (vol_label_status) {
126 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
130 * Send error message generated by read_dev_volume_label()
131 * only we really had a tape mounted. This supresses superfluous
132 * error messages when nothing is mounted.
134 if (tape_previously_mounted) {
135 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
139 if (tape_initially_mounted) {
140 tape_initially_mounted = false;
145 Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
147 tape_previously_mounted = true;
150 * If the device requires mount, close it, so the device can be ejected.
152 if (dev->requires_mount()) {
156 /* Call autochanger only once unless ask_sysop called */
157 if (try_autochanger) {
159 Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
160 dcr->VolumeName, dcr->VolCatInfo.Slot);
161 stat = autoload_device(dcr, 0, NULL);
163 try_autochanger = false;
164 continue; /* try reading volume mounted */
168 /* Mount a specific volume and no other */
169 Dmsg0(200, "calling dir_ask_sysop\n");
170 if (!dir_ask_sysop_to_mount_volume(dcr)) {
171 goto get_out; /* error return */
173 try_autochanger = true; /* permit using autochanger again */
174 continue; /* try reading again */
179 Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
186 set_jcr_job_status(jcr, JS_Running);
187 dir_send_job_status(jcr);
188 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
189 dcr->VolumeName, dev->print_name());
193 if (dcr->reserved_device) {
194 dev->reserved_device--;
195 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
196 dcr->reserved_device = false;
208 * Acquire device for writing. We permit multiple writers.
209 * If this is the first one, we read the label.
211 * Returns: NULL if failed for any reason
213 * Note, normally reserve_device_for_append() is called
214 * before this routine.
216 DCR *acquire_device_for_append(DCR *dcr)
218 bool release = false;
219 bool recycle = false;
220 bool do_mount = false;
221 DEVICE *dev = dcr->dev;
224 init_device_wait_timers(dcr);
226 dev->block(BST_DOING_ACQUIRE);
227 Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":
228 (dev->is_dvd()?"DVD":"disk"));
231 * With the reservation system, this should not happen
233 if (dev->can_read()) {
234 Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
235 Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
239 if (dev->can_append()) {
240 Dmsg0(190, "device already in append.\n");
242 * Device already in append mode
244 * Check if we have the right Volume mounted
245 * OK if current volume info OK
246 * OK if next volume matches current volume
247 * otherwise mount desired volume obtained from
248 * dir_find_next_appendable_volume
249 * dev->VolHdr.VolumeName is what is in the drive
250 * dcr->VolumeName is what we pass into the routines, or
251 * get back from the subroutines.
253 bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
254 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
255 !(dir_find_next_appendable_volume(dcr) &&
256 strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
257 Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
259 /* Release volume reserved by dir_find_next_appendable_volume() */
260 if (dcr->VolumeName[0]) {
261 free_unused_volume(dcr);
263 if (dev->num_writers != 0) {
264 Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"),
265 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
266 Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",
267 dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
270 /* Wrong tape mounted, release it, then fall through to get correct one */
271 Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
276 * At this point, the correct tape is already mounted, so
277 * we do not need to do mount_next_write_volume(), unless
278 * we need to recycle the tape.
280 recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
281 Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
282 if (recycle && dev->num_writers != 0) {
283 Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
284 " on device %s because it is in use by another job.\n"),
285 dev->VolHdr.VolumeName, dev->print_name());
288 if (dev->num_writers == 0) {
289 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
293 /* Not already in append mode, so mount the device */
294 Dmsg0(190, "Not in append mode, try mount.\n");
295 ASSERT(dev->num_writers == 0);
299 if (do_mount || recycle) {
300 Dmsg0(190, "Do mount_next_write_vol\n");
301 bool mounted = mount_next_write_volume(dcr, release);
303 if (!job_canceled(jcr)) {
304 /* Reduce "noise" -- don't print if job canceled */
305 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
307 Dmsg1(200, "Could not ready device %s for append.\n",
314 dev->num_writers++; /* we are now a writer */
315 if (jcr->NumVolumes == 0) {
319 if (dcr->reserved_device) {
320 dev->reserved_device--;
321 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
322 dcr->reserved_device = false;
333 if (dcr->reserved_device) {
334 dev->reserved_device--;
335 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
336 dcr->reserved_device = false;
345 * This job is done, so release the device. From a Unix standpoint,
346 * the device remains open.
349 bool release_device(DCR *dcr)
352 DEVICE *dev = dcr->dev;
356 Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
358 /* if device is reserved, job never started, so release the reserve here */
359 if (dcr->reserved_device) {
360 dev->reserved_device--;
361 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
362 dcr->reserved_device = false;
365 if (dev->can_read()) {
366 dev->clear_read(); /* clear read bit */
368 /******FIXME**** send read volume usage statistics to director */
370 } else if (dev->num_writers > 0) {
372 * Note if WEOT is set, we are at the end of the tape
373 * and may not be positioned correctly, so the
374 * job_media_record and update_vol_info have already been
375 * done, which means we skip them here.
378 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
379 if (dev->is_labeled()) {
380 Dmsg0(100, "dir_create_jobmedia_record. Release\n");
381 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
382 Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
383 dcr->VolCatInfo.VolCatName, jcr->Job);
385 /* If no more writers, write an EOF */
386 if (!dev->num_writers && dev->can_write()) {
388 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
390 if (!dev->at_weot()) {
391 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
392 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
393 /* Note! do volume update before close, which zaps VolCatInfo */
394 Dmsg0(100, "dir_update_vol_info. Release0\n");
395 dir_update_volume_info(dcr, false); /* send Volume info to Director */
401 * If we reach here, it is most likely because the job
402 * has failed, since the device is not in read mode and
403 * there are no writers. It was probably reserved.
407 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
408 if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
412 /* Fire off Alert command and include any output */
413 if (!job_canceled(jcr) && dcr->device->alert_command) {
417 char line[MAXSTRING];
418 alert = get_pool_memory(PM_FNAME);
419 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
420 bpipe = open_bpipe(alert, 0, "r");
422 while (fgets(line, sizeof(line), bpipe->rfd)) {
423 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
425 status = close_bpipe(bpipe);
431 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
432 alert, be.strerror(status));
435 Dmsg1(400, "alert status=%d\n", status);
436 free_pool_memory(alert);
439 if (jcr->read_dcr == dcr) {
440 jcr->read_dcr = NULL;
442 if (jcr->dcr == dcr) {
450 * Create a new Device Control Record and attach
451 * it to the device (if this is a real job).
453 DCR *new_dcr(JCR *jcr, DEVICE *dev)
455 DCR *dcr = (DCR *)malloc(sizeof(DCR));
456 memset(dcr, 0, sizeof(DCR));
460 dcr->device = dev->device;
461 dcr->block = new_block(dev);
462 dcr->rec = new_record();
463 dcr->max_job_spool_size = dev->device->max_job_spool_size;
464 /* Attach this dcr only if dev is initialized */
465 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
466 dev->attached_dcrs->append(dcr); /* attach dcr to device */
467 // jcr->dcrs->append(dcr); /* put dcr in list for Job */
475 * Search the dcrs list for the given dcr. If it is found,
476 * as it should be, then remove it. Also zap the jcr pointer
477 * to the dcr if it is the same one.
480 static void remove_dcr_from_dcrs(DCR *dcr)
486 int num = jcr->dcrs->size();
487 for (i=0; i < num; i++) {
488 ldcr = (DCR *)jcr->dcrs->get(i);
490 jcr->dcrs->remove(i);
491 if (jcr->dcr == dcr) {
501 * Free up all aspects of the given dcr -- i.e. dechain it,
502 * release allocated memory, zap pointers, ...
504 void free_dcr(DCR *dcr)
507 DEVICE *dev = dcr->dev;
509 if (dcr->reserved_device) {
511 dev->reserved_device--;
512 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
513 dcr->reserved_device = false;
514 /* If we set read mode in reserving, remove it */
515 if (dev->can_read()) {
518 if (dev->num_writers < 0) {
519 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
520 dev->num_writers = 0;
525 /* Detach this dcr only if the dev is initialized */
526 if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
527 dev->attached_dcrs->remove(dcr); /* detach dcr from device */
528 // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */
531 free_block(dcr->block);
534 free_record(dcr->rec);
537 dcr->jcr->dcr = NULL;
539 free_unused_volume(dcr); /* free unused vols attached to this dcr */
541 pthread_cond_broadcast(&dev->wait_next_vol);
542 pthread_cond_broadcast(&wait_device_release);