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