]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/reserve.c
4543c3a65597b179a7dda50acd9629f8835f5983
[bacula/bacula] / bacula / src / stored / reserve.c
1 /*
2  *   Drive reservation functions for Storage Daemon
3  *
4  *   Kern Sibbald, MM
5  *
6  *   Split from job.c and acquire.c June 2005
7  *
8  *   Version $Id$
9  *
10  */
11 /*
12    Copyright (C) 2000-2005 Kern Sibbald
13
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License
16    version 2 as amended with additional clauses defined in the
17    file LICENSE in the main source directory.
18
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
22    the file LICENSE for additional details.
23
24  */
25
26 #include "bacula.h"
27 #include "stored.h"
28
29 /*
30  *   Use Device command from Director
31  *   He tells is what Device Name to use, the Media Type,
32  *      the Pool Name, and the Pool Type.
33  *
34  *    Ensure that the device exists and is opened, then store
35  *      the media and pool info in the JCR.  This class is used
36  *      only temporarily in this file.
37  */
38 class DIRSTORE {
39 public:
40    alist *device;
41    bool append;
42    char name[MAX_NAME_LENGTH];
43    char media_type[MAX_NAME_LENGTH];
44    char pool_name[MAX_NAME_LENGTH];
45    char pool_type[MAX_NAME_LENGTH];
46 };
47
48 /* Reserve context */
49 class RCTX {
50 public:
51    alist *errors;
52    JCR *jcr;
53    char *device_name;
54    DIRSTORE *store;
55    DEVRES   *device;
56    bool PreferMountedVols;
57    bool exact_match;
58    bool have_volume;
59    bool do_not_wait;
60    bool available_autochanger;
61    char VolumeName[MAX_NAME_LENGTH];
62 };
63
64 static dlist *vol_list = NULL;
65 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
66 static pthread_mutex_t search_lock = PTHREAD_MUTEX_INITIALIZER;
67
68 /* Forward referenced functions */
69 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
70 static int search_res_for_device(RCTX &rctx);
71 static int reserve_device(RCTX &rctx);
72 static bool reserve_device_for_read(DCR *dcr);
73 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
74 static bool use_storage_cmd(JCR *jcr);
75 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx);
76
77 /* Requests from the Director daemon */
78 static char use_storage[]  = "use storage=%127s media_type=%127s "
79    "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
80 static char use_device[]  = "use device=%127s\n";
81
82 /* Responses sent to Director daemon */
83 static char OK_device[] = "3000 OK use device device=%s\n";
84 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
85 static char BAD_use[]   = "3913 Bad use command: %s\n";
86
87 bool use_cmd(JCR *jcr) 
88 {
89    /*
90     * Get the device, media, and pool information
91     */
92    if (!use_storage_cmd(jcr)) {
93       set_jcr_job_status(jcr, JS_ErrorTerminated);
94       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
95       return false;
96    }
97    return true;
98 }
99
100 static int my_compare(void *item1, void *item2)
101 {
102    return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
103 }
104
105
106 /*
107  * Put a new Volume entry in the Volume list. This
108  *  effectively reserves the volume so that it will
109  *  not be mounted again.
110  *
111  *  Return: VOLRES entry on success
112  *          NULL if the Volume is already in the list
113  */
114 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
115 {
116    VOLRES *vol, *nvol;
117
118    Dmsg1(400, "new_volume %s\n", VolumeName);
119    vol = (VOLRES *)malloc(sizeof(VOLRES));
120    memset(vol, 0, sizeof(VOLRES));
121    vol->vol_name = bstrdup(VolumeName);
122    vol->dev = dcr->dev;
123    vol->dcr = dcr;
124    P(vol_list_lock);
125    nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
126    V(vol_list_lock);
127    if (nvol != vol) {
128       free(vol->vol_name);
129       free(vol);
130       if (dcr->dev) {
131          nvol->dev = dcr->dev;
132       }
133       return NULL;
134    }
135    return vol;
136 }
137
138 /*
139  * Search for a Volume name in the Volume list.
140  *
141  *  Returns: VOLRES entry on success
142  *           NULL if the Volume is not in the list
143  */
144 VOLRES *find_volume(const char *VolumeName)
145 {
146    VOLRES vol, *fvol;
147    vol.vol_name = bstrdup(VolumeName);
148    P(vol_list_lock);
149    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
150    V(vol_list_lock);
151    free(vol.vol_name);
152    return fvol;
153 }
154
155 /*  
156  * Free a Volume from the Volume list
157  *
158  *  Returns: true if the Volume found and removed from the list
159  *           false if the Volume is not in the list
160  */
161 bool free_volume(DEVICE *dev)
162 {
163    VOLRES vol, *fvol;
164
165    if (dev->VolHdr.VolumeName[0] == 0) {
166       /*
167        * Our device has no VolumeName listed, but
168        *  search the list for any Volume attached to
169        *  this device and remove it.
170        */
171       P(vol_list_lock);
172       foreach_dlist(fvol, vol_list) {
173          if (fvol && fvol->dev == dev) {
174             vol_list->remove(fvol);
175             if (fvol->vol_name) {
176                free(fvol->vol_name);
177             }
178             free(fvol);
179             break;
180          }
181       }
182       V(vol_list_lock);
183       return fvol != NULL;
184    }
185    Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
186    vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
187    P(vol_list_lock);
188    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
189    if (fvol) {
190       vol_list->remove(fvol);
191       free(fvol->vol_name);
192       free(fvol);
193    }
194    V(vol_list_lock);
195    free(vol.vol_name);
196    dev->VolHdr.VolumeName[0] = 0;
197    return fvol != NULL;
198 }
199
200 /* Free volume reserved by this dcr but not attached to a dev */
201 void free_unused_volume(DCR *dcr)
202 {
203    VOLRES *vol;
204    P(vol_list_lock);
205    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
206       if (vol->dcr == dcr && (vol->dev == NULL || 
207           strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
208          vol_list->remove(vol);
209          free(vol->vol_name);
210          free(vol);
211          break;
212       }
213    }
214    V(vol_list_lock);
215 }
216
217 /*
218  * List Volumes -- this should be moved to status.c
219  */
220 void list_volumes(BSOCK *user)  
221 {
222    VOLRES *vol;
223    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
224       if (vol->dev) {
225          bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
226       } else {
227          bnet_fsend(user, "%s\n", vol->vol_name);
228       }
229    }
230 }
231       
232 /* Create the Volume list */
233 void create_volume_list()
234 {
235    VOLRES *dummy = NULL;
236    if (vol_list == NULL) {
237       vol_list = New(dlist(dummy, &dummy->link));
238    }
239 }
240
241 /* Release all Volumes from the list */
242 void free_volume_list()
243 {
244    VOLRES *vol;
245    if (!vol_list) {
246       return;
247    }
248    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
249       Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
250          vol->dcr, vol->dev);
251    }
252    delete vol_list;
253    vol_list = NULL;
254 }
255
256 bool is_volume_in_use(DCR *dcr)
257 {
258    VOLRES *vol = find_volume(dcr->VolumeName);
259    if (!vol) {
260       return false;                   /* vol not in list */
261    }
262    if (!vol->dev) {                   /* vol not attached to device */
263       return false;
264    }
265    if (dcr->dev == vol->dev) {        /* same device OK */
266       return false;
267    }
268    if (!vol->dev->is_busy()) {
269       return false;
270    }
271    return true;
272 }
273
274
275 static bool use_storage_cmd(JCR *jcr)
276 {
277    POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
278    BSOCK *dir = jcr->dir_bsock;
279    int append;
280    bool ok;       
281    int Copy, Stripe;
282    DIRSTORE *store;
283    RCTX rctx;
284 #ifdef implemented
285    char *error;
286 #endif
287
288    memset(&rctx, 0, sizeof(RCTX));
289    rctx.jcr = jcr;
290    /*
291     * If there are multiple devices, the director sends us
292     *   use_device for each device that it wants to use.
293     */
294    Dmsg1(100, "<dird: %s", dir->msg);
295    jcr->dirstore = New(alist(10, not_owned_by_alist));
296    do {
297       ok = sscanf(dir->msg, use_storage, store_name.c_str(), 
298                   media_type.c_str(), pool_name.c_str(), 
299                   pool_type.c_str(), &append, &Copy, &Stripe) == 7;
300       if (!ok) {
301          break;
302       }
303       unbash_spaces(store_name);
304       unbash_spaces(media_type);
305       unbash_spaces(pool_name);
306       unbash_spaces(pool_type);
307       store = new DIRSTORE;
308       jcr->dirstore->append(store);
309       memset(store, 0, sizeof(DIRSTORE));
310       store->device = New(alist(10));
311       bstrncpy(store->name, store_name, sizeof(store->name));
312       bstrncpy(store->media_type, media_type, sizeof(store->media_type));
313       bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
314       bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
315       store->append = append;
316
317       /* Now get all devices */
318       while (bnet_recv(dir) >= 0) {
319          ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
320          if (!ok) {
321             break;
322          }
323          unbash_spaces(dev_name);
324          store->device->append(bstrdup(dev_name.c_str()));
325       }
326    }  while (ok && bnet_recv(dir) >= 0);
327
328 #ifdef DEVELOPER
329    /* This loop is debug code and can be removed */
330    /* ***FIXME**** remove after 1.38 release */
331    char *device_name;
332    foreach_alist(store, jcr->dirstore) {
333       Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n", 
334          store->name, store->media_type, store->pool_name, 
335          store->pool_type);
336       foreach_alist(device_name, store->device) {
337          Dmsg1(100, "   Device=%s\n", device_name);
338       }
339    }
340 #endif
341
342    /*                    
343     * At this point, we have a list of all the Director's Storage
344     *  resources indicated for this Job, which include Pool, PoolType,
345     *  storage name, and Media type.     
346     * Then for each of the Storage resources, we have a list of
347     *  device names that were given.
348     *
349     * Wiffle through them and find one that can do the backup.
350     */
351    if (ok) {
352       /*
353        * First look for an exact match of Volume name as the
354        *  tape may already be mounted.
355        */
356       rctx.do_not_wait = true;
357       rctx.exact_match = true;
358       if ((ok = find_suitable_device_for_job(jcr, rctx))) {
359          goto done;
360       }
361       rctx.exact_match = false;
362
363       /* Now search if an unused autochanger slot is available */
364       rctx.available_autochanger = true;
365       if ((ok = find_suitable_device_for_job(jcr, rctx))) {
366          goto done;
367       }
368       rctx.available_autochanger = false;
369
370
371       /*
372        * Make up to two passes. The first with PreferMountedVols possibly
373        *   set to true.  In that case, we look only for an available 
374        *   drive with something mounted. If that fails, then we
375        *   do a second pass with PerferMountedVols set false.
376        */
377       rctx.PreferMountedVols = jcr->PreferMountedVols;
378       if (!rctx.PreferMountedVols) {
379          rctx.do_not_wait = false;
380       }
381       if ((ok = find_suitable_device_for_job(jcr, rctx))) {
382          goto done;
383       }
384       if (rctx.PreferMountedVols) {
385          rctx.PreferMountedVols = false;
386          rctx.do_not_wait = false;
387          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
388             goto done;
389          }
390       }
391       if (verbose) {
392          unbash_spaces(dir->msg);
393          pm_strcpy(jcr->errmsg, dir->msg);
394          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
395       }
396       Jmsg(jcr, M_FATAL, 0, _("\n"
397          "     Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
398            dev_name.c_str(), media_type.c_str());
399       bnet_fsend(dir, NO_device, dev_name.c_str());
400 #ifdef implemented
401       for (error=(char*)rctx->errors.first(); error;
402            error=(char*)rctx->errors.next()) {
403          Jmsg(jcr, M_INFO, 0, "%s", error);
404       }
405 #endif
406       Dmsg1(100, ">dird: %s", dir->msg);
407    } else {
408       unbash_spaces(dir->msg);
409       pm_strcpy(jcr->errmsg, dir->msg);
410       if (verbose) {
411          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
412       }
413       bnet_fsend(dir, BAD_use, jcr->errmsg);
414       Dmsg1(100, ">dird: %s", dir->msg);
415    }
416
417 done:
418    foreach_alist(store, jcr->dirstore) {
419       delete store->device;
420       delete store;
421    }
422    delete jcr->dirstore;
423 #ifdef implemented
424    for (error=(char*)rctx->errors.first(); error;
425         error=(char*)rctx->errors.next()) {
426       free(error);
427    }
428 #endif
429    return ok;
430 }
431
432
433 /*
434  * Search for a device suitable for this job.
435  */
436 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
437 {
438    bool first = true;
439    bool ok;
440    DCR *dcr = NULL;
441    DIRSTORE *store;
442    char *device_name;
443
444    init_jcr_device_wait_timers(jcr);
445    for ( ;; ) {
446       int can_wait = false;
447       ok = false;
448       P(search_lock);
449       foreach_alist(store, jcr->dirstore) {
450          rctx.store = store;
451          foreach_alist(device_name, store->device) {
452             int stat;
453             rctx.device_name = device_name;
454             stat = search_res_for_device(rctx); 
455             if (stat == 1) {             /* found available device */
456                ok = true;
457                break;
458             } else if (stat == 0) {      /* device busy */
459                can_wait = true;
460             }
461             /* otherwise error */
462 //             rctx->errors.push(bstrdup(jcr->errmsg));
463          }
464          if (ok) {
465             break;
466          }
467       }
468       V(search_lock);
469       /*
470        * We did not find a suitable device, so
471        *  if there is some device for which we can wait, then
472        *  wait and try again until the wait time expires
473        */
474       if (rctx.do_not_wait || !can_wait || !wait_for_device(jcr, first)) {
475          break;
476       }
477       first = false;                  /* first wait complete */
478
479 #ifdef implemented
480       for (error=(char*)rctx->errors.first(); error;
481            error=(char*)rctx->errors.next()) {
482          free(error);
483       }
484 #endif
485    }
486    if (dcr) {
487       free_dcr(dcr);
488    }
489    return ok;
490 }
491
492 /*
493  * Search for a particular storage device with particular storage
494  *  characteristics (MediaType).
495  */
496 static int search_res_for_device(RCTX &rctx) 
497 {
498    AUTOCHANGER *changer;
499    BSOCK *dir = rctx.jcr->dir_bsock;
500    bool ok;
501    int stat;
502
503    Dmsg1(100, "Search res for %s\n", rctx.device_name);
504    if (!rctx.available_autochanger) {
505       foreach_res(rctx.device, R_DEVICE) {
506          Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
507          /* Find resource, and make sure we were able to open it */
508          if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
509             stat = reserve_device(rctx);
510             if (stat != 1) {
511                return stat;
512             }
513             Dmsg1(220, "Got: %s", dir->msg);
514             bash_spaces(rctx.device_name);
515             ok = bnet_fsend(dir, OK_device, rctx.device_name);
516             Dmsg1(100, ">dird dev: %s", dir->msg);
517             return ok ? 1 : -1;
518          }
519       }
520    }
521    foreach_res(changer, R_AUTOCHANGER) {
522       Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
523       /* Find resource, and make sure we were able to open it */
524       if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
525          /* Try each device in this AutoChanger */
526          foreach_alist(rctx.device, changer->device) {
527             Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
528             stat = reserve_device(rctx);
529             if (stat == -1) {            /* hard error */
530                return -1;
531             }
532             if (stat == 0) {             /* must wait, try next one */
533                continue;
534             }
535             POOL_MEM dev_name;
536             Dmsg1(100, "Device %s opened.\n", rctx.device_name);
537             pm_strcpy(dev_name, rctx.device->hdr.name);
538             bash_spaces(dev_name);
539             ok = bnet_fsend(dir, OK_device, dev_name.c_str());  /* Return real device name */
540             Dmsg1(100, ">dird changer: %s", dir->msg);
541             return ok ? 1 : -1;
542          }
543       }
544    }
545    return 0;                    /* nothing found */
546 }
547
548 /*
549  *  Try to reserve a specific device.
550  *
551  *  Returns: 1 -- OK, have DCR
552  *           0 -- must wait
553  *          -1 -- fatal error
554  */
555 static int reserve_device(RCTX &rctx)
556 {
557    bool ok;
558    DCR *dcr;
559    const int name_len = MAX_NAME_LENGTH;
560
561    /* Make sure MediaType is OK */
562    if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
563       return -1;
564    }
565
566    if (!rctx.device->dev) {
567       rctx.device->dev = init_dev(rctx.jcr, rctx.device);
568    }
569    if (!rctx.device->dev) {
570       if (rctx.device->changer_res) {
571         Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
572            "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
573              rctx.device->hdr.name, rctx.device_name);
574       } else {
575          Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
576             "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
577               rctx.device_name);
578       }
579       return -1;  /* no use waiting */
580    }  
581    Dmsg1(100, "Found device %s\n", rctx.device->hdr.name);
582    dcr = new_dcr(rctx.jcr, rctx.device->dev);
583    if (!dcr) {
584       BSOCK *dir = rctx.jcr->dir_bsock;
585       bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
586       Dmsg1(100, ">dird: %s", dir->msg);
587       return -1;
588    }
589    rctx.jcr->dcr = dcr;
590    bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
591    bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
592    bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
593    bstrncpy(dcr->dev_name, rctx.device_name, name_len);
594    if (rctx.store->append == SD_APPEND) {
595       if (rctx.exact_match && !rctx.have_volume) {
596          dcr->any_volume = true;
597          if (dir_find_next_appendable_volume(dcr)) {
598             Dmsg1(200, "Looking for Volume=%s\n", dcr->VolumeName);
599             bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
600             rctx.have_volume = true;
601          } else {
602             Dmsg0(200, "No next volume found\n");
603             rctx.VolumeName[0] = 0;
604         }
605       }
606       ok = reserve_device_for_append(dcr, rctx);
607       Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
608    } else {
609       ok = reserve_device_for_read(dcr);
610    }
611    if (!ok) {
612       free_dcr(rctx.jcr->dcr);
613       return 0;
614    }
615    return 1;
616 }
617
618 /*
619  * We "reserve" the drive by setting the ST_READ bit. No one else
620  *  should touch the drive until that is cleared.
621  *  This allows the DIR to "reserve" the device before actually
622  *  starting the job. 
623  */
624 static bool reserve_device_for_read(DCR *dcr)
625 {
626    DEVICE *dev = dcr->dev;
627    JCR *jcr = dcr->jcr;
628    bool ok = false;
629
630    ASSERT(dcr);
631
632    dev->block(BST_DOING_ACQUIRE);
633
634    if (is_device_unmounted(dev)) {             
635       Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
636       Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
637            dev->print_name());
638       goto bail_out;
639    }
640
641    if (dev->is_busy()) {
642       Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
643          dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
644       Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
645             dev->print_name());
646       goto bail_out;
647    }
648
649    dev->clear_append();
650    dev->set_read();
651    ok = true;
652
653 bail_out:
654    dev->unblock();
655    return ok;
656 }
657
658
659 /*
660  * We reserve the device for appending by incrementing the 
661  *  reserved_device. We do virtually all the same work that
662  *  is done in acquire_device_for_append(), but we do
663  *  not attempt to mount the device. This routine allows
664  *  the DIR to reserve multiple devices before *really* 
665  *  starting the job. It also permits the SD to refuse 
666  *  certain devices (not up, ...).
667  *
668  * Note, in reserving a device, if the device is for the
669  *  same pool and the same pool type, then it is acceptable.
670  *  The Media Type has already been checked. If we are
671  *  the first tor reserve the device, we put the pool
672  *  name and pool type in the device record.
673  */
674 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
675 {
676    JCR *jcr = dcr->jcr;
677    DEVICE *dev = dcr->dev;
678    bool ok = false;
679
680    ASSERT(dcr);
681
682    dev->block(BST_DOING_ACQUIRE);
683
684    if (dev->can_read()) {
685       Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
686       Dmsg1(100, "%s", jcr->errmsg);
687       goto bail_out;
688    }
689
690    if (is_device_unmounted(dev)) {
691       Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
692       Dmsg1(100, "%s", jcr->errmsg);
693       goto bail_out;
694    }
695
696    Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
697
698    if (can_reserve_drive(dcr, rctx) != 1) {
699       Dmsg1(100, "%s", jcr->errmsg);
700       goto bail_out;
701    }
702
703    dev->reserved_device++;
704    Dmsg1(200, "Inc reserve=%d\n", dev->reserved_device);
705    dcr->reserved_device = true;
706    ok = true;
707
708 bail_out:
709    dev->unblock();
710    return ok;
711 }
712
713 /*
714  * Returns: 1 if drive can be reserved
715  *          0 if we should wait
716  *         -1 on error
717  */
718 static int can_reserve_drive(DCR *dcr, RCTX &rctx) 
719 {
720    DEVICE *dev = dcr->dev;
721    JCR *jcr = dcr->jcr;
722
723    /* Check for prefer mounted volumes */
724    if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
725       Mmsg0(jcr->errmsg, _("Want mounted Volume, drive is empty\n"));
726       Dmsg0(200, "want mounted -- no vol\n");
727       return 0;                 /* No volume mounted */
728    }
729
730    /* Check for exact Volume name match */
731    if (rctx.exact_match && rctx.have_volume &&
732        strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
733       Mmsg2(jcr->errmsg, _("Not exact match have=%s want=%s\n"),
734             dev->VolHdr.VolumeName, rctx.VolumeName);
735       Dmsg2(200, "Not exact match have=%s want=%s\n",
736             dev->VolHdr.VolumeName, rctx.VolumeName);
737       return 0;
738    }
739
740    /* Check for unused autochanger drive */
741    if (rctx.available_autochanger && dev->num_writers == 0 &&
742        dev->VolHdr.VolumeName[0] == 0) {
743       /* Device is available but not yet reserved, reserve it for us */
744       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
745       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
746       return 1;                       /* reserve drive */
747    }
748
749    /*
750     * Handle the case that there are no writers
751     */
752    if (dev->num_writers == 0) {
753       /* Now check if there are any reservations on the drive */
754       if (dev->reserved_device) {           
755          /* Now check if we want the same Pool and pool type */
756          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
757              strcmp(dev->pool_type, dcr->pool_type) == 0) {
758             /* OK, compatible device */
759             Dmsg0(200, "got dev: num_writers=0, reserved, pool matches\n");
760             return 1;
761          } else {
762             /* Drive not suitable for us */
763             Mmsg2(jcr->errmsg, _("Drive busy wrong pool: num_writers=0, reserved, pool=%s wanted=%s\n"),
764                dev->pool_name, dcr->pool_name);
765             Dmsg2(200, "busy: num_writers=0, reserved, pool=%s wanted=%s\n",
766                dev->pool_name, dcr->pool_name);
767             return 0;                 /* wait */
768          }
769       } else if (dev->can_append()) {
770          /* Device in append mode, check if changing pool */
771          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
772              strcmp(dev->pool_type, dcr->pool_type) == 0) {
773             Dmsg0(200, "got dev: num_writers=0, can_append, pool matches\n");
774             /* OK, compatible device */
775             return 1;
776          } else {
777             /* Changing pool, unload old tape if any in drive */
778             Dmsg0(200, "got dev: num_writers=0, reserved, pool change\n");
779             unload_autochanger(dcr, 0);
780          }
781       }
782       /* Device is available but not yet reserved, reserve it for us */
783       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
784       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
785       return 1;                       /* reserve drive */
786    }
787
788    /*
789     * Check if the device is in append mode with writers (i.e.
790     *  available if pool is the same).
791     */
792    if (dev->can_append() || dev->num_writers > 0) {
793       Dmsg0(190, "device already in append.\n");
794       /* Yes, now check if we want the same Pool and pool type */
795       if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
796           strcmp(dev->pool_type, dcr->pool_type) == 0) {
797          Dmsg0(200, "got dev: num_writers>=0, can_append, pool matches\n");
798          /* OK, compatible device */
799          return 1;
800       } else {
801          /* Drive not suitable for us */
802          Mmsg(jcr->errmsg, _("Wanted Pool \"%s\", but device %s is using Pool \"%s\" .\n"), 
803                  dcr->pool_name, dev->print_name(), dev->pool_name);
804          Dmsg2(200, "busy: num_writers>0, can_append, pool=%s wanted=%s\n",
805             dev->pool_name, dcr->pool_name);
806          return 0;                    /* wait */
807       }
808    } else {
809       Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
810       Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
811       return -1;                      /* error, should not get here */
812    }
813
814    return 0;
815 }