]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/reserve.c
Misc updates
[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 };
58
59 static dlist *vol_list = NULL;
60 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
61
62 /* Forward referenced functions */
63 static int can_reserve_drive(DCR *dcr, bool PerferMountedVols);
64 static int search_res_for_device(RCTX &rctx);
65 static int reserve_device(RCTX &rctx);
66 static bool reserve_device_for_read(DCR *dcr);
67 static bool reserve_device_for_append(DCR *dcr, bool PreferMountedVols);
68 static bool use_storage_cmd(JCR *jcr);
69 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx);
70
71 /* Requests from the Director daemon */
72 static char use_storage[]  = "use storage=%127s media_type=%127s "
73    "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
74 static char use_device[]  = "use device=%127s\n";
75
76 /* Responses sent to Director daemon */
77 static char OK_device[] = "3000 OK use device device=%s\n";
78 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
79 static char BAD_use[]   = "3913 Bad use command: %s\n";
80
81 bool use_cmd(JCR *jcr) 
82 {
83    /*
84     * Get the device, media, and pool information
85     */
86    if (!use_storage_cmd(jcr)) {
87       set_jcr_job_status(jcr, JS_ErrorTerminated);
88       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
89       return false;
90    }
91    return true;
92 }
93
94 static int my_compare(void *item1, void *item2)
95 {
96    return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
97 }
98
99
100 /*
101  * Put a new Volume entry in the Volume list. This
102  *  effectively reserves the volume so that it will
103  *  not be mounted again.
104  *
105  *  Return: VOLRES entry on success
106  *          NULL if the Volume is already in the list
107  */
108 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
109 {
110    VOLRES *vol, *nvol;
111    vol = (VOLRES *)malloc(sizeof(VOLRES));
112    memset(vol, 0, sizeof(VOLRES));
113    vol->vol_name = bstrdup(VolumeName);
114    vol->dev = dcr->dev;
115    vol->dcr = dcr;
116    P(vol_list_lock);
117    nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
118    V(vol_list_lock);
119    if (nvol != vol) {
120       free(vol->vol_name);
121       free(vol);
122       if (dcr->dev) {
123          nvol->dev = dcr->dev;
124       }
125       return NULL;
126    }
127    return vol;
128 }
129
130 /*
131  * Search for a Volume name in the Volume list.
132  *
133  *  Returns: VOLRES entry on success
134  *           NULL if the Volume is not in the list
135  */
136 VOLRES *find_volume(const char *VolumeName)
137 {
138    VOLRES vol, *fvol;
139    vol.vol_name = bstrdup(VolumeName);
140    P(vol_list_lock);
141    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
142    V(vol_list_lock);
143    free(vol.vol_name);
144    return fvol;
145 }
146
147 /*  
148  * Free a Volume from the Volume list
149  *
150  *  Returns: true if the Volume found and removed from the list
151  *           false if the Volume is not in the list
152  */
153 bool free_volume(DEVICE *dev)
154 {
155    VOLRES vol, *fvol;
156
157    if (dev->VolHdr.VolumeName[0] == 0) {
158       return false;
159    }
160    vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
161    P(vol_list_lock);
162    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
163    if (fvol) {
164       vol_list->remove(fvol);
165       free(fvol->vol_name);
166       free(fvol);
167    }
168    V(vol_list_lock);
169    free(vol.vol_name);
170    dev->VolHdr.VolumeName[0] = 0;
171    return fvol != NULL;
172 }
173
174 /* Free volume reserved by this dcr but not attached to a dev */
175 void free_unused_volume(DCR *dcr)
176 {
177    VOLRES *vol;
178    P(vol_list_lock);
179    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
180       if (vol->dcr == dcr && (vol->dev == NULL || 
181           strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
182          vol_list->remove(vol);
183          free(vol->vol_name);
184          free(vol);
185          break;
186       }
187    }
188    V(vol_list_lock);
189 }
190
191 /*
192  * List Volumes -- this should be moved to status.c
193  */
194 void list_volumes(BSOCK *user)  
195 {
196    VOLRES *vol;
197    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
198       bnet_fsend(user, "%s\n", vol->vol_name);
199    }
200 }
201       
202 /* Create the Volume list */
203 void create_volume_list()
204 {
205    VOLRES *dummy = NULL;
206    if (vol_list == NULL) {
207       vol_list = New(dlist(dummy, &dummy->link));
208    }
209 }
210
211 /* Release all Volumes from the list */
212 void free_volume_list()
213 {
214    VOLRES *vol;
215    if (!vol_list) {
216       return;
217    }
218    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
219       Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
220          vol->dcr, vol->dev);
221    }
222    delete vol_list;
223    vol_list = NULL;
224 }
225
226 bool is_volume_in_use(DCR *dcr)
227 {
228    VOLRES *vol = find_volume(dcr->VolumeName);
229    if (!vol) {
230       return false;                   /* vol not in list */
231    }
232    if (!vol->dev) {                   /* vol not attached to device */
233       return false;
234    }
235    if (dcr->dev == vol->dev) {        /* same device OK */
236       return false;
237    }
238    if (!vol->dev->is_busy()) {
239       return false;
240    }
241    return true;
242 }
243
244
245 static bool use_storage_cmd(JCR *jcr)
246 {
247    POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
248    BSOCK *dir = jcr->dir_bsock;
249    int append;
250    bool ok;       
251    int Copy, Stripe;
252    DIRSTORE *store;
253    RCTX rctx;
254    rctx.jcr = jcr;
255 #ifdef implemented
256    char *error;
257 #endif
258
259    /*
260     * If there are multiple devices, the director sends us
261     *   use_device for each device that it wants to use.
262     */
263    Dmsg1(100, "<dird: %s", dir->msg);
264    jcr->dirstore = New(alist(10, not_owned_by_alist));
265    do {
266       ok = sscanf(dir->msg, use_storage, store_name.c_str(), 
267                   media_type.c_str(), pool_name.c_str(), 
268                   pool_type.c_str(), &append, &Copy, &Stripe) == 7;
269       if (!ok) {
270          break;
271       }
272       unbash_spaces(store_name);
273       unbash_spaces(media_type);
274       unbash_spaces(pool_name);
275       unbash_spaces(pool_type);
276       store = new DIRSTORE;
277       jcr->dirstore->append(store);
278       memset(store, 0, sizeof(DIRSTORE));
279       store->device = New(alist(10));
280       bstrncpy(store->name, store_name, sizeof(store->name));
281       bstrncpy(store->media_type, media_type, sizeof(store->media_type));
282       bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
283       bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
284       store->append = append;
285
286       /* Now get all devices */
287       while (bnet_recv(dir) >= 0) {
288          ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
289          if (!ok) {
290             break;
291          }
292          unbash_spaces(dev_name);
293          store->device->append(bstrdup(dev_name.c_str()));
294       }
295    }  while (ok && bnet_recv(dir) >= 0);
296
297 #ifdef DEVELOPER
298    /* This loop is debug code and can be removed */
299    /* ***FIXME**** remove after 1.38 release */
300    char *device_name;
301    foreach_alist(store, jcr->dirstore) {
302       Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n", 
303          store->name, store->media_type, store->pool_name, 
304          store->pool_type);
305       foreach_alist(device_name, store->device) {
306          Dmsg1(100, "   Device=%s\n", device_name);
307       }
308    }
309 #endif
310
311    /*                    
312     * At this point, we have a list of all the Director's Storage
313     *  resources indicated for this Job, which include Pool, PoolType,
314     *  storage name, and Media type.     
315     * Then for each of the Storage resources, we have a list of
316     *  device names that were given.
317     *
318     * Wiffle through them and find one that can do the backup.
319     */
320    if (ok) {
321       /*
322        * Make up to two passes. The first with PreferMountedVols possibly
323        *   set to true.  In that case, we look only for an available 
324        *   drive with something mounted. If that fails, then we
325        *   do a second pass with PerferMountedVols set false.
326        */
327       rctx.PreferMountedVols = jcr->PreferMountedVols;
328       ok = find_suitable_device_for_job(jcr, rctx);
329       if (ok) {
330          goto done;
331       }
332       if (rctx.PreferMountedVols) {
333          rctx.PreferMountedVols = false;
334          ok = find_suitable_device_for_job(jcr, rctx);
335          if (ok) {
336             goto done;
337          }
338       }
339       if (verbose) {
340          unbash_spaces(dir->msg);
341          pm_strcpy(jcr->errmsg, dir->msg);
342          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
343       }
344       Jmsg(jcr, M_FATAL, 0, _("\n"
345          "     Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
346            dev_name.c_str(), media_type.c_str());
347       bnet_fsend(dir, NO_device, dev_name.c_str());
348 #ifdef implemented
349       for (error=(char*)rctx->errors.first(); error;
350            error=(char*)rctx->errors.next()) {
351          Jmsg(jcr, M_INFO, 0, "%s", error);
352       }
353 #endif
354       Dmsg1(100, ">dird: %s\n", dir->msg);
355    } else {
356       unbash_spaces(dir->msg);
357       pm_strcpy(jcr->errmsg, dir->msg);
358       if (verbose) {
359          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
360       }
361       bnet_fsend(dir, BAD_use, jcr->errmsg);
362       Dmsg1(100, ">dird: %s\n", dir->msg);
363    }
364
365 done:
366    foreach_alist(store, jcr->dirstore) {
367       delete store->device;
368       delete store;
369    }
370    delete jcr->dirstore;
371 #ifdef implemented
372    for (error=(char*)rctx->errors.first(); error;
373         error=(char*)rctx->errors.next()) {
374       free(error);
375    }
376 #endif
377    return ok;
378 }
379
380
381 /*
382  * Search for a device suitable for this job.
383  */
384 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
385 {
386    bool first = true;
387    bool ok = false;
388    DCR *dcr = NULL;
389    DIRSTORE *store;
390    char *device_name;
391
392    init_jcr_device_wait_timers(jcr);
393    for ( ;; ) {
394       int need_wait = false;
395       foreach_alist(store, jcr->dirstore) {
396          rctx.store = store;
397          foreach_alist(device_name, store->device) {
398             int stat;
399             rctx.device_name = device_name;
400             stat = search_res_for_device(rctx); 
401             if (stat == 1) {             /* found available device */
402                dcr = jcr->dcr;
403                ok = true;
404                break;
405             } else if (stat == 0) {      /* device busy */
406                need_wait = true;
407             }
408             /* otherwise error */
409 //             rctx->errors.push(bstrdup(jcr->errmsg));
410          }
411       }
412       /*
413        * If there is some device for which we can wait, then
414        *  wait and try again until the wait time expires
415        */
416       if (!need_wait || !wait_for_device(jcr, first)) {
417          break;
418       }
419       first = false;
420 #ifdef implemented
421       for (error=(char*)rctx->errors.first(); error;
422            error=(char*)rctx->errors.next()) {
423          free(error);
424       }
425 #endif
426    }
427    if (!ok && dcr) {
428       free_dcr(dcr);
429    }
430
431    return ok;
432 }
433
434 /*
435  * Search for a particular storage device with particular storage
436  *  characteristics (MediaType).
437  */
438 static int search_res_for_device(RCTX &rctx) 
439 {
440    AUTOCHANGER *changer;
441    BSOCK *dir = rctx.jcr->dir_bsock;
442    bool ok;
443    int stat;
444
445    Dmsg1(100, "Search res for %s\n", rctx.device_name);
446    foreach_res(rctx.device, R_DEVICE) {
447       Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
448       /* Find resource, and make sure we were able to open it */
449       if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0 &&
450           strcmp(rctx.device->media_type, rctx.store->media_type) == 0) {
451          stat = reserve_device(rctx);
452          if (stat != 1) {
453             return stat;
454          }
455          Dmsg1(220, "Got: %s", dir->msg);
456          bash_spaces(rctx.device_name);
457          ok = bnet_fsend(dir, OK_device, rctx.device_name);
458          Dmsg1(100, ">dird: %s\n", dir->msg);
459          return ok ? 1 : -1;
460       }
461    }
462    foreach_res(changer, R_AUTOCHANGER) {
463       Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
464       /* Find resource, and make sure we were able to open it */
465       if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
466          /* Try each device in this AutoChanger */
467          foreach_alist(rctx.device, changer->device) {
468             Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
469             stat = reserve_device(rctx);
470             if (stat == -1) {            /* hard error */
471                return -1;
472             }
473             if (stat == 0) {             /* must wait, try next one */
474                continue;
475             }
476             POOL_MEM dev_name;
477             Dmsg1(100, "Device %s opened.\n", rctx.device_name);
478             pm_strcpy(dev_name, rctx.device->hdr.name);
479             bash_spaces(dev_name);
480             ok = bnet_fsend(dir, OK_device, dev_name.c_str());  /* Return real device name */
481             Dmsg1(100, ">dird: %s\n", dir->msg);
482             return ok ? 1 : -1;
483          }
484       }
485    }
486    return 0;                    /* nothing found */
487 }
488
489 /*
490  *  Try to reserve a specific device.
491  *
492  *  Returns: 1 -- OK, have DCR
493  *           0 -- must wait
494  *          -1 -- fatal error
495  */
496 static int reserve_device(RCTX &rctx)
497 {
498    bool ok;
499    DCR *dcr;
500    const int name_len = MAX_NAME_LENGTH;
501    if (!rctx.device->dev) {
502       rctx.device->dev = init_dev(rctx.jcr, rctx.device);
503    }
504    if (!rctx.device->dev) {
505       if (rctx.device->changer_res) {
506         Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
507            "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
508              rctx.device->hdr.name, rctx.device_name);
509       } else {
510          Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
511             "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
512               rctx.device_name);
513       }
514       return -1;  /* no use waiting */
515    }  
516    Dmsg1(100, "Found device %s\n", rctx.device->hdr.name);
517    dcr = new_dcr(rctx.jcr, rctx.device->dev);
518    if (!dcr) {
519       BSOCK *dir = rctx.jcr->dir_bsock;
520       bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
521       Dmsg1(100, ">dird: %s\n", dir->msg);
522       return -1;
523    }
524    rctx.jcr->dcr = dcr;
525    bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
526    bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
527    bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
528    bstrncpy(dcr->dev_name, rctx.device_name, name_len);
529    if (rctx.store->append == SD_APPEND) {
530       ok = reserve_device_for_append(dcr, rctx.PreferMountedVols);
531       Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
532    } else {
533       ok = reserve_device_for_read(dcr);
534    }
535    if (!ok) {
536       free_dcr(rctx.jcr->dcr);
537       return 0;
538    }
539    return 1;
540 }
541
542 /*
543  * We "reserve" the drive by setting the ST_READ bit. No one else
544  *  should touch the drive until that is cleared.
545  *  This allows the DIR to "reserve" the device before actually
546  *  starting the job. 
547  */
548 static bool reserve_device_for_read(DCR *dcr)
549 {
550    DEVICE *dev = dcr->dev;
551    JCR *jcr = dcr->jcr;
552    bool ok = false;
553
554    ASSERT(dcr);
555
556    dev->block(BST_DOING_ACQUIRE);
557
558    if (is_device_unmounted(dev)) {             
559       Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
560       Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
561            dev->print_name());
562       goto bail_out;
563    }
564
565    if (dev->is_busy()) {
566       Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
567          dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
568       Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
569             dev->print_name());
570       goto bail_out;
571    }
572
573    dev->clear_append();
574    dev->set_read();
575    ok = true;
576
577 bail_out:
578    dev->unblock();
579    return ok;
580 }
581
582
583 /*
584  * We reserve the device for appending by incrementing the 
585  *  reserved_device. We do virtually all the same work that
586  *  is done in acquire_device_for_append(), but we do
587  *  not attempt to mount the device. This routine allows
588  *  the DIR to reserve multiple devices before *really* 
589  *  starting the job. It also permits the SD to refuse 
590  *  certain devices (not up, ...).
591  *
592  * Note, in reserving a device, if the device is for the
593  *  same pool and the same pool type, then it is acceptable.
594  *  The Media Type has already been checked. If we are
595  *  the first tor reserve the device, we put the pool
596  *  name and pool type in the device record.
597  */
598 static bool reserve_device_for_append(DCR *dcr, bool PreferMountedVols) 
599 {
600    JCR *jcr = dcr->jcr;
601    DEVICE *dev = dcr->dev;
602    bool ok = false;
603
604    ASSERT(dcr);
605
606    dev->block(BST_DOING_ACQUIRE);
607
608    if (dev->can_read()) {
609       Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
610       Dmsg1(100, "%s", jcr->errmsg);
611       goto bail_out;
612    }
613
614    if (is_device_unmounted(dev)) {
615       Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
616       Dmsg1(100, "%s", jcr->errmsg);
617       goto bail_out;
618    }
619
620    Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
621
622    if (can_reserve_drive(dcr, PreferMountedVols) != 1) {
623       Mmsg1(jcr->errmsg, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
624       Dmsg1(100, "%s", jcr->errmsg);
625       goto bail_out;
626    }
627
628    dev->reserved_device++;
629    Dmsg1(200, "Inc reserve=%d\n", dev->reserved_device);
630    dcr->reserved_device = true;
631    ok = true;
632
633 bail_out:
634    dev->unblock();
635    return ok;
636 }
637
638 /*
639  * Returns: 1 if drive can be reserved
640  *          0 if we should wait
641  *         -1 on error
642  */
643 static int can_reserve_drive(DCR *dcr, bool PreferMountedVols) 
644 {
645    DEVICE *dev = dcr->dev;
646    JCR *jcr = dcr->jcr;
647
648    if (PreferMountedVols && !dev->VolHdr.VolumeName[0] &&
649        dev->is_tape() && !dev->is_autochanger()) {
650       return 0;                 /* No volume mounted */
651    }
652
653    /*
654     * Handle the case that the drive is not yet in append mode
655     */
656    if (!dev->can_append() && dev->num_writers == 0) {
657       /* Now check if there are any reservations on the drive */
658       if (dev->reserved_device) {           
659          /* Yes, now check if we want the same Pool and pool type */
660          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
661              strcmp(dev->pool_type, dcr->pool_type) == 0) {
662             /* OK, compatible device */
663          } else {
664             /* Drive not suitable for us */
665             return 0;                 /* wait */
666          }
667       } else {
668          /* Device is available but not yet reserved, reserve it for us */
669          bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
670          bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
671       }
672       return 1;                       /* reserve drive */
673    }
674
675    /*
676     * Check if device in append mode with no writers (i.e. available)
677     */
678    if (dev->can_append() && dev->num_writers == 0) {
679       /* Device is available but not yet reserved, reserve it for us */
680       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
681       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
682       return 1;
683    }
684    /*
685     * Check if the device is in append mode with writers (i.e.
686     *  available if pool is the same).
687     */
688    if (dev->can_append() || dev->num_writers > 0) {
689       Dmsg0(190, "device already in append.\n");
690       /* Yes, now check if we want the same Pool and pool type */
691       if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
692           strcmp(dev->pool_type, dcr->pool_type) == 0) {
693          /* OK, compatible device */
694          return 1;
695       } else {
696          /* Drive not suitable for us */
697          Jmsg(jcr, M_WARNING, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
698          return 0;                    /* wait */
699       }
700    } else {
701       Pmsg0(000, "Logic error!!!! Should not get here.\n");
702       Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
703       return -1;                      /* error, should not get here */
704    }
705
706    return 0;
707 }