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