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