1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2002-2013 Free Software Foundation Europe e.V.
5    Copyright (C) 2011-2012 Planets Communications B.V.
6    Copyright (C) 2013-2018 Bareos GmbH & Co. KG
7 
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    Affero General Public License for more details.
17 
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22 */
23 /*
24  * Kern Sibbald, August MMII
25  */
26 /**
27  * @file
28  * Routines to acquire and release a device for read/write
29  */
30 
31 #include "include/bareos.h" /* pull in global headers */
32 #include "stored/stored.h"  /* pull in Storage Daemon headers */
33 #include "stored/acquire.h"
34 #include "stored/autochanger.h"
35 #include "stored/bsr.h"
36 #include "stored/job.h"
37 #include "stored/label.h"
38 #include "stored/sd_plugins.h"
39 #include "stored/sd_stats.h"
40 #include "stored/wait.h"
41 #include "lib/berrno.h"
42 #include "lib/edit.h"
43 #include "lib/berrno.h"
44 #include "include/jcr.h"
45 #include "stored/block.h"
46 #include "stored/jcr_private.h"
47 
48 namespace storagedaemon {
49 
DeviceControlRecord()50 DeviceControlRecord::DeviceControlRecord()
51 {
52   PoolMem errmsg(PM_MESSAGE);
53   int errstat;
54 
55   tid = pthread_self();
56   spool_fd = -1;
57   if ((errstat = pthread_mutex_init(&mutex_, NULL)) != 0) {
58     BErrNo be;
59 
60     Mmsg(errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat));
61     Jmsg0(NULL, M_ERROR_TERM, 0, errmsg.c_str());
62   }
63 
64   if ((errstat = pthread_mutex_init(&r_mutex, NULL)) != 0) {
65     BErrNo be;
66 
67     Mmsg(errmsg, _("Unable to init r_mutex: ERR=%s\n"), be.bstrerror(errstat));
68     Jmsg0(NULL, M_ERROR_TERM, 0, errmsg.c_str());
69   }
70 }
71 
72 static int const rdebuglevel = 100;
73 
74 /* Forward referenced functions */
75 static void AttachDcrToDev(DeviceControlRecord* dcr);
76 static void DetachDcrFromDev(DeviceControlRecord* dcr);
77 static void SetDcrFromVol(DeviceControlRecord* dcr, VolumeList* vol);
78 
79 /**
80  * Acquire device for reading.
81  *  The drive should have previously been reserved by calling
82  *  ReserveDeviceForRead(). We read the Volume label from the block and
83  *  leave the block pointers just after the label.
84  *
85  *  Returns: NULL if failed for any reason
86  *           dcr  if successful
87  */
AcquireDeviceForRead(DeviceControlRecord * dcr)88 bool AcquireDeviceForRead(DeviceControlRecord* dcr)
89 {
90   Device* dev;
91   JobControlRecord* jcr = dcr->jcr;
92   bool retval = false;
93   bool tape_previously_mounted;
94   VolumeList* vol;
95   bool try_autochanger = true;
96   int i;
97   int vol_label_status;
98   int retry = 0;
99 
100   Enter(rdebuglevel);
101   dev = dcr->dev;
102   dev->Lock_read_acquire();
103   Dmsg2(rdebuglevel, "dcr=%p dev=%p\n", dcr, dcr->dev);
104   Dmsg2(rdebuglevel, "MediaType dcr=%s dev=%s\n", dcr->media_type,
105         dev->device->media_type);
106   dev->dblock(BST_DOING_ACQUIRE);
107 
108   if (dev->num_writers > 0) {
109     Jmsg2(jcr, M_FATAL, 0,
110           _("Acquire read: num_writers=%d not zero. Job %d canceled.\n"),
111           dev->num_writers, jcr->JobId);
112     goto get_out;
113   }
114 
115   /* Find next Volume, if any */
116   vol = jcr->impl->VolList;
117   if (!vol) {
118     char ed1[50];
119     Jmsg(jcr, M_FATAL, 0,
120          _("No volumes specified for reading. Job %s canceled.\n"),
121          edit_int64(jcr->JobId, ed1));
122     goto get_out;
123   }
124   jcr->impl->CurReadVolume++;
125   for (i = 1; i < jcr->impl->CurReadVolume; i++) { vol = vol->next; }
126   if (!vol) {
127     Jmsg(jcr, M_FATAL, 0,
128          _("Logic error: no next volume to read. Numvol=%d Curvol=%d\n"),
129          jcr->impl->NumReadVolumes, jcr->impl->CurReadVolume);
130     goto get_out; /* should not happen */
131   }
132   SetDcrFromVol(dcr, vol);
133 
134   Dmsg2(rdebuglevel, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot);
135 
136   /*
137    * If the MediaType requested for this volume is not the
138    * same as the current drive, we attempt to find the same
139    * device that was used to write the orginal volume.  If
140    * found, we switch to using that device.
141    *
142    * N.B. A lot of routines rely on the dcr pointer not changing
143    * ReadRecords.c even has multiple dcrs cached, so we take care
144    * here to release all important parts of the dcr and re-acquire
145    * them such as the block pointer (size may change), but we do
146    * not release the dcr.
147    */
148   Dmsg2(rdebuglevel, "MediaType dcr=%s dev=%s\n", dcr->media_type,
149         dev->device->media_type);
150   if (dcr->media_type[0] &&
151       !bstrcmp(dcr->media_type, dev->device->media_type)) {
152     ReserveContext rctx;
153     DirectorStorage* store;
154     int status;
155 
156     Jmsg3(jcr, M_INFO, 0,
157           _("Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
158             "  device=%s\n"),
159           dcr->media_type, dev->device->media_type, dev->print_name());
160     Dmsg3(rdebuglevel,
161           "Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
162           "  device=%s\n",
163           dcr->media_type, dev->device->media_type, dev->print_name());
164 
165     dev->dunblock(DEV_UNLOCKED);
166 
167     LockReservations();
168     memset(&rctx, 0, sizeof(ReserveContext));
169     rctx.jcr = jcr;
170     jcr->impl->read_dcr = dcr;
171     jcr->impl->reserve_msgs = new alist(10, not_owned_by_alist);
172     rctx.any_drive = true;
173     rctx.device_name = vol->device;
174     store = new DirectorStorage;
175     memset(store, 0, sizeof(DirectorStorage));
176     store->name[0] = 0; /* No dir name */
177     bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
178     bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
179     bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
180     store->append = false;
181     rctx.store = store;
182     CleanDevice(dcr); /* clean up the dcr */
183 
184     /*
185      * Search for a new device
186      */
187     status = SearchResForDevice(rctx);
188     ReleaseReserveMessages(jcr); /* release queued messages */
189     UnlockReservations();
190 
191     if (status == 1) { /* found new device to use */
192       /*
193        * Switching devices, so acquire lock on new device, then release the old
194        * one.
195        */
196       dcr->dev->Lock_read_acquire(); /* lock new one */
197       dev->Unlock_read_acquire();    /* release old one */
198       dev = dcr->dev;                /* get new device pointer */
199       dev->dblock(BST_DOING_ACQUIRE);
200 
201       dcr->VolumeName[0] = 0;
202       Jmsg(jcr, M_INFO, 0,
203            _("Media Type change.  New read device %s chosen.\n"),
204            dev->print_name());
205       Dmsg1(50, "Media Type change.  New read device %s chosen.\n",
206             dev->print_name());
207 
208       bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
209       dcr->setVolCatName(vol->VolumeName);
210       bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
211       dcr->VolCatInfo.Slot = vol->Slot;
212       dcr->VolCatInfo.InChanger = vol->Slot > 0;
213       bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
214       bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
215     } else {
216       /* error */
217       Jmsg1(jcr, M_FATAL, 0,
218             _("No suitable device found to read Volume \"%s\"\n"),
219             vol->VolumeName);
220       Dmsg1(rdebuglevel, "No suitable device found to read Volume \"%s\"\n",
221             vol->VolumeName);
222       goto get_out;
223     }
224   }
225   Dmsg2(rdebuglevel, "MediaType dcr=%s dev=%s\n", dcr->media_type,
226         dev->device->media_type);
227 
228   dev->ClearUnload();
229 
230   if (dev->vol && dev->vol->IsSwapping()) {
231     dev->vol->SetSlotNumber(vol->Slot);
232     Dmsg3(rdebuglevel, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->GetSlot(),
233           dev->vol->vol_name, dev->print_name());
234   }
235 
236   InitDeviceWaitTimers(dcr);
237 
238   tape_previously_mounted =
239       dev->CanRead() || dev->CanAppend() || dev->IsLabeled();
240   // tape_initially_mounted = tape_previously_mounted;
241 
242   /*
243    * Volume info is always needed because of VolParts
244    */
245   Dmsg1(rdebuglevel, "DirGetVolumeInfo vol=%s\n", dcr->VolumeName);
246   if (!dcr->DirGetVolumeInfo(GET_VOL_INFO_FOR_READ)) {
247     Dmsg2(rdebuglevel, "dir_get_vol_info failed for vol=%s: %s\n",
248           dcr->VolumeName, jcr->errmsg);
249     Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
250   }
251   dev->SetLoad(); /* set to load volume */
252 
253   while (1) {
254     /*
255      * If not polling limit retries
256      */
257     if (!dev->poll && retry++ > 10) { break; }
258 
259     /*
260      * See if we are changing the volume in the device.
261      * If so we need to force a reread of the tape label.
262      */
263     if (dev->device->drive_crypto_enabled ||
264         (dev->HasCap(CAP_ALWAYSOPEN) &&
265          !bstrcmp(dev->VolHdr.VolumeName, dcr->VolumeName))) {
266       dev->ClearLabeled();
267     }
268 
269     if (JobCanceled(jcr)) {
270       char ed1[50];
271       Mmsg1(dev->errmsg, _("Job %s canceled.\n"), edit_int64(jcr->JobId, ed1));
272       Jmsg(jcr, M_INFO, 0, dev->errmsg);
273       goto get_out; /* error return */
274     }
275 
276     dcr->DoUnload();
277     dcr->DoSwapping(false /*!IsWriting*/);
278     dcr->DoLoad(false /*!IsWriting*/);
279     SetDcrFromVol(dcr, vol); /* refresh dcr with desired volume info */
280 
281     /*
282      * This code ensures that the device is ready for reading. If it is a file,
283      * it opens it. If it is a tape, it checks the volume name
284      */
285     Dmsg1(rdebuglevel, "stored: open vol=%s\n", dcr->VolumeName);
286     if (!dev->open(dcr, OPEN_READ_ONLY)) {
287       if (!dev->poll) {
288         Jmsg3(jcr, M_WARNING, 0,
289               _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
290               dev->print_name(), dcr->VolumeName, dev->bstrerror());
291       }
292       goto default_path;
293     }
294     Dmsg1(rdebuglevel, "opened dev %s OK\n", dev->print_name());
295 
296     /*
297      * See if we are changing the volume in the device.
298      * If so we need to force a reread of the tape label.
299      */
300     if (!dev->device->drive_crypto_enabled && dev->HasCap(CAP_ALWAYSOPEN) &&
301         bstrcmp(dev->VolHdr.VolumeName, dcr->VolumeName)) {
302       vol_label_status = VOL_OK;
303     } else {
304       /*
305        * Read Volume Label
306        */
307       Dmsg0(rdebuglevel, "calling read-vol-label\n");
308       vol_label_status = ReadDevVolumeLabel(dcr);
309     }
310 
311     switch (vol_label_status) {
312       case VOL_OK:
313         Dmsg0(rdebuglevel, "Got correct volume.\n");
314         retval = true;
315         dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
316         break;                             /* got it */
317       case VOL_IO_ERROR:
318         Dmsg0(rdebuglevel, "IO Error\n");
319         /*
320          * Send error message generated by ReadDevVolumeLabel() only when we
321          * really had a tape mounted. This supresses superfluous error messages
322          * when nothing is mounted.
323          */
324         if (tape_previously_mounted) {
325           Jmsg(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
326         }
327         goto default_path;
328       case VOL_NAME_ERROR:
329         Dmsg3(rdebuglevel, "Vol name=%s want=%s drv=%s.\n",
330               dev->VolHdr.VolumeName, dcr->VolumeName, dev->print_name());
331         if (dev->IsVolumeToUnload()) { goto default_path; }
332         dev->SetUnload(); /* force unload of unwanted tape */
333         if (!UnloadAutochanger(dcr, -1)) {
334           /*
335            * At least free the device so we can re-open with correct volume
336            */
337           dev->close(dcr);
338           FreeVolume(dev);
339         }
340         dev->SetLoad();
341         /* Fall through */
342       default:
343         Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
344       default_path:
345         Dmsg0(rdebuglevel, "default path\n");
346         tape_previously_mounted = true;
347 
348         /*
349          * If the device requires mount, close it, so the device can be ejected.
350          */
351         if (dev->RequiresMount()) {
352           dev->close(dcr);
353           FreeVolume(dev);
354         }
355 
356         /*
357          * Call autochanger only once unless ask_sysop called
358          */
359         if (try_autochanger) {
360           int status;
361           Dmsg2(rdebuglevel, "calling autoload Vol=%s Slot=%d\n",
362                 dcr->VolumeName, dcr->VolCatInfo.Slot);
363           status = AutoloadDevice(dcr, 0, NULL);
364           if (status > 0) {
365             try_autochanger = false;
366             continue; /* try reading volume mounted */
367           }
368         }
369 
370         /*
371          * Mount a specific volume and no other
372          */
373         Dmsg0(rdebuglevel, "calling dir_ask_sysop\n");
374         if (!dcr->DirAskSysopToMountVolume(ST_READREADY)) {
375           goto get_out; /* error return */
376         }
377 
378         /*
379          * Volume info is always needed because of VolParts
380          */
381         Dmsg1(150, "DirGetVolumeInfo vol=%s\n", dcr->VolumeName);
382         if (!dcr->DirGetVolumeInfo(GET_VOL_INFO_FOR_READ)) {
383           Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n",
384                 dcr->VolumeName, jcr->errmsg);
385           Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
386         }
387         dev->SetLoad(); /* set to load volume */
388 
389         try_autochanger = true; /* permit trying the autochanger again */
390 
391         continue; /* try reading again */
392     }             /* end switch */
393     break;
394   } /* end while loop */
395 
396   if (!retval) {
397     Jmsg1(jcr, M_FATAL, 0,
398           _("Too many errors trying to mount device %s for reading.\n"),
399           dev->print_name());
400     goto get_out;
401   }
402 
403   dev->ClearAppend();
404   dev->SetRead();
405   jcr->sendJobStatus(JS_Running);
406   Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
407        dcr->VolumeName, dev->print_name());
408 
409 get_out:
410   dev->Lock();
411   dcr->ClearReserved();
412 
413   /*
414    * Normally we are blocked, but in at least one error case above we are not
415    * blocked because we unsuccessfully tried changing devices.
416    */
417   if (dev->IsBlocked()) {
418     dev->dunblock(DEV_LOCKED);
419   } else {
420     dev->Unlock(); /* dunblock() unlock the device too */
421   }
422 
423   Dmsg2(rdebuglevel, "dcr=%p dev=%p\n", dcr, dcr->dev);
424   Dmsg2(rdebuglevel, "MediaType dcr=%s dev=%s\n", dcr->media_type,
425         dev->device->media_type);
426 
427   dev->Unlock_read_acquire();
428 
429   Leave(rdebuglevel);
430 
431   return retval;
432 }
433 
434 /**
435  * Acquire device for writing. We permit multiple writers.
436  *  If this is the first one, we read the label.
437  *
438  *  Returns: NULL if failed for any reason
439  *           dcr if successful.
440  *   Note, normally ReserveDeviceForAppend() is called
441  *   before this routine.
442  */
AcquireDeviceForAppend(DeviceControlRecord * dcr)443 DeviceControlRecord* AcquireDeviceForAppend(DeviceControlRecord* dcr)
444 {
445   Device* dev = dcr->dev;
446   JobControlRecord* jcr = dcr->jcr;
447   bool retval = false;
448   bool have_vol = false;
449 
450   Enter(200);
451   InitDeviceWaitTimers(dcr);
452 
453   dev->Lock_acquire(); /* only one job at a time */
454   dev->Lock();
455   Dmsg1(100, "acquire_append device is %s\n", dev->IsTape() ? "tape" : "disk");
456 
457   /*
458    * With the reservation system, this should not happen
459    */
460   if (dev->CanRead()) {
461     Jmsg1(jcr, M_FATAL, 0,
462           _("Want to append, but device %s is busy reading.\n"),
463           dev->print_name());
464     Dmsg1(200, "Want to append but device %s is busy reading.\n",
465           dev->print_name());
466     goto get_out;
467   }
468 
469   dev->ClearUnload();
470 
471   /*
472    * have_vol defines whether or not MountNextWriteVolume should
473    * ask the Director again about what Volume to use.
474    */
475   if (dev->CanAppend() && dcr->IsSuitableVolumeMounted() &&
476       !bstrcmp(dcr->VolCatInfo.VolCatStatus, "Recycle")) {
477     Dmsg0(190, "device already in append.\n");
478     /*
479      * At this point, the correct tape is already mounted, so
480      * we do not need to do MountNextWriteVolume(), unless
481      * we need to recycle the tape.
482      */
483     if (dev->num_writers == 0) {
484       dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
485     }
486     have_vol = dcr->IsTapePositionOk();
487   }
488 
489   if (!have_vol) {
490     dev->rLock(true);
491     BlockDevice(dev, BST_DOING_ACQUIRE);
492     dev->Unlock();
493     Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
494     if (!dcr->MountNextWriteVolume()) {
495       if (!JobCanceled(jcr)) {
496         /* Reduce "noise" -- don't print if job canceled */
497         Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
498              dev->print_name());
499         Dmsg1(200, "Could not ready device %s for append.\n",
500               dev->print_name());
501       }
502       dev->Lock();
503       UnblockDevice(dev);
504       goto get_out;
505     }
506     Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
507     dev->Lock();
508     UnblockDevice(dev);
509   }
510 
511   dev->num_writers++; /* we are now a writer */
512   if (jcr->impl->NumWriteVolumes == 0) { jcr->impl->NumWriteVolumes = 1; }
513   dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */
514   Dmsg4(100, "=== nwriters=%d nres=%d vcatjob=%d dev=%s\n", dev->num_writers,
515         dev->NumReserved(), dev->VolCatInfo.VolCatJobs, dev->print_name());
516   dcr->DirUpdateVolumeInfo(false, false); /* send Volume info to Director */
517   retval = true;
518 
519 get_out:
520   /*
521    * Don't plugin close here, we might have multiple writers
522    */
523   dcr->ClearReserved();
524   dev->Unlock();
525   dev->Unlock_acquire();
526   Leave(200);
527 
528   return retval ? dcr : NULL;
529 }
530 
531 /**
532  * This job is done, so release the device. From a Unix standpoint, the device
533  * remains open.
534  *
535  * Note, if we were spooling, we may enter with the device blocked.
536  * We unblock at the end, only if it was us who blocked the device.
537  */
ReleaseDevice(DeviceControlRecord * dcr)538 bool ReleaseDevice(DeviceControlRecord* dcr)
539 {
540   utime_t now;
541   JobControlRecord* jcr = dcr->jcr;
542   Device* dev = dcr->dev;
543   bool retval = true;
544   char tbuf[100];
545   int was_blocked = BST_NOT_BLOCKED;
546 
547   Jmsg(jcr, M_INFO, 0, "Releasing device %s.\n", dev->print_name());
548 
549   /*
550    * Capture job statistics now that we are done using this device.
551    */
552   now = (utime_t)time(NULL);
553   UpdateJobStatistics(jcr, now);
554 
555   /*
556    * Some devices do cache write operations (e.g. droplet_device).
557    * Therefore flushing the cache is required to determine
558    * if a job have been written successfully.
559    * As a flush operation can take quite a long time,
560    * this must be done before acquiring locks.
561    * A previous implementation did the flush inside dev->close(),
562    * which resulted in various locking problems.
563    */
564   if (!JobCanceled(jcr)) {
565     if (!dev->flush(dcr)) {
566       Jmsg(jcr, M_FATAL, 0, "Failed to flush device %s.\n", dev->print_name());
567     }
568   }
569 
570   dev->Lock();
571   if (!dev->IsBlocked()) {
572     BlockDevice(dev, BST_RELEASING);
573   } else {
574     was_blocked = dev->blocked();
575     dev->SetBlocked(BST_RELEASING);
576   }
577   LockVolumes();
578   Dmsg1(100, "releasing device %s\n", dev->print_name());
579 
580   /*
581    * If device is reserved, job never started, so release the reserve here
582    */
583   dcr->ClearReserved();
584 
585   if (dev->CanRead()) {
586     VolumeCatalogInfo* vol = &dev->VolCatInfo;
587 
588     dev->ClearRead(); /* clear read bit */
589     Dmsg2(150, "dir_update_vol_info. label=%d Vol=%s\n", dev->IsLabeled(),
590           vol->VolCatName);
591     if (dev->IsLabeled() && vol->VolCatName[0] != 0) {
592       dcr->DirUpdateVolumeInfo(false, false); /* send Volume info to Director */
593       RemoveReadVolume(jcr, dcr->VolumeName);
594       VolumeUnused(dcr);
595     }
596   } else if (dev->num_writers > 0) {
597     /*
598      * Note if WEOT is set, we are at the end of the tape and may not be
599      * positioned correctly, so the job_media_record and update_vol_info have
600      * already been done, which means we skip them here.
601      */
602     dev->num_writers--;
603     Dmsg1(100, "There are %d writers in ReleaseDevice\n", dev->num_writers);
604     if (dev->IsLabeled()) {
605       Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
606             dev->getVolCatName(), dev->print_name());
607       if (!dev->AtWeot() && !dcr->DirCreateJobmediaRecord(false)) {
608         Jmsg2(jcr, M_FATAL, 0,
609               _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
610               dcr->getVolCatName(), jcr->Job);
611       }
612 
613       /*
614        * If no more writers, and no errors, and wrote something, write an EOF
615        */
616       if (!dev->num_writers && dev->CanWrite() && dev->block_num > 0) {
617         dev->weof(1);
618         WriteAnsiIbmLabels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
619       }
620       if (!dev->AtWeot()) {
621         dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
622 
623         /*
624          * Note! do volume update before close, which zaps VolCatInfo
625          */
626         dcr->DirUpdateVolumeInfo(false,
627                                  false); /* send Volume info to Director */
628         Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
629               dev->getVolCatName(), dev->print_name());
630       }
631       if (dev->num_writers == 0) { /* if not being used */
632         VolumeUnused(dcr);         /*  we obviously are not using the volume */
633       }
634     }
635 
636   } else {
637     /*
638      * If we reach here, it is most likely because the job has failed,
639      * since the device is not in read mode and there are no writers.
640      * It was probably reserved.
641      */
642     VolumeUnused(dcr);
643   }
644 
645   Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers,
646         dev->NumReserved(), dev->print_name());
647 
648   /*
649    * If no writers, close if file or !CAP_ALWAYS_OPEN
650    */
651   if (dev->num_writers == 0 &&
652       (!dev->IsTape() || !dev->HasCap(CAP_ALWAYSOPEN))) {
653     dev->close(dcr);
654     FreeVolume(dev);
655   }
656 
657   UnlockVolumes();
658 
659   /*
660    * Fire off Alert command and include any output
661    */
662   if (!JobCanceled(jcr)) {
663     if (!dcr->device->drive_tapealert_enabled && dcr->device->alert_command) {
664       int status = 1;
665       POOLMEM *alert, *line;
666       Bpipe* bpipe;
667 
668       alert = GetPoolMemory(PM_FNAME);
669       line = GetPoolMemory(PM_FNAME);
670 
671       alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
672 
673       /*
674        * Wait maximum 5 minutes
675        */
676       bpipe = OpenBpipe(alert, 60 * 5, "r");
677       if (bpipe) {
678         while (bfgets(line, bpipe->rfd)) {
679           Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
680         }
681         status = CloseBpipe(bpipe);
682       } else {
683         status = errno;
684       }
685       if (status != 0) {
686         BErrNo be;
687         Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"), alert,
688              be.bstrerror(status));
689       }
690 
691       Dmsg1(400, "alert status=%d\n", status);
692       FreePoolMemory(alert);
693       FreePoolMemory(line);
694     } else {
695       /*
696        * If all reservations are cleared for this device raise an event that SD
697        * plugins can register to.
698        */
699       if (dev->NumReserved() == 0) {
700         GeneratePluginEvent(jcr, bsdEventDeviceRelease, dcr);
701       }
702     }
703   }
704 
705   pthread_cond_broadcast(&dev->wait_next_vol);
706   Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
707         (uint32_t)jcr->JobId,
708         bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
709   ReleaseDeviceCond();
710 
711   /*
712    * If we are the thread that blocked the device, then unblock it
713    */
714   if (pthread_equal(dev->no_wait_id, pthread_self())) {
715     dev->dunblock(true);
716   } else {
717     /*
718      * Otherwise, reset the prior block status and unlock
719      */
720     dev->SetBlocked(was_blocked);
721     dev->Unlock();
722   }
723 
724   if (dcr->keep_dcr) {
725     DetachDcrFromDev(dcr);
726   } else {
727     FreeDeviceControlRecord(dcr);
728   }
729 
730   Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
731         (uint32_t)jcr->JobId);
732 
733   return retval;
734 }
735 
736 /**
737  * Clean up the device for reuse without freeing the memory
738  */
CleanDevice(DeviceControlRecord * dcr)739 bool CleanDevice(DeviceControlRecord* dcr)
740 {
741   bool retval;
742 
743   dcr->keep_dcr = true; /* do not free the dcr */
744   retval = ReleaseDevice(dcr);
745   dcr->keep_dcr = false;
746 
747   return retval;
748 }
749 
750 /**
751  * Setup DeviceControlRecord with a new device.
752  */
SetupNewDcrDevice(JobControlRecord * jcr,DeviceControlRecord * dcr,Device * dev,BlockSizes * blocksizes)753 void SetupNewDcrDevice(JobControlRecord* jcr,
754                        DeviceControlRecord* dcr,
755                        Device* dev,
756                        BlockSizes* blocksizes)
757 {
758   dcr->jcr = jcr; /* point back to jcr */
759 
760   /*
761    * Set device information, possibly change device
762    */
763   if (dev) {
764     /*
765      * Set wanted blocksizes
766      */
767     if (blocksizes) {
768       dev->min_block_size = blocksizes->min_block_size;
769       dev->max_block_size = blocksizes->max_block_size;
770     }
771 
772     if (dcr->block) { FreeBlock(dcr->block); }
773     dcr->block = new_block(dev);
774 
775     if (dcr->rec) {
776       FreeRecord(dcr->rec);
777       dcr->rec = NULL;
778     }
779     dcr->rec = new_record();
780 
781     if (dcr->attached_to_dev) { DetachDcrFromDev(dcr); }
782 
783     /*
784      * Use job spoolsize prior to device spoolsize
785      */
786     if (jcr && jcr->impl->spool_size) {
787       dcr->max_job_spool_size = jcr->impl->spool_size;
788     } else {
789       dcr->max_job_spool_size = dev->device->max_job_spool_size;
790     }
791 
792     dcr->device = dev->device;
793     dcr->SetDev(dev);
794     AttachDcrToDev(dcr);
795 
796     /*
797      * Initialize the auto deflation/inflation which can
798      * be disabled per DeviceControlRecord when we want to. e.g. when we want to
799      * send the data as part of a replication stream in which we
800      * don't want to first inflate the data to then again
801      * do deflation for sending it to the other storage daemon.
802      */
803     dcr->autodeflate = dcr->device->autodeflate;
804     dcr->autoinflate = dcr->device->autoinflate;
805   }
806 }
807 
AttachDcrToDev(DeviceControlRecord * dcr)808 static void AttachDcrToDev(DeviceControlRecord* dcr)
809 {
810   Device* dev;
811   JobControlRecord* jcr;
812 
813   P(dcr->mutex_);
814   dev = dcr->dev;
815   jcr = dcr->jcr;
816   if (jcr) Dmsg1(500, "JobId=%u enter AttachDcrToDev\n", (uint32_t)jcr->JobId);
817   /* ***FIXME*** return error if dev not initiated */
818   if (!dcr->attached_to_dev && dev->initiated && jcr &&
819       jcr->getJobType() != JT_SYSTEM) {
820     dev->Lock();
821     Dmsg4(200, "Attach Jid=%d dcr=%p size=%d dev=%s\n", (uint32_t)jcr->JobId,
822           dcr, dev->attached_dcrs->size(), dev->print_name());
823     dev->attached_dcrs->append(dcr); /* attach dcr to device */
824     dev->Unlock();
825     dcr->attached_to_dev = true;
826   }
827   V(dcr->mutex_);
828 }
829 
830 /**
831  * DeviceControlRecord is locked before calling this routine
832  */
LockedDetachDcrFromDev(DeviceControlRecord * dcr)833 static void LockedDetachDcrFromDev(DeviceControlRecord* dcr)
834 {
835   Device* dev = dcr->dev;
836   Dmsg0(500, "Enter DetachDcrFromDev\n"); /* jcr is NULL in some cases */
837 
838   /* Detach this dcr only if attached */
839   if (dcr->attached_to_dev && dev) {
840     dcr->UnreserveDevice();
841     dev->Lock();
842     Dmsg4(200, "Detach Jid=%d dcr=%p size=%d to dev=%s\n",
843           (uint32_t)dcr->jcr->JobId, dcr, dev->attached_dcrs->size(),
844           dev->print_name());
845     dcr->attached_to_dev = false;
846     if (dev->attached_dcrs->size()) {
847       dev->attached_dcrs->remove(dcr); /* detach dcr from device */
848     }
849     //    RemoveDcrFromDcrs(dcr);      /* remove dcr from jcr list */
850     dev->Unlock();
851   }
852   dcr->attached_to_dev = false;
853 }
854 
855 
DetachDcrFromDev(DeviceControlRecord * dcr)856 static void DetachDcrFromDev(DeviceControlRecord* dcr)
857 {
858   P(dcr->mutex_);
859   LockedDetachDcrFromDev(dcr);
860   V(dcr->mutex_);
861 }
862 
863 /**
864  * Free up all aspects of the given dcr -- i.e. dechain it,
865  *  release allocated memory, zap pointers, ...
866  */
FreeDeviceControlRecord(DeviceControlRecord * dcr)867 void FreeDeviceControlRecord(DeviceControlRecord* dcr)
868 {
869   JobControlRecord* jcr;
870 
871   P(dcr->mutex_);
872   jcr = dcr->jcr;
873 
874   LockedDetachDcrFromDev(dcr);
875 
876   if (dcr->block) { FreeBlock(dcr->block); }
877 
878   if (dcr->rec) { FreeRecord(dcr->rec); }
879 
880   if (jcr && jcr->impl->dcr == dcr) { jcr->impl->dcr = NULL; }
881 
882   if (jcr && jcr->impl->read_dcr == dcr) { jcr->impl->read_dcr = NULL; }
883 
884   V(dcr->mutex_);
885 
886   pthread_mutex_destroy(&dcr->mutex_);
887   pthread_mutex_destroy(&dcr->r_mutex);
888 
889   delete dcr;
890 }
891 
SetDcrFromVol(DeviceControlRecord * dcr,VolumeList * vol)892 static void SetDcrFromVol(DeviceControlRecord* dcr, VolumeList* vol)
893 {
894   /*
895    * Note, if we want to be able to work from a .bsr file only
896    *  for disaster recovery, we must "simulate" reading the catalog
897    */
898   bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
899   dcr->setVolCatName(vol->VolumeName);
900   bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
901   dcr->VolCatInfo.Slot = vol->Slot;
902   dcr->VolCatInfo.InChanger = vol->Slot > 0;
903 }
904 
905 } /* namespace storagedaemon */
906