1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
8
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 * Routines to acquire and release a device for read/write
21 *
22 * Written by Kern Sibbald, August MMII
23 */
24
25 #include "bacula.h" /* pull in global headers */
26 #include "stored.h" /* pull in Storage Deamon headers */
27
28 static int const rdbglvl = 100;
29
30 /* Forward referenced functions */
31 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol);
32
33 /*********************************************************************
34 * Acquire device for reading.
35 * The drive should have previously been reserved by calling
36 * reserve_device_for_read(). We read the Volume label from the block and
37 * leave the block pointers just after the label.
38 *
39 * Returns: false if failed for any reason
40 * true if successful
41 */
acquire_device_for_read(DCR * dcr)42 bool acquire_device_for_read(DCR *dcr)
43 {
44 DEVICE *dev;
45 JCR *jcr = dcr->jcr;
46 bool ok = false;
47 bool tape_previously_mounted;
48 VOL_LIST *vol;
49 bool try_autochanger = true;
50 int i;
51 int vol_label_status;
52 int retry = 0;
53
54 Enter(rdbglvl);
55 dev = dcr->dev;
56 ASSERT2(!dev->adata, "Called with adata dev. Wrong!");
57 dev->Lock_read_acquire();
58 Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
59 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
60 dev->dblock(BST_DOING_ACQUIRE);
61
62 if (dev->num_writers > 0) {
63 Jmsg2(jcr, M_FATAL, 0, _("Acquire read: num_writers=%d not zero. Job %d canceled.\n"),
64 dev->num_writers, jcr->JobId);
65 goto get_out;
66 }
67
68 /* Find next Volume, if any */
69 vol = jcr->VolList;
70 if (!vol) {
71 char ed1[50];
72 Jmsg(jcr, M_FATAL, 0, _("No volumes specified for reading. Job %s canceled.\n"),
73 edit_int64(jcr->JobId, ed1));
74 goto get_out;
75 }
76 jcr->CurReadVolume++;
77 for (i=1; i<jcr->CurReadVolume; i++) {
78 vol = vol->next;
79 }
80 if (!vol) {
81 Jmsg(jcr, M_FATAL, 0, _("Logic error: no next volume to read. Numvol=%d Curvol=%d\n"),
82 jcr->NumReadVolumes, jcr->CurReadVolume);
83 goto get_out; /* should not happen */
84 }
85 set_dcr_from_vol(dcr, vol);
86
87 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
88 Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
89 goto get_out;
90 }
91
92 Dmsg2(rdbglvl, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot);
93
94 /*
95 * If the MediaType requested for this volume is not the
96 * same as the current drive, we attempt to find the same
97 * device that was used to write the orginal volume. If
98 * found, we switch to using that device.
99 *
100 * N.B. A lot of routines rely on the dcr pointer not changing
101 * read_records.c even has multiple dcrs cached, so we take care
102 * here to release all important parts of the dcr and re-acquire
103 * them such as the block pointer (size may change), but we do
104 * not release the dcr.
105 */
106 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
107 if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
108 RCTX rctx;
109 DIRSTORE *store;
110 int stat;
111
112 Jmsg4(jcr, M_INFO, 0, _("Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
113 " %s device=%s\n"),
114 dcr->media_type, dev->device->media_type, dev->print_type(),
115 dev->print_name());
116 Dmsg4(rdbglvl, "Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
117 " %s device=%s\n",
118 dcr->media_type, dev->device->media_type,
119 dev->print_type(), dev->print_name());
120
121 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
122
123 dev->dunblock(DEV_UNLOCKED);
124
125 lock_reservations();
126 memset(&rctx, 0, sizeof(RCTX));
127 rctx.jcr = jcr;
128 jcr->read_dcr = dcr;
129 jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
130 rctx.any_drive = true;
131 rctx.device_name = vol->device;
132 store = new DIRSTORE;
133 memset(store, 0, sizeof(DIRSTORE));
134 store->name[0] = 0; /* No storage name */
135 bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
136 bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
137 bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
138 store->append = false;
139 rctx.store = store;
140 clean_device(dcr); /* clean up the dcr */
141
142 /*
143 * Search for a new device
144 */
145 stat = search_res_for_device(rctx);
146 release_reserve_messages(jcr); /* release queued messages */
147 unlock_reservations();
148
149 if (stat == 1) { /* found new device to use */
150 /*
151 * Switching devices, so acquire lock on new device,
152 * then release the old one.
153 */
154 dcr->dev->Lock_read_acquire(); /* lock new one */
155 dev->Unlock_read_acquire(); /* release old one */
156 dev = dcr->dev; /* get new device pointer */
157 dev->dblock(BST_DOING_ACQUIRE);
158
159 dcr->VolumeName[0] = 0;
160 Jmsg(jcr, M_INFO, 0, _("Media Type change. New read %s device %s chosen.\n"),
161 dev->print_type(), dev->print_name());
162 Dmsg2(50, "Media Type change. New read %s device %s chosen.\n",
163 dev->print_type(), dev->print_name());
164 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
165 Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
166 goto get_out;
167 }
168 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
169 dcr->setVolCatName(vol->VolumeName);
170 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
171 dcr->VolCatInfo.Slot = vol->Slot;
172 dcr->VolCatInfo.InChanger = vol->Slot > 0;
173 bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
174 bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
175 } else {
176 /* error */
177 Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
178 vol->VolumeName);
179 Dmsg1(rdbglvl, "No suitable device found to read Volume \"%s\"\n", vol->VolumeName);
180 goto get_out;
181 }
182 }
183 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
184
185 dev->clear_unload();
186
187 if (dev->vol && dev->vol->is_swapping()) {
188 dev->vol->set_slot(vol->Slot);
189 Dmsg3(rdbglvl, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->get_slot(),
190 dev->vol->vol_name, dev->print_name());
191 }
192
193 init_device_wait_timers(dcr);
194
195 tape_previously_mounted = dev->can_read() || dev->can_append() ||
196 dev->is_labeled();
197 // tape_initially_mounted = tape_previously_mounted;
198
199 /* Volume info is always needed because of VolType */
200 Dmsg1(rdbglvl, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
201 if (!dir_get_volume_info(dcr, dcr->VolumeName, GET_VOL_INFO_FOR_READ)) {
202 Dmsg2(rdbglvl, "dir_get_vol_info failed for vol=%s: %s\n",
203 dcr->VolumeName, jcr->errmsg);
204 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
205 }
206 dev->set_load(); /* set to load volume */
207
208 for ( ;; ) {
209 /* If not polling limit retries */
210 if (!dev->poll && retry++ > 10) {
211 break;
212 }
213 dev->clear_labeled(); /* force reread of label */
214 if (job_canceled(jcr)) {
215 char ed1[50];
216 Mmsg1(dev->errmsg, _("Job %s canceled.\n"), edit_int64(jcr->JobId, ed1));
217 Jmsg(jcr, M_INFO, 0, dev->errmsg);
218 goto get_out; /* error return */
219 }
220
221 dcr->do_unload();
222 dcr->do_swapping(SD_READ);
223 dcr->do_load(SD_READ);
224 set_dcr_from_vol(dcr, vol); /* refresh dcr with desired volume info */
225
226 /*
227 * This code ensures that the device is ready for
228 * reading. If it is a file, it opens it.
229 * If it is a tape, it checks the volume name
230 */
231 Dmsg1(rdbglvl, "open vol=%s\n", dcr->VolumeName);
232 if (!dev->open_device(dcr, OPEN_READ_ONLY)) {
233 if (!dev->poll) {
234 Jmsg4(jcr, M_WARNING, 0, _("Read open %s device %s Volume \"%s\" failed: ERR=%s\n"),
235 dev->print_type(), dev->print_name(), dcr->VolumeName, dev->bstrerror());
236 }
237 goto default_path;
238 }
239 Dmsg1(rdbglvl, "opened dev %s OK\n", dev->print_name());
240
241 /* Read Volume Label */
242 Dmsg0(rdbglvl, "calling read-vol-label\n");
243 vol_label_status = dev->read_dev_volume_label(dcr);
244 switch (vol_label_status) {
245 case VOL_OK:
246 Dmsg1(rdbglvl, "Got correct volume. VOL_OK: %s\n", dcr->VolCatInfo.VolCatName);
247 ok = true;
248 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
249 break; /* got it */
250 case VOL_IO_ERROR:
251 Dmsg0(rdbglvl, "IO Error\n");
252 /*
253 * Send error message generated by dev->read_dev_volume_label()
254 * only we really had a tape mounted. This supresses superfluous
255 * error messages when nothing is mounted.
256 */
257 if (tape_previously_mounted) {
258 Jmsg(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
259 }
260 goto default_path;
261 case VOL_TYPE_ERROR:
262 Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
263 goto get_out;
264 case VOL_NAME_ERROR:
265 Dmsg3(rdbglvl, "Vol name=%s want=%s drv=%s.\n", dev->VolHdr.VolumeName,
266 dcr->VolumeName, dev->print_name());
267 if (dev->is_volume_to_unload()) {
268 goto default_path;
269 }
270 dev->set_unload(); /* force unload of unwanted tape */
271 if (!unload_autochanger(dcr, -1)) {
272 /* at least free the device so we can re-open with correct volume */
273 dev->close(dcr);
274 free_volume(dev);
275 }
276 dev->set_load();
277 /* Fall through */
278 default:
279 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
280 default_path:
281 Dmsg0(rdbglvl, "default path\n");
282 tape_previously_mounted = true;
283
284 /*
285 * If the device requires mount, close it, so the device can be ejected.
286 */
287 if (dev->requires_mount()) {
288 dev->close(dcr);
289 free_volume(dev);
290 }
291
292 /* Call autochanger only once unless ask_sysop called */
293 if (try_autochanger) {
294 int stat;
295 Dmsg2(rdbglvl, "calling autoload Vol=%s Slot=%d\n",
296 dcr->VolumeName, dcr->VolCatInfo.Slot);
297 stat = autoload_device(dcr, SD_READ, NULL);
298 if (stat > 0) {
299 try_autochanger = false;
300 continue; /* try reading volume mounted */
301 }
302 }
303
304 /* Mount a specific volume and no other */
305 Dmsg0(rdbglvl, "calling dir_ask_sysop\n");
306 if (!dir_ask_sysop_to_mount_volume(dcr, SD_READ)) {
307 goto get_out; /* error return */
308 }
309
310 /* Volume info is always needed because of VolType */
311 Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
312 if (!dir_get_volume_info(dcr, dcr->VolumeName, GET_VOL_INFO_FOR_READ)) {
313 Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n",
314 dcr->VolumeName, jcr->errmsg);
315 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
316 }
317 dev->set_load(); /* set to load volume */
318
319 try_autochanger = true; /* permit trying the autochanger again */
320
321 continue; /* try reading again */
322 } /* end switch */
323 break;
324 } /* end for loop */
325
326 if (!ok) {
327 Jmsg2(jcr, M_FATAL, 0, _("Too many errors trying to mount %s device %s for reading.\n"),
328 dev->print_type(), dev->print_name());
329 goto get_out;
330 }
331
332 dev->clear_append();
333 dev->set_read();
334 jcr->sendJobStatus(JS_Running);
335 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on %s device %s.\n"),
336 dcr->VolumeName, dev->print_type(), dev->print_name());
337
338 get_out:
339 dev->Lock();
340 /* If failed and not writing plugin close device */
341 if (!ok && dev->num_writers == 0 && dev->num_reserved() == 0) {
342 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
343 }
344 /*
345 * Normally we are blocked, but in at least one error case above
346 * we are not blocked because we unsuccessfully tried changing
347 * devices.
348 */
349 if (dev->is_blocked()) {
350 dev->dunblock(DEV_LOCKED);
351 } else {
352 dev->Unlock(); /* dunblock() unlock the device too */
353 }
354 Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
355 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
356 dev->Unlock_read_acquire();
357 Leave(rdbglvl);
358 return ok;
359 }
360
361 /*
362 * Acquire device for writing. We permit multiple writers.
363 * If this is the first one, we read the label.
364 *
365 * Returns: NULL if failed for any reason
366 * dcr if successful.
367 * Note, normally reserve_device_for_append() is called
368 * before this routine.
369 */
acquire_device_for_append(DCR * dcr)370 DCR *acquire_device_for_append(DCR *dcr)
371 {
372 DEVICE *dev = dcr->dev;
373 JCR *jcr = dcr->jcr;
374 bool ok = false;
375 bool have_vol = false;
376
377 Enter(200);
378 dcr->set_ameta();
379 init_device_wait_timers(dcr);
380
381 dev->Lock_acquire(); /* only one job at a time */
382 dev->Lock();
383 Dmsg1(100, "acquire_append device is %s\n", dev->print_type());
384 /*
385 * With the reservation system, this should not happen
386 */
387 if (dev->can_read()) {
388 Mmsg2(jcr->errmsg, "Want to append but %s device %s is busy reading.\n",
389 dev->print_type(), dev->print_name());
390 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
391 Dmsg0(50, jcr->errmsg);
392 goto get_out;
393 }
394
395 dev->clear_unload();
396
397 /*
398 * have_vol defines whether or not mount_next_write_volume should
399 * ask the Director again about what Volume to use.
400 */
401 if (dev->can_append() && dcr->is_suitable_volume_mounted() &&
402 strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") != 0) {
403 Dmsg0(190, "device already in append.\n");
404 /*
405 * At this point, the correct tape is already mounted, so
406 * we do not need to do mount_next_write_volume(), unless
407 * we need to recycle the tape.
408 */
409 if (dev->num_writers == 0) {
410 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
411 }
412 have_vol = dcr->is_tape_position_ok();
413 }
414
415 if (!have_vol) {
416 dev->rLock(true);
417 block_device(dev, BST_DOING_ACQUIRE);
418 dev->Unlock();
419 Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
420 if (!dcr->mount_next_write_volume()) {
421 if (!job_canceled(jcr) && !jcr->is_incomplete()) {
422 /* Reduce "noise" -- don't print if job canceled */
423 Mmsg2(jcr->errmsg, _("Could not ready %s device %s for append.\n"),
424 dev->print_type(), dev->print_name());
425 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
426 Dmsg0(50, jcr->errmsg);
427 }
428 dev->Lock();
429 unblock_device(dev);
430 goto get_out;
431 }
432 Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
433 dev->Lock();
434 unblock_device(dev);
435 }
436
437 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
438 Mmsg0(jcr->errmsg, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
439 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
440 Dmsg0(50, jcr->errmsg);
441 goto get_out;
442 }
443
444 dev->num_writers++; /* we are now a writer */
445 if (jcr->NumWriteVolumes == 0) {
446 jcr->NumWriteVolumes = 1;
447 }
448 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */
449
450 ok = dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
451 if (!ok) { /* We cannot use this volume/device */
452 Jmsg(jcr, M_WARNING, 0, _("Warning cannot use Volume \"%s\", update_volume_info failed.\n"),
453 dev->VolCatInfo.VolCatName);
454 dev->num_writers--; /* on fail update_volume do not update num_writers */
455 /* TODO: See if we revert the NumWriteVolumes as well */
456 }
457
458 Dmsg4(100, "=== nwriters=%d nres=%d vcatjob=%d dev=%s\n",
459 dev->num_writers, dev->num_reserved(), dev->VolCatInfo.VolCatJobs,
460 dev->print_name());
461
462 get_out:
463 /* Don't plugin close here, we might have multiple writers */
464 dcr->clear_reserved();
465 dev->Unlock();
466 dev->Unlock_acquire();
467 Leave(200);
468 return ok ? dcr : NULL;
469 }
470
471 /*
472 * This job is done, so release the device. From a Unix standpoint,
473 * the device remains open.
474 *
475 * Note, if we were spooling, we may enter with the device blocked.
476 * We unblock at the end, only if it was us who blocked the
477 * device.
478 *
479 */
release_device(DCR * dcr)480 bool release_device(DCR *dcr)
481 {
482 JCR *jcr = dcr->jcr;
483 DEVICE *dev = dcr->dev;
484 bool ok = true;
485 char tbuf[100];
486 bsteal_lock_t holder;
487
488 dev->Lock();
489 if (!obtain_device_block(dev,
490 &holder,
491 0, /* infinite wait */
492 BST_RELEASING)) {
493 ASSERT2(0, "unable to obtain device block");
494 }
495
496 lock_volumes();
497 Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
498
499 /* if device is reserved, job never started, so release the reserve here */
500 dcr->clear_reserved();
501
502 if (dev->can_read()) {
503 VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
504 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
505 dev->clear_read(); /* clear read bit */
506 Dmsg2(150, "dir_update_vol_info. label=%d Vol=%s\n",
507 dev->is_labeled(), vol->VolCatName);
508 if (dev->is_labeled() && vol->VolCatName[0] != 0) {
509 dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
510 remove_read_volume(jcr, dcr->VolumeName);
511 volume_unused(dcr);
512 }
513 } else if (dev->num_writers > 0) {
514 /*
515 * Note if WEOT is set, we are at the end of the tape
516 * and may not be positioned correctly, so the
517 * job_media_record and update_vol_info have already been
518 * done, which means we skip them here.
519 */
520 dev->num_writers--;
521 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
522 if (dev->is_labeled()) {
523 if (!dev->at_weot()) {
524 Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
525 dev->getVolCatName(), dev->print_name());
526 }
527 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
528 Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
529 dcr->getVolCatName(), jcr->Job);
530 }
531 /* If no more writers, and no errors, and wrote something, write an EOF */
532 if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
533 dev->weof(dcr, 1);
534 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
535 }
536 if (!dev->at_weot()) {
537 dev->VolCatInfo.VolCatFiles = dev->get_file(); /* set number of files */
538 /* Note! do volume update before close, which zaps VolCatInfo */
539 dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
540 Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
541 dev->getVolCatName(), dev->print_name());
542 }
543 if (dev->num_writers == 0) { /* if not being used */
544 volume_unused(dcr); /* we obviously are not using the volume */
545 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
546 } else {
547 /* Other jobs are writing, make sure our data is safely written */
548 if (!dev->sync_data(dcr)) {
549 Jmsg(jcr, M_ERROR, 0, ("%s\n"), dev->errmsg);
550 }
551 }
552 }
553 } else {
554 /*
555 * If we reach here, it is most likely because the job
556 * has failed, since the device is not in read mode and
557 * there are no writers. It was probably reserved.
558 */
559 volume_unused(dcr);
560 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
561 }
562 Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
563 dev->print_name());
564
565 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
566 if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
567 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
568 /* Sync the data before close() if needed for this device */
569 if (!dev->sync_data(dcr)) {
570 Jmsg(jcr, M_ERROR, 0, ("%s\n"), dev->errmsg);
571 }
572 if (!dev->close(dcr) && dev->errmsg[0]) {
573 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
574 }
575 free_volume(dev);
576 }
577 unlock_volumes();
578
579 /* Do new tape alert code */
580 dev->get_tape_alerts(dcr);
581 /* alert_callback is in tape_alert.c -- show only most recent (last) alert */
582 dev->show_tape_alerts(dcr, list_long, list_last, alert_callback);
583
584 pthread_cond_broadcast(&dev->wait_next_vol);
585 Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
586 (uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
587 pthread_cond_broadcast(&wait_device_release);
588
589 give_back_device_block(dev, &holder);
590 /*
591 * If we are the thread that blocked the device, then unblock it
592 */
593 if (pthread_equal(dev->no_wait_id, pthread_self())) {
594 dev->dunblock(true);
595 } else {
596 dev->Unlock();
597 }
598
599 dev->end_of_job(dcr, TRUNC_CONF_DEFAULT);
600
601 if (dcr->keep_dcr) {
602 dev->detach_dcr_from_dev(dcr);
603 } else {
604 free_dcr(dcr);
605 }
606 Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
607 (uint32_t)jcr->JobId);
608 return ok;
609 }
610
611 /*
612 * Clean up the device for reuse without freeing the memory
613 */
clean_device(DCR * dcr)614 bool clean_device(DCR *dcr)
615 {
616 bool ok;
617 dcr->keep_dcr = true; /* do not free the dcr */
618 ok = release_device(dcr);
619 dcr->keep_dcr = false;
620 return ok;
621 }
622
623 /*
624 * Create a new Device Control Record and attach
625 * it to the device (if this is a real job).
626 * Note, this has been updated so that it can be called first
627 * without a DEVICE, then a second or third time with a DEVICE,
628 * and each time, it should cleanup and point to the new device.
629 * This should facilitate switching devices.
630 * Note, each dcr must point to the controlling job (jcr). However,
631 * a job can have multiple dcrs, so we must not store in the jcr's
632 * structure as previously. The higher level routine must store
633 * this dcr in the right place
634 *
635 */
new_dcr(JCR * jcr,DCR * dcr,DEVICE * dev,bool writing)636 DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev, bool writing)
637 {
638 DEVICE *odev;
639 if (!dcr) {
640 dcr = (DCR *)malloc(sizeof(DCR));
641 memset(dcr, 0, sizeof(DCR));
642 dcr->tid = pthread_self();
643 dcr->uploads = New(alist(100, false));
644 dcr->downloads = New(alist(100, false));
645 dcr->spool_fd = -1;
646 }
647 dcr->jcr = jcr; /* point back to jcr */
648 odev = dcr->dev;
649 if (dcr->attached_to_dev && odev) {
650 Dmsg2(100, "Detach 0x%x from olddev %s\n", dcr, odev->print_name());
651 odev->detach_dcr_from_dev(dcr);
652 }
653 ASSERT2(!dcr->attached_to_dev, "DCR is attached. Wrong!");
654 /* Set device information, possibly change device */
655 if (dev) {
656 ASSERT2(!dev->adata, "Called with adata dev. Wrong!");
657 dev->free_dcr_blocks(dcr);
658 dev->new_dcr_blocks(dcr);
659 if (dcr->rec) {
660 free_record(dcr->rec);
661 }
662 dcr->rec = new_record();
663 /* Use job spoolsize prior to device spoolsize */
664 if (jcr && jcr->spool_size) {
665 dcr->max_job_spool_size = jcr->spool_size;
666 } else {
667 dcr->max_job_spool_size = dev->device->max_job_spool_size;
668 }
669 dcr->device = dev->device;
670 dcr->set_dev(dev);
671 Dmsg2(100, "Attach 0x%x to dev %s\n", dcr, dev->print_name());
672 dev->attach_dcr_to_dev(dcr);
673 }
674 if (writing) {
675 dcr->set_writing();
676 } else {
677 dcr->clear_writing();
678 }
679 return dcr;
680 }
681
682 /*
683 * Search the dcrs list for the given dcr. If it is found,
684 * as it should be, then remove it. Also zap the jcr pointer
685 * to the dcr if it is the same one.
686 *
687 * Note, this code will be turned on when we can write to multiple
688 * dcrs at the same time.
689 */
690 #ifdef needed
remove_dcr_from_dcrs(DCR * dcr)691 static void remove_dcr_from_dcrs(DCR *dcr)
692 {
693 JCR *jcr = dcr->jcr;
694 if (jcr->dcrs) {
695 int i = 0;
696 DCR *ldcr;
697 int num = jcr->dcrs->size();
698 for (i=0; i < num; i++) {
699 ldcr = (DCR *)jcr->dcrs->get(i);
700 if (ldcr == dcr) {
701 jcr->dcrs->remove(i);
702 if (jcr->dcr == dcr) {
703 jcr->dcr = NULL;
704 }
705 }
706 }
707 }
708 }
709 #endif
710
attach_dcr_to_dev(DCR * dcr)711 void DEVICE::attach_dcr_to_dev(DCR *dcr)
712 {
713 JCR *jcr = dcr->jcr;
714
715 Lock_dcrs();
716 jcr = dcr->jcr;
717 if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
718 /* ***FIXME*** return error if dev not initiated */
719 if (!dcr->attached_to_dev && initiated && jcr && jcr->getJobType() != JT_SYSTEM) {
720 ASSERT2(!adata, "Called on adata dev. Wrong!");
721 Dmsg4(200, "Attach Jid=%d dcr=%p size=%d dev=%s\n", (uint32_t)jcr->JobId,
722 dcr, attached_dcrs->size(), print_name());
723 attached_dcrs->append(dcr); /* attach dcr to device */
724 dcr->attached_to_dev = true;
725 }
726 Unlock_dcrs();
727 }
728
729 /*
730 * Note!! Do not enter with dev->Lock() since unreserve_device()
731 * is going to lock it too.
732 */
detach_dcr_from_dev(DCR * dcr)733 void DEVICE::detach_dcr_from_dev(DCR *dcr)
734 {
735 Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
736
737 Lock();
738 Lock_dcrs();
739 /* Detach this dcr only if attached */
740 if (dcr->attached_to_dev) {
741 ASSERT2(!adata, "Called with adata dev. Wrong!");
742 dcr->unreserve_device(true);
743 Dmsg4(200, "Detach Jid=%d dcr=%p size=%d to dev=%s\n", (uint32_t)dcr->jcr->JobId,
744 dcr, attached_dcrs->size(), print_name());
745 dcr->attached_to_dev = false;
746 if (attached_dcrs->size()) {
747 attached_dcrs->remove(dcr); /* detach dcr from device */
748 }
749 }
750 /* Check if someone accidentally left a drive reserved, and clear it */
751 if (attached_dcrs->size() == 0 && num_reserved() > 0) {
752 Pmsg3(000, "Warning!!! Detach %s DCR: dcrs=0 reserved=%d setting reserved==0. dev=%s\n",
753 dcr->is_writing() ? "writing" : "reading", num_reserved(), print_name());
754 m_num_reserved = 0;
755 }
756 dcr->attached_to_dev = false;
757 Unlock_dcrs();
758 Unlock();
759 }
760
761 /*
762 * Free up all aspects of the given dcr -- i.e. dechain it,
763 * release allocated memory, zap pointers, ...
764 */
free_dcr(DCR * dcr)765 void free_dcr(DCR *dcr)
766 {
767 JCR *jcr;
768
769 jcr = dcr->jcr;
770
771 if (dcr->dev) {
772 dcr->dev->detach_dcr_from_dev(dcr);
773 }
774
775 if (dcr->dev) {
776 dcr->dev->free_dcr_blocks(dcr);
777 } else {
778 dcr->ameta_block = NULL;
779 free_block(dcr->block);
780 }
781 if (dcr->rec) {
782 free_record(dcr->rec);
783 }
784 if (jcr && jcr->dcr == dcr) {
785 jcr->dcr = NULL;
786 }
787 if (jcr && jcr->read_dcr == dcr) {
788 jcr->read_dcr = NULL;
789 }
790 delete dcr->uploads;
791 delete dcr->downloads;
792 free(dcr);
793 }
794
set_dcr_from_vol(DCR * dcr,VOL_LIST * vol)795 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol)
796 {
797 /*
798 * Note, if we want to be able to work from a .bsr file only
799 * for disaster recovery, we must "simulate" reading the catalog
800 */
801 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
802 dcr->setVolCatName(vol->VolumeName);
803 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
804 dcr->VolCatInfo.Slot = vol->Slot;
805 dcr->VolCatInfo.InChanger = vol->Slot > 0;
806 dcr->CurrentVol = vol; /* Keep VOL_LIST pointer (freed at the end of the job) */
807 }
808