2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
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.
14 Bacula® is a registered trademark of Kern Sibbald.
17 * Subroutines to handle Catalog reqests sent to the Director
18 * Reqests/commands from the Director are handled in dircmd.c
20 * Kern Sibbald, December 2000
24 #include "bacula.h" /* pull in global headers */
25 #include "stored.h" /* pull in Storage Deamon headers */
27 static const int dbglvl = 200;
29 /* Requests sent to the Director */
30 static char Find_media[] = "CatReq Job=%s FindMedia=%d pool_name=%s media_type=%s\n";
31 static char Get_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s write=%d\n";
32 static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s"
33 " VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u"
34 " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%s VolStatus=%s"
35 " Slot=%d relabel=%d InChanger=%d VolReadTime=%s VolWriteTime=%s"
36 " VolFirstWritten=%s VolParts=%u\n";
37 static char Create_job_media[] = "CatReq Job=%s CreateJobMedia"
38 " FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u"
39 " StartBlock=%u EndBlock=%u Copy=%d Strip=%d MediaId=%s\n";
40 static char FileAttributes[] = "UpdCat Job=%s FileAttributes ";
42 /* Responses received from the Director */
43 static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%lu"
44 " VolBlocks=%lu VolBytes=%lld VolMounts=%lu"
45 " VolErrors=%lu VolWrites=%lu"
46 " MaxVolBytes=%lld VolCapacityBytes=%lld VolStatus=%20s"
47 " Slot=%ld MaxVolJobs=%lu MaxVolFiles=%lu InChanger=%ld"
48 " VolReadTime=%lld VolWriteTime=%lld EndFile=%lu EndBlock=%lu"
49 " VolParts=%lu LabelType=%ld MediaId=%lld ScratchPoolId=%lld\n";
52 static char OK_create[] = "1000 OK CreateJobMedia\n";
54 static bthread_mutex_t vol_info_mutex = BTHREAD_MUTEX_PRIORITY(PRIO_SD_VOL_INFO);
58 static char Device_update[] = "DevUpd Job=%s device=%s "
59 "append=%d read=%d num_writers=%d "
60 "open=%d labeled=%d offline=%d "
61 "reserved=%d max_writers=%d "
62 "autoselect=%d autochanger=%d "
63 "changer_name=%s media_type=%s volume_name=%s\n";
66 /** Send update information about a device to Director */
67 bool dir_update_device(JCR *jcr, DEVICE *dev)
69 BSOCK *dir = jcr->dir_bsock;
70 POOL_MEM dev_name, VolumeName, MediaType, ChangerName;
71 DEVRES *device = dev->device;
74 pm_strcpy(dev_name, device->hdr.name);
75 bash_spaces(dev_name);
76 if (dev->is_labeled()) {
77 pm_strcpy(VolumeName, dev->VolHdr.VolumeName);
79 pm_strcpy(VolumeName, "*");
81 bash_spaces(VolumeName);
82 pm_strcpy(MediaType, device->media_type);
83 bash_spaces(MediaType);
84 if (device->changer_res) {
85 pm_strcpy(ChangerName, device->changer_res->hdr.name);
86 bash_spaces(ChangerName);
88 pm_strcpy(ChangerName, "*");
90 ok = dir->fsend(Device_update,
94 dev->can_read()!=0, dev->num_writers,
95 dev->is_open()!=0, dev->is_labeled()!=0,
96 dev->is_offline()!=0, dev->reserved_device,
97 dev->is_tape()?100000:1,
99 ChangerName.c_str(), MediaType.c_str(), VolumeName.c_str());
100 Dmsg1(dbglvl, ">dird: %s\n", dir->msg);
104 bool dir_update_changer(JCR *jcr, AUTOCHANGER *changer)
106 BSOCK *dir = jcr->dir_bsock;
107 POOL_MEM dev_name, MediaType;
111 pm_strcpy(dev_name, changer->hdr.name);
112 bash_spaces(dev_name);
113 device = (DEVRES *)changer->device->first();
114 pm_strcpy(MediaType, device->media_type);
115 bash_spaces(MediaType);
116 /* This is mostly to indicate that we are here */
117 ok = dir->fsend(Device_update,
119 dev_name.c_str(), /* Changer name */
120 0, 0, 0, /* append, read, num_writers */
121 0, 0, 0, /* is_open, is_labeled, offline */
122 0, 0, /* reserved, max_writers */
124 changer->device->size(), /* Number of devices */
126 "*", /* ChangerName */
127 MediaType.c_str(), /* MediaType */
129 Dmsg1(dbglvl, ">dird: %s\n", dir->msg);
136 * Send current JobStatus to Director
138 bool dir_send_job_status(JCR *jcr)
140 return jcr->sendJobStatus();
144 * Common routine for:
145 * dir_get_volume_info()
147 * dir_find_next_appendable_volume()
149 * NOTE!!! All calls to this routine must be protected by
150 * locking vol_info_mutex before calling it so that
151 * we don't have one thread modifying the parameters
152 * and another reading them.
154 * Returns: true on success and vol info in dcr->VolCatInfo
157 static bool do_get_volume_info(DCR *dcr)
160 BSOCK *dir = jcr->dir_bsock;
165 dcr->setVolCatInfo(false);
166 if (dir->recv() <= 0) {
167 Dmsg0(dbglvl, "getvolname error bnet_recv\n");
168 Mmsg(jcr->errmsg, _("Network error on bnet_recv in req_vol_info.\n"));
171 memset(&vol, 0, sizeof(vol));
172 Dmsg1(dbglvl, "<dird %s", dir->msg);
173 n = sscanf(dir->msg, OK_media, vol.VolCatName,
174 &vol.VolCatJobs, &vol.VolCatFiles,
175 &vol.VolCatBlocks, &vol.VolCatAmetaBytes,
176 &vol.VolCatMounts, &vol.VolCatErrors,
177 &vol.VolCatWrites, &vol.VolCatMaxBytes,
178 &vol.VolCatCapacityBytes, vol.VolCatStatus,
179 &vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles,
180 &InChanger, &vol.VolReadTime, &vol.VolWriteTime,
181 &vol.EndFile, &vol.EndBlock, &vol.VolCatParts,
182 &vol.LabelType, &vol.VolMediaId, &vol.VolScratchPoolId);
184 Dmsg1(dbglvl, "get_volume_info failed: ERR=%s", dir->msg);
186 * Note, we can get an error here either because there is
187 * a comm problem, or if the volume is not a suitable
188 * volume to use, so do not issue a Jmsg() here, do it
189 * in the calling routine.
191 Mmsg(jcr->errmsg, _("Error getting Volume info: %s"), dir->msg);
194 vol.InChanger = InChanger; /* bool in structure */
196 vol.VolCatBytes = vol.VolCatAmetaBytes;
197 unbash_spaces(vol.VolCatName);
198 bstrncpy(dcr->VolumeName, vol.VolCatName, sizeof(dcr->VolumeName));
199 dcr->VolCatInfo = vol; /* structure assignment */
201 Dmsg2(dbglvl, "do_reqest_vol_info return true slot=%d Volume=%s\n",
202 vol.Slot, vol.VolCatName);
203 Dmsg3(dbglvl, "Dir returned VolCatAmetaBytes=%lld Status=%s Vol=%s\n",
204 vol.VolCatAmetaBytes, vol.VolCatStatus, vol.VolCatName);
210 * Get Volume info for a specific volume from the Director's Database
212 * Returns: true on success (Director guarantees that Pool and MediaType
213 * are correct and VolStatus==Append or
214 * VolStatus==Recycle)
217 * Volume information returned in dcr->VolCatInfo
219 bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing)
222 BSOCK *dir = jcr->dir_bsock;
225 dcr->setVolCatName(dcr->VolumeName);
226 bash_spaces(dcr->getVolCatName());
227 dir->fsend(Get_Vol_Info, jcr->Job, dcr->getVolCatName(),
228 writing==GET_VOL_INFO_FOR_WRITE?1:0);
229 Dmsg1(dbglvl, ">dird %s", dir->msg);
230 unbash_spaces(dcr->getVolCatName());
231 bool ok = do_get_volume_info(dcr);
239 * Get info on the next appendable volume in the Director's database
241 * Returns: true on success dcr->VolumeName is volume
242 * reserve_volume() called on Volume name
243 * false on failure dcr->VolumeName[0] == 0
244 * also sets dcr->found_in_use if at least one
245 * in use volume was found.
247 * Volume information returned in dcr
250 bool dir_find_next_appendable_volume(DCR *dcr)
253 BSOCK *dir = jcr->dir_bsock;
255 char lastVolume[MAX_NAME_LENGTH];
257 Dmsg2(dbglvl, "dir_find_next_appendable_volume: reserved=%d Vol=%s\n",
258 dcr->is_reserved(), dcr->VolumeName);
259 Mmsg(jcr->errmsg, "Unknown error\n");
262 * Try the thirty oldest or most available volumes. Note,
263 * the most available could already be mounted on another
264 * drive, so we continue looking for a not in use Volume.
268 dcr->clear_found_in_use();
270 for (int vol_index=1; vol_index < 30; vol_index++) {
271 bash_spaces(dcr->media_type);
272 bash_spaces(dcr->pool_name);
273 dir->fsend(Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type);
274 unbash_spaces(dcr->media_type);
275 unbash_spaces(dcr->pool_name);
276 Dmsg1(dbglvl, ">dird %s", dir->msg);
277 if (do_get_volume_info(dcr)) {
278 /* Give up if we get the same volume name twice */
279 if (lastVolume[0] && strcmp(lastVolume, dcr->VolumeName) == 0) {
280 Mmsg(jcr->errmsg, "Director returned same volume name=%s twice.\n",
282 Dmsg1(dbglvl, "Got same vol = %s\n", lastVolume);
285 bstrncpy(lastVolume, dcr->VolumeName, sizeof(lastVolume));
286 if (dcr->can_i_write_volume()) {
287 Dmsg1(dbglvl, "Call reserve_volume for write. Vol=%s\n", dcr->VolumeName);
288 if (reserve_volume(dcr, dcr->VolumeName) == NULL) {
289 Dmsg1(dbglvl, "%s", jcr->errmsg);
290 if (dcr->dev->must_wait()) {
292 dcr->VolumeName[0] = 0;
297 Dmsg1(dbglvl, "dir_find_next_appendable_volume return true. vol=%s\n",
302 Mmsg(jcr->errmsg, "Volume %s is in use.\n", dcr->VolumeName);
303 Dmsg1(dbglvl, "Volume %s is in use.\n", dcr->VolumeName);
304 /* If volume is not usable, it is in use by someone else */
305 dcr->set_found_in_use();
309 Dmsg2(dbglvl, "No vol. index %d return false. dev=%s\n", vol_index,
310 dcr->dev->print_name());
314 dcr->VolumeName[0] = 0;
319 if (!rtn && dcr->VolCatInfo.VolScratchPoolId != 0) {
320 Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
321 Dmsg2(000, "!!!!!!!!! Volume=%s rejected ScratchPoolId=%lld\n", dcr->VolumeName,
322 dcr->VolCatInfo.VolScratchPoolId);
323 Dmsg1(000, "%s", jcr->errmsg);
325 // Dmsg3(000, "Rtn=%d Volume=%s ScratchPoolId=%lld\n", rtn, dcr->VolumeName,
326 // dcr->VolCatInfo.VolScratchPoolId);
333 * After writing a Volume, send the updated statistics
334 * back to the director. The information comes from the
337 bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten)
340 BSOCK *dir = jcr->dir_bsock;
341 DEVICE *dev = dcr->dev;
342 VOLUME_CAT_INFO *vol;
343 char ed1[50], ed4[50], ed5[50], ed6[50], ed7[50], ed8[50];
348 /* If system job, do not update catalog */
349 if (jcr->getJobType() == JT_SYSTEM) {
353 vol = &dev->VolCatInfo;
354 if (vol->VolCatName[0] == 0) {
355 Jmsg0(jcr, M_FATAL, 0, _("NULL Volume name. This shouldn't happen!!!\n"));
356 Pmsg0(000, _("NULL Volume name. This shouldn't happen!!!\n"));
360 /* Lock during Volume update */
362 dev->Lock_VolCatInfo();
363 /* Just labeled or relabeled the tape */
365 dev->setVolCatStatus("Append");
367 // if (update_LastWritten) {
368 vol->VolLastWritten = time(NULL);
370 pm_strcpy(VolumeName, vol->VolCatName);
371 bash_spaces(VolumeName);
372 InChanger = vol->InChanger;
373 dir->fsend(Update_media, jcr->Job,
374 VolumeName.c_str(), vol->VolCatJobs, vol->VolCatFiles,
375 vol->VolCatBlocks, edit_uint64(vol->VolCatAmetaBytes, ed1),
376 vol->VolCatMounts, vol->VolCatErrors,
377 vol->VolCatWrites, edit_uint64(vol->VolCatMaxBytes, ed4),
378 edit_uint64(vol->VolLastWritten, ed5),
379 vol->VolCatStatus, vol->Slot, label,
380 InChanger, /* bool in structure */
381 edit_int64(vol->VolReadTime, ed6),
382 edit_int64(vol->VolWriteTime, ed7),
383 edit_uint64(vol->VolFirstWritten, ed8),
385 Dmsg1(100, ">dird %s", dir->msg);
387 /* Do not lock device here because it may be locked from label */
388 if (!jcr->is_canceled()) {
390 * We sent info directly from dev to the Director.
391 * What the Director sends back is first read into
392 * the dcr with do_get_volume_info()
394 if (!do_get_volume_info(dcr)) {
395 Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
396 Dmsg2(dbglvl, _("Didn't get vol info vol=%s: ERR=%s"),
397 vol->VolCatName, jcr->errmsg);
400 Dmsg1(100, "get_volume_info() %s", dir->msg);
401 /* Update dev Volume info in case something changed (e.g. expired) */
402 dcr->VolCatInfo.VolCatAmetaBytes = dev->VolCatInfo.VolCatAmetaBytes;
403 dcr->VolCatInfo.VolCatFiles = dev->VolCatInfo.VolCatFiles;
404 bstrncpy(vol->VolCatStatus, dcr->VolCatInfo.VolCatStatus, sizeof(vol->VolCatStatus));
405 /* ***FIXME*** copy other fields that can change, if any */
410 dev->Unlock_VolCatInfo();
416 * After writing a Volume, create the JobMedia record.
418 bool dir_create_jobmedia_record(DCR *dcr, bool zero)
421 BSOCK *dir = jcr->dir_bsock;
424 if (!dcr->WroteVol) {
425 return true; /* nothing written to the Volume */
428 /* If system job, do not update catalog */
429 if (jcr->getJobType() == JT_SYSTEM) {
433 /* Throw out records where FI is zero -- i.e. nothing done */
434 if (!zero && dcr->VolFirstIndex == 0 &&
435 (dcr->StartBlock != 0 || dcr->EndBlock != 0)) {
436 Dmsg7(dbglvl, "Discard: JobMedia Vol=%s wrote=%d MediaId=%d FI=%d LI=%d StartBlock=%d EndBlock=%d Suppressed\n",
437 dcr->VolumeName, dcr->WroteVol, dcr->VolMediaId,
438 dcr->VolFirstIndex, dcr->VolLastIndex, dcr->StartBlock, dcr->EndBlock);
442 Dmsg7(100, "JobMedia Vol=%s wrote=%d MediaId=%d FI=%d LI=%d StartBlock=%d EndBlock=%d Wrote\n",
443 dcr->VolumeName, dcr->WroteVol, dcr->VolMediaId,
444 dcr->VolFirstIndex, dcr->VolLastIndex, dcr->StartBlock, dcr->EndBlock);
445 dcr->WroteVol = false;
447 /* Send dummy place holder to avoid purging */
448 dir->fsend(Create_job_media, jcr->Job,
449 0 , 0, 0, 0, 0, 0, 0, 0, edit_uint64(dcr->VolMediaId, ed1));
451 dir->fsend(Create_job_media, jcr->Job,
452 dcr->VolFirstIndex, dcr->VolLastIndex,
453 dcr->StartFile, dcr->EndFile,
454 dcr->StartBlock, dcr->EndBlock,
455 dcr->Copy, dcr->Stripe,
456 edit_uint64(dcr->VolMediaId, ed1));
458 Dmsg1(dbglvl, ">dird %s", dir->msg);
459 if (dir->recv() <= 0) {
460 Dmsg0(dbglvl, "create_jobmedia error bnet_recv\n");
461 Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"),
465 Dmsg1(210, "<dird %s", dir->msg);
466 if (strcmp(dir->msg, OK_create) != 0) {
467 Dmsg1(dbglvl, "Bad response from Dir: %s\n", dir->msg);
468 Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: %s\n"), dir->msg);
476 * Update File Attribute data
477 * We do the following:
478 * 1. expand the bsock buffer to be large enough
479 * 2. Write a "header" into the buffer with serialized data
484 * data length that follows
485 * start of raw byte data from the Device record.
486 * Note, this is primarily for Attribute data, but can
487 * also handle any device record. The Director must know
488 * the raw byte data format that is defined for each Stream.
489 * Now Restore Objects pass through here STREAM_RESTORE_OBJECT
491 bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec)
494 BSOCK *dir = jcr->dir_bsock;
497 #ifdef NO_ATTRIBUTES_TEST
501 dir->msg = check_pool_memory_size(dir->msg, sizeof(FileAttributes) +
502 MAX_NAME_LENGTH + sizeof(DEV_RECORD) + rec->data_len + 1);
503 dir->msglen = bsnprintf(dir->msg, sizeof(FileAttributes) +
504 MAX_NAME_LENGTH + 1, FileAttributes, jcr->Job);
505 ser_begin(dir->msg + dir->msglen, 0);
506 ser_uint32(rec->VolSessionId);
507 ser_uint32(rec->VolSessionTime);
508 ser_int32(rec->FileIndex);
509 ser_int32(rec->Stream);
510 ser_uint32(rec->data_len);
511 ser_bytes(rec->data, rec->data_len);
512 dir->msglen = ser_length(dir->msg);
513 Dmsg1(1800, ">dird %s\n", dir->msg); /* Attributes */
514 if (rec->maskedStream == STREAM_UNIX_ATTRIBUTES ||
515 rec->maskedStream == STREAM_UNIX_ATTRIBUTES_EX) {
516 Dmsg2(1500, "==== set_data_end FI=%ld %s\n", rec->FileIndex, rec->data);
517 dir->set_data_end(rec->FileIndex); /* set offset of valid data */
524 * Request the sysop to create an appendable volume
526 * Entered with device blocked.
527 * Leaves with device blocked.
529 * Returns: true on success (operator issues a mount command)
531 * Note, must create dev->errmsg on error return.
533 * On success, dcr->VolumeName and dcr->VolCatInfo contain
534 * information on suggested volume, but this may not be the
535 * same as what is actually mounted.
537 * When we return with success, the correct tape may or may not
538 * actually be mounted. The calling routine must read it and
541 bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr)
543 int stat = W_TIMEOUT;
544 DEVICE *dev = dcr->dev;
546 bool got_vol = false;
548 if (job_canceled(jcr)) {
551 Dmsg0(400, "enter dir_ask_sysop_to_create_appendable_volume\n");
552 ASSERT(dev->blocked());
554 if (job_canceled(jcr)) {
556 _("Job %s canceled while waiting for mount on Storage Device \"%s\".\n"),
557 jcr->Job, dev->print_name());
558 Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
561 got_vol = dir_find_next_appendable_volume(dcr); /* get suggested volume */
566 if (stat == W_TIMEOUT || stat == W_MOUNT) {
568 "Job %s is waiting. Cannot find any appendable volumes.\n"
569 "Please use the \"label\" command to create a new Volume for:\n"
572 " Media type: %s\n"),
577 Jmsg(jcr, M_MOUNT, 0, "%s", dev->errmsg);
578 Dmsg1(dbglvl, "%s", dev->errmsg);
582 jcr->sendJobStatus(JS_WaitMedia);
584 stat = wait_for_sysop(dcr);
585 Dmsg1(dbglvl, "Back from wait_for_sysop stat=%d\n", stat);
587 Dmsg1(dbglvl, "Poll timeout in create append vol on device %s\n", dev->print_name());
591 if (stat == W_TIMEOUT) {
592 if (!double_dev_wait_time(dev)) {
593 Mmsg(dev->errmsg, _("Max time exceeded waiting to mount Storage Device %s for Job %s\n"),
594 dev->print_name(), jcr->Job);
595 Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
596 Dmsg1(dbglvl, "Gave up waiting on device %s\n", dev->print_name());
597 return false; /* exceeded maximum waits */
601 if (stat == W_ERROR) {
603 Mmsg0(dev->errmsg, _("pthread error in mount_next_volume.\n"));
604 Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
607 Dmsg1(dbglvl, "Someone woke me for device %s\n", dev->print_name());
611 jcr->sendJobStatus(JS_Running);
612 Dmsg0(dbglvl, "leave dir_ask_sysop_to_create_appendable_volume\n");
617 * Request to mount specific Volume
619 * Entered with device blocked and dcr->VolumeName is desired
621 * Leaves with device blocked.
623 * Returns: true on success (operator issues a mount command)
625 * Note, must create dev->errmsg on error return.
628 bool dir_ask_sysop_to_mount_volume(DCR *dcr, bool write_access)
630 int stat = W_TIMEOUT;
631 DEVICE *dev = dcr->dev;
634 Dmsg0(400, "enter dir_ask_sysop_to_mount_volume\n");
635 if (!dcr->VolumeName[0]) {
636 Mmsg0(dev->errmsg, _("Cannot request another volume: no volume name given.\n"));
641 if (job_canceled(jcr)) {
642 Mmsg(dev->errmsg, _("Job %s canceled while waiting for mount on Storage Device %s.\n"),
643 jcr->Job, dev->print_name());
652 * If we are not polling, and the wait timeout or the
653 * user explicitly did a mount, send him the message.
656 if (!dev->poll && (stat == W_TIMEOUT || stat == W_MOUNT)) {
659 msg = _("%sPlease mount append Volume \"%s\" or label a new one for:\n"
663 " Media type: %s\n");
665 msg = _("%sPlease mount read Volume \"%s\" for:\n"
669 " Media type: %s\n");
671 Jmsg(jcr, M_MOUNT, 0, msg,
672 dev->is_nospace()?_("\n\nWARNING: device is full! Please add more disk space then ...\n\n"):"",
678 Dmsg3(400, "Mount \"%s\" on device \"%s\" for Job %s\n",
679 dcr->VolumeName, dev->print_name(), jcr->Job);
682 jcr->sendJobStatus(JS_WaitMount);
684 stat = wait_for_sysop(dcr); /* wait on device */
685 Dmsg1(100, "Back from wait_for_sysop stat=%d\n", stat);
687 Dmsg1(100, "Poll timeout in mount vol on device %s\n", dev->print_name());
688 Dmsg1(100, "Blocked=%s\n", dev->print_blocked());
692 if (stat == W_TIMEOUT) {
693 if (!double_dev_wait_time(dev)) {
694 Mmsg(dev->errmsg, _("Max time exceeded waiting to mount Storage Device %s for Job %s\n"),
695 dev->print_name(), jcr->Job);
696 Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
697 Dmsg1(400, "Gave up waiting on device %s\n", dev->print_name());
698 return false; /* exceeded maximum waits */
702 if (stat == W_ERROR) {
704 Mmsg(dev->errmsg, _("pthread error in mount_volume\n"));
705 Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
708 Dmsg1(100, "Someone woke me for device %s\n", dev->print_name());
713 jcr->sendJobStatus(JS_Running);
714 Dmsg0(100, "leave dir_ask_sysop_to_mount_volume\n");