]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/reserve.c
This commit was manufactured by cvs2svn to create tag
[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-2006 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 static dlist *vol_list = NULL;
30 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
31
32 /* Forward referenced functions */
33 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
34 static int reserve_device(RCTX &rctx);
35 static bool reserve_device_for_read(DCR *dcr);
36 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
37 static bool use_storage_cmd(JCR *jcr);
38 static void queue_reserve_message(JCR *jcr);
39
40 /* Requests from the Director daemon */
41 static char use_storage[]  = "use storage=%127s media_type=%127s "
42    "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
43 static char use_device[]  = "use device=%127s\n";
44
45 /* Responses sent to Director daemon */
46 static char OK_device[] = "3000 OK use device device=%s\n";
47 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
48 static char BAD_use[]   = "3913 Bad use command: %s\n";
49
50 bool use_cmd(JCR *jcr) 
51 {
52    /*
53     * Get the device, media, and pool information
54     */
55    if (!use_storage_cmd(jcr)) {
56       set_jcr_job_status(jcr, JS_ErrorTerminated);
57       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
58       return false;
59    }
60    return true;
61 }
62
63 static int my_compare(void *item1, void *item2)
64 {
65    return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
66 }
67
68 static brwlock_t reservation_lock;
69
70 void init_reservations_lock()
71 {
72    int errstat;
73    if ((errstat=rwl_init(&reservation_lock)) != 0) {
74       berrno be;
75       Emsg1(M_ABORT, 0, _("Unable to initialize reservation lock. ERR=%s\n"),
76             be.strerror(errstat));
77    }
78
79 }
80
81 void term_reservations_lock()
82 {
83    rwl_destroy(&reservation_lock);
84 }
85
86 /* This applies to a drive and to Volumes */
87 void lock_reservations()
88 {
89    int errstat;
90    if ((errstat=rwl_writelock(&reservation_lock)) != 0) {
91       berrno be;
92       Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
93            errstat, be.strerror(errstat));
94    }
95 }
96
97 void unlock_reservations()
98 {
99    int errstat;
100    if ((errstat=rwl_writeunlock(&reservation_lock)) != 0) {
101       berrno be;
102       Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
103            errstat, be.strerror(errstat));
104    }
105 }
106
107
108 /*
109  * Put a new Volume entry in the Volume list. This
110  *  effectively reserves the volume so that it will
111  *  not be mounted again.
112  *
113  *  Return: VOLRES entry on success
114  *          NULL if the Volume is already in the list
115  */
116 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
117 {
118    VOLRES *vol, *nvol;
119
120    Dmsg1(400, "new_volume %s\n", VolumeName);
121    /* 
122     * We lock the reservations system here to ensure
123     *  when adding a new volume that no newly scheduled
124     *  job can reserve it.
125     */
126    lock_reservations();
127    P(vol_list_lock);
128    if (dcr->dev) {
129 again:
130       foreach_dlist(vol, vol_list) {
131          if (vol && vol->dev == dcr->dev) {
132             vol_list->remove(vol);
133             if (vol->vol_name) {
134                free(vol->vol_name);
135             }
136             free(vol);
137             goto again;
138          }
139       }
140    }
141    vol = (VOLRES *)malloc(sizeof(VOLRES));
142    memset(vol, 0, sizeof(VOLRES));
143    vol->vol_name = bstrdup(VolumeName);
144    vol->dev = dcr->dev;
145    vol->dcr = dcr;
146    Dmsg2(100, "New Vol=%s dev=%s\n", VolumeName, dcr->dev->print_name());
147    nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
148    if (nvol != vol) {
149       free(vol->vol_name);
150       free(vol);
151       vol = NULL;
152       if (dcr->dev) {
153          DEVICE *dev = nvol->dev;
154          if (!dev->is_busy()) {
155             Dmsg3(100, "Swap vol=%s from dev=%s to %s\n", VolumeName,
156                dev->print_name(), dcr->dev->print_name());
157             nvol->dev = dcr->dev;
158             dev->VolHdr.VolumeName[0] = 0;
159          } else {
160             Dmsg3(100, "!!!! could not swap vol=%s from dev=%s to %s\n", VolumeName,
161                dev->print_name(), dcr->dev->print_name());
162          }
163       }
164    }
165    V(vol_list_lock);
166    unlock_reservations();
167    return vol;
168 }
169
170 /*
171  * Search for a Volume name in the Volume list.
172  *
173  *  Returns: VOLRES entry on success
174  *           NULL if the Volume is not in the list
175  */
176 VOLRES *find_volume(const char *VolumeName)
177 {
178    VOLRES vol, *fvol;
179    /* Do not lock reservations here */
180    P(vol_list_lock);
181    vol.vol_name = bstrdup(VolumeName);
182    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
183    free(vol.vol_name);
184    V(vol_list_lock);
185    return fvol;
186 }
187
188 /*  
189  * Free a Volume from the Volume list
190  *
191  *  Returns: true if the Volume found and removed from the list
192  *           false if the Volume is not in the list
193  */
194 bool free_volume(DEVICE *dev)
195 {
196    VOLRES vol, *fvol;
197
198    P(vol_list_lock);
199    if (dev->VolHdr.VolumeName[0] == 0) {
200       Dmsg1(100, "free_volume: no vol on dev %s\n", dev->print_name());
201       /*
202        * Our device has no VolumeName listed, but
203        *  search the list for any Volume attached to
204        *  this device and remove it.
205        */
206       foreach_dlist(fvol, vol_list) {
207          if (fvol && fvol->dev == dev) {
208             vol_list->remove(fvol);
209             if (fvol->vol_name) {
210                Dmsg2(100, "free_volume %s dev=%s\n", fvol->vol_name, dev->print_name());
211                free(fvol->vol_name);
212             }
213             free(fvol);
214             break;
215          }
216       }
217       goto bail_out;
218    }
219    Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
220    vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
221    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
222    if (fvol) {
223       vol_list->remove(fvol);
224       Dmsg2(100, "free_volume %s dev=%s\n", fvol->vol_name, dev->print_name());
225       free(fvol->vol_name);
226       free(fvol);
227    }
228    free(vol.vol_name);
229    dev->VolHdr.VolumeName[0] = 0;
230 bail_out:
231    V(vol_list_lock);
232    return fvol != NULL;
233 }
234
235 /* Free volume reserved by this dcr but not attached to a dev */
236 void free_unused_volume(DCR *dcr)
237 {
238    VOLRES *vol;
239
240    P(vol_list_lock);
241    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
242       if (vol->dcr == dcr && (vol->dev == NULL || 
243           strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
244          vol_list->remove(vol);
245          Dmsg1(100, "free_unused_olume %s\n", vol->vol_name);
246          free(vol->vol_name);
247          free(vol);
248          break;
249       }
250    }
251    V(vol_list_lock);
252 }
253
254 /*
255  * List Volumes -- this should be moved to status.c
256  */
257 void list_volumes(BSOCK *user)  
258 {
259    VOLRES *vol;
260    P(vol_list_lock);
261    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
262       if (vol->dev) {
263          bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
264       } else {
265          bnet_fsend(user, "%s\n", vol->vol_name);
266       }
267    }
268    V(vol_list_lock);
269 }
270       
271 /* Create the Volume list */
272 void create_volume_list()
273 {
274    VOLRES *dummy = NULL;
275    if (vol_list == NULL) {
276       vol_list = New(dlist(dummy, &dummy->link));
277    }
278 }
279
280 /* Release all Volumes from the list */
281 void free_volume_list()
282 {
283    VOLRES *vol;
284    if (!vol_list) {
285       return;
286    }
287    P(vol_list_lock);
288    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
289       Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
290          vol->dcr, vol->dev);
291    }
292    delete vol_list;
293    vol_list = NULL;
294    V(vol_list_lock);
295 }
296
297 bool is_volume_in_use(DCR *dcr)
298 {
299    VOLRES *vol = find_volume(dcr->VolumeName);
300    if (!vol) {
301       Dmsg1(100, "Vol=%s not in use.\n", dcr->VolumeName);
302       return false;                   /* vol not in list */
303    }
304    if (!vol->dev) {                   /* vol not attached to device */
305       Dmsg1(100, "Vol=%s has no dev.\n", dcr->VolumeName);
306       return false;
307    }
308    if (dcr->dev == vol->dev) {        /* same device OK */
309       Dmsg1(100, "Vol=%s on same dev.\n", dcr->VolumeName);
310       return false;
311    }
312    if (!vol->dev->is_busy()) {
313       Dmsg2(100, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
314       return false;
315    }
316    Dmsg2(100, "Vol=%s used by %s.\n", dcr->VolumeName, vol->dev->print_name());
317    return true;
318 }
319
320
321 /*
322  * We get the following type of information:
323  *
324  * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
325  *  use device=zzz
326  *  use device=aaa
327  *  use device=bbb
328  * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
329  *  use device=bbb
330  *
331  */
332 static bool use_storage_cmd(JCR *jcr)
333 {
334    POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
335    BSOCK *dir = jcr->dir_bsock;
336    int append;
337    bool ok;       
338    int Copy, Stripe;
339    DIRSTORE *store;
340    RCTX rctx;
341    char *msg;
342    alist *msgs;
343
344    memset(&rctx, 0, sizeof(RCTX));
345    rctx.jcr = jcr;
346    /*
347     * If there are multiple devices, the director sends us
348     *   use_device for each device that it wants to use.
349     */
350    jcr->dirstore = New(alist(10, not_owned_by_alist));
351    msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));  
352    do {
353       Dmsg1(100, "<dird: %s", dir->msg);
354       ok = sscanf(dir->msg, use_storage, store_name.c_str(), 
355                   media_type.c_str(), pool_name.c_str(), 
356                   pool_type.c_str(), &append, &Copy, &Stripe) == 7;
357       if (!ok) {
358          break;
359       }
360       unbash_spaces(store_name);
361       unbash_spaces(media_type);
362       unbash_spaces(pool_name);
363       unbash_spaces(pool_type);
364       store = new DIRSTORE;
365       jcr->dirstore->append(store);
366       memset(store, 0, sizeof(DIRSTORE));
367       store->device = New(alist(10));
368       bstrncpy(store->name, store_name, sizeof(store->name));
369       bstrncpy(store->media_type, media_type, sizeof(store->media_type));
370       bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
371       bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
372       store->append = append;
373
374       /* Now get all devices */
375       while (bnet_recv(dir) >= 0) {
376          Dmsg1(100, "<dird device: %s", dir->msg);
377          ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
378          if (!ok) {
379             break;
380          }
381          unbash_spaces(dev_name);
382          store->device->append(bstrdup(dev_name.c_str()));
383       }
384    }  while (ok && bnet_recv(dir) >= 0);
385
386 #ifdef DEVELOPER
387    /* This loop is debug code and can be removed */
388    /* ***FIXME**** remove after 1.38 release */
389    char *device_name;
390    foreach_alist(store, jcr->dirstore) {
391       Dmsg5(110, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n", 
392          store->name, store->media_type, store->pool_name, 
393          store->pool_type, store->append);
394       foreach_alist(device_name, store->device) {
395          Dmsg1(110, "   Device=%s\n", device_name);
396       }
397    }
398 #endif
399
400    init_jcr_device_wait_timers(jcr);
401    /*                    
402     * At this point, we have a list of all the Director's Storage
403     *  resources indicated for this Job, which include Pool, PoolType,
404     *  storage name, and Media type.     
405     * Then for each of the Storage resources, we have a list of
406     *  device names that were given.
407     *
408     * Wiffle through them and find one that can do the backup.
409     */
410    if (ok) {
411       bool first = true;           /* print wait message once */
412       bool fail = false;
413       rctx.notify_dir = true;
414       lock_reservations();
415       for ( ; !fail && !job_canceled(jcr); ) {
416          while ((msg = (char *)msgs->pop())) {
417             free(msg);
418          }
419          rctx.suitable_device = false;
420          rctx.have_volume = false;
421          rctx.any_drive = false;
422          if (!jcr->PreferMountedVols) {
423             /* Look for unused drives in autochangers */
424             rctx.num_writers = 20000000;   /* start with impossible number */
425             rctx.low_use_drive = NULL;
426             rctx.PreferMountedVols = false;                
427             rctx.exact_match = false;
428             rctx.autochanger_only = true;
429             Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
430                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
431                rctx.autochanger_only, rctx.any_drive);
432             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
433                break;
434             }
435             /* Look through all drives possibly for low_use drive */
436             if (rctx.low_use_drive) {
437                rctx.try_low_use_drive = true;
438                if ((ok = find_suitable_device_for_job(jcr, rctx))) {
439                   break;
440                }
441                rctx.try_low_use_drive = false;
442             }
443             rctx.autochanger_only = false;
444             Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
445                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
446                rctx.autochanger_only, rctx.any_drive);
447             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
448                break;
449             }
450          }
451          /* Look for an exact match all drives */
452          rctx.PreferMountedVols = true;
453          rctx.exact_match = true;
454          rctx.autochanger_only = false;
455          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
456             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
457             rctx.autochanger_only, rctx.any_drive);
458          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
459             break;
460          }
461          /* Look for any mounted drive */
462          rctx.exact_match = false;
463          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
464             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
465             rctx.autochanger_only, rctx.any_drive);
466          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
467             break;
468          }
469          /* Try any drive */
470          rctx.any_drive = true;
471          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
472             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
473             rctx.autochanger_only, rctx.any_drive);
474          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
475             break;
476          }
477          /* Keep reservations locked *except* during wait_for_device() */
478          unlock_reservations();
479          if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
480             Dmsg0(100, "Fail. !suitable_device || !wait_for_device\n");
481             fail = true;
482          }   
483          lock_reservations();
484          first = false;
485          bnet_sig(dir, BNET_HEARTBEAT);  /* Inform Dir that we are alive */
486       }
487       unlock_reservations();
488       if (!ok) {
489          /*
490           * If we get here, there are no suitable devices available, which
491           *  means nothing configured.  If a device is suitable but busy
492           *  with another Volume, we will not come here.
493           */
494          unbash_spaces(dir->msg);
495          pm_strcpy(jcr->errmsg, dir->msg);
496          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
497          Jmsg(jcr, M_FATAL, 0, _("\n"
498             "     Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
499               dev_name.c_str(), media_type.c_str());
500          bnet_fsend(dir, NO_device, dev_name.c_str());
501
502          Dmsg1(100, ">dird: %s", dir->msg);
503       }
504    } else {
505       unbash_spaces(dir->msg);
506       pm_strcpy(jcr->errmsg, dir->msg);
507       Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
508       bnet_fsend(dir, BAD_use, jcr->errmsg);
509       Dmsg1(100, ">dird: %s", dir->msg);
510    }
511
512    release_msgs(jcr);
513    return ok;
514 }
515
516 void release_msgs(JCR *jcr)
517 {
518    alist *msgs = jcr->reserve_msgs;
519    char *msg;
520
521    if (!msgs) {
522       return;
523    }
524    lock_reservations();
525    while ((msg = (char *)msgs->pop())) {
526       free(msg);
527    }
528    delete msgs;
529    jcr->reserve_msgs = NULL;
530    unlock_reservations();
531 }
532
533 /*
534  * Search for a device suitable for this job.
535  */
536 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
537 {
538    bool ok;
539    DIRSTORE *store;
540    char *device_name;
541
542    /* 
543     * For each storage device that the user specified, we
544     *  search and see if there is a resource for that device.
545     */
546    Dmsg4(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
547       rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
548       rctx.autochanger_only);
549    ok = false;
550    foreach_alist(store, jcr->dirstore) {
551       rctx.store = store;
552       foreach_alist(device_name, store->device) {
553          int stat;
554          rctx.device_name = device_name;
555          stat = search_res_for_device(rctx); 
556          if (stat == 1) {             /* found available device */
557             Dmsg1(100, "Suitable device found=%s\n", device_name);
558             ok = true;
559             break;
560          } else if (stat == 0) {      /* device busy */
561             Dmsg1(110, "Suitable device found=%s, not used: busy\n", device_name);
562          } else {
563             /* otherwise error */
564             Dmsg0(110, "No suitable device found.\n");
565          }
566       }
567       if (ok) {
568          break;
569       }
570    }
571
572    return ok;
573 }
574
575 /*
576  * Search for a particular storage device with particular storage
577  *  characteristics (MediaType).
578  */
579 int search_res_for_device(RCTX &rctx) 
580 {
581    AUTOCHANGER *changer;
582    BSOCK *dir = rctx.jcr->dir_bsock;
583    bool ok;
584    int stat;
585
586    Dmsg1(110, "Search res for %s\n", rctx.device_name);
587    /* Look through Autochangers first */
588    foreach_res(changer, R_AUTOCHANGER) {
589       Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
590       /* Find resource, and make sure we were able to open it */
591       if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
592          /* Try each device in this AutoChanger */
593          foreach_alist(rctx.device, changer->device) {
594             Dmsg1(110, "Try changer device %s\n", rctx.device->hdr.name);
595             stat = reserve_device(rctx);
596             if (stat != 1) {             /* try another device */
597                continue;
598             }
599             POOL_MEM dev_name;
600             if (rctx.store->append == SD_APPEND) {
601                Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
602                   rctx.jcr->dcr->dev->reserved_device);
603             } else {
604                Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
605                   rctx.jcr->read_dcr->dev->reserved_device);
606             }
607             if (rctx.notify_dir) {
608                pm_strcpy(dev_name, rctx.device->hdr.name);
609                bash_spaces(dev_name);
610                ok = bnet_fsend(dir, OK_device, dev_name.c_str());  /* Return real device name */
611                Dmsg1(100, ">dird changer: %s", dir->msg);
612             } else {
613                ok = true;
614             }
615             return ok ? 1 : -1;
616          }
617       }
618    }
619
620    /* Now if requested look through regular devices */
621    if (!rctx.autochanger_only) {
622       foreach_res(rctx.device, R_DEVICE) {
623          Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
624          /* Find resource, and make sure we were able to open it */
625          if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
626             stat = reserve_device(rctx);
627             if (stat != 1) {
628                return stat;
629             }
630             if (rctx.notify_dir) {
631                bash_spaces(rctx.device_name);
632                ok = bnet_fsend(dir, OK_device, rctx.device_name);
633                Dmsg1(100, ">dird dev: %s", dir->msg);
634             } else {
635                ok = true;
636             }
637             return ok ? 1 : -1;
638          }
639       }
640    }
641    return -1;                    /* nothing found */
642 }
643
644 /*
645  *  Try to reserve a specific device.
646  *
647  *  Returns: 1 -- OK, have DCR
648  *           0 -- must wait
649  *          -1 -- fatal error
650  */
651 static int reserve_device(RCTX &rctx)
652 {
653    bool ok;
654    DCR *dcr;
655    const int name_len = MAX_NAME_LENGTH;
656
657    /* Make sure MediaType is OK */
658    Dmsg2(110, "MediaType device=%s request=%s\n",
659          rctx.device->media_type, rctx.store->media_type);
660    if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
661       return -1;
662    }
663
664    /* Make sure device exists -- i.e. we can stat() it */
665    if (!rctx.device->dev) {
666       rctx.device->dev = init_dev(rctx.jcr, rctx.device);
667    }
668    if (!rctx.device->dev) {
669       if (rctx.device->changer_res) {
670         Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
671            "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
672              rctx.device->hdr.name, rctx.device_name);
673       } else {
674          Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
675             "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
676               rctx.device_name);
677       }
678       return -1;  /* no use waiting */
679    }  
680
681    rctx.suitable_device = true;
682    Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
683          rctx.jcr->JobId);
684    dcr = new_dcr(rctx.jcr, rctx.device->dev);
685    if (!dcr) {
686       BSOCK *dir = rctx.jcr->dir_bsock;
687       bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
688       Dmsg1(100, ">dird: %s", dir->msg);
689       return -1;
690    }
691    bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
692    bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
693    bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
694    bstrncpy(dcr->dev_name, rctx.device_name, name_len);
695    if (rctx.store->append == SD_APPEND) {
696       if (rctx.exact_match && !rctx.have_volume) {
697          dcr->any_volume = true;
698          if (dir_find_next_appendable_volume(dcr)) {
699             bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
700             Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
701             rctx.have_volume = true;
702          } else {
703             Dmsg0(100, "No next volume found\n");
704             rctx.VolumeName[0] = 0;
705         }
706       }
707       ok = reserve_device_for_append(dcr, rctx);
708       if (ok) {
709          rctx.jcr->dcr = dcr;
710          Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
711                dcr->dev->reserved_device,
712                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
713       }
714    } else {
715       ok = reserve_device_for_read(dcr);
716       if (ok) {
717          rctx.jcr->read_dcr = dcr;
718          Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
719                dcr->dev->reserved_device,
720                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
721       }
722    }
723    if (!ok) {
724       free_dcr(dcr);
725       Dmsg0(110, "Not OK.\n");
726       return 0;
727    }
728    return 1;
729 }
730
731 /*
732  * We "reserve" the drive by setting the ST_READ bit. No one else
733  *  should touch the drive until that is cleared.
734  *  This allows the DIR to "reserve" the device before actually
735  *  starting the job. 
736  */
737 static bool reserve_device_for_read(DCR *dcr)
738 {
739    DEVICE *dev = dcr->dev;
740    JCR *jcr = dcr->jcr;
741    bool ok = false;
742
743    ASSERT(dcr);
744
745    /* Get locks in correct order */
746    unlock_reservations();
747    P(dev->mutex);
748    lock_reservations();
749
750    if (is_device_unmounted(dev)) {             
751       Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
752       Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
753            jcr->JobId, dev->print_name());
754       queue_reserve_message(jcr);
755       goto bail_out;
756    }
757
758    if (dev->is_busy()) {
759       Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
760          dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
761       Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
762             jcr->JobId, dev->print_name());
763       queue_reserve_message(jcr);
764       goto bail_out;
765    }
766
767    dev->clear_append();
768    dev->set_read();
769    ok = true;
770    dev->reserved_device++;
771    Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
772       dev->print_name(), dev);
773    dcr->reserved_device = true;
774
775 bail_out:
776    V(dev->mutex);
777    return ok;
778 }
779
780
781 /*
782  * We reserve the device for appending by incrementing the 
783  *  reserved_device. We do virtually all the same work that
784  *  is done in acquire_device_for_append(), but we do
785  *  not attempt to mount the device. This routine allows
786  *  the DIR to reserve multiple devices before *really* 
787  *  starting the job. It also permits the SD to refuse 
788  *  certain devices (not up, ...).
789  *
790  * Note, in reserving a device, if the device is for the
791  *  same pool and the same pool type, then it is acceptable.
792  *  The Media Type has already been checked. If we are
793  *  the first tor reserve the device, we put the pool
794  *  name and pool type in the device record.
795  */
796 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
797 {
798    JCR *jcr = dcr->jcr;
799    DEVICE *dev = dcr->dev;
800    bool ok = false;
801
802    ASSERT(dcr);
803
804    P(dev->mutex);
805
806    /* If device is being read, we cannot write it */
807    if (dev->can_read()) {
808       Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"), 
809          jcr->JobId, dev->print_name());
810       Dmsg1(110, "%s", jcr->errmsg);
811       queue_reserve_message(jcr);
812       goto bail_out;
813    }
814
815    /* If device is unmounted, we are out of luck */
816    if (is_device_unmounted(dev)) {
817       Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"), 
818          jcr->JobId, dev->print_name());
819       Dmsg1(110, "%s", jcr->errmsg);
820       queue_reserve_message(jcr);
821       goto bail_out;
822    }
823
824    Dmsg1(110, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
825
826    /* Now do detailed tests ... */
827    if (can_reserve_drive(dcr, rctx) != 1) {
828       Dmsg0(110, "can_reserve_drive!=1\n");
829       goto bail_out;
830    }
831
832    dev->reserved_device++;
833    Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
834       dev->print_name(), dev);
835    dcr->reserved_device = true;
836    ok = true;
837
838 bail_out:
839    V(dev->mutex);
840    return ok;
841 }
842
843 /*
844  * Returns: 1 if drive can be reserved
845  *          0 if we should wait
846  *         -1 on error or impossibility
847  */
848 static int can_reserve_drive(DCR *dcr, RCTX &rctx) 
849 {
850    DEVICE *dev = dcr->dev;
851    JCR *jcr = dcr->jcr;
852
853    Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
854          rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
855          rctx.autochanger_only, rctx.any_drive);
856
857    /* setting any_drive overrides PreferMountedVols flag */
858    if (!rctx.any_drive) {
859       /*
860        * When PreferMountedVols is set, we keep track of the 
861        *  drive in use that has the least number of writers, then if
862        *  no unmounted drive is found, we try that drive. This   
863        *  helps spread the load to the least used drives.  
864        */
865       if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
866          Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
867             dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
868          return 1;
869       }
870       /* If he wants a free drive, but this one is busy, no go */
871       if (!rctx.PreferMountedVols && dev->is_busy()) {
872          /* Save least used drive */
873          if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
874             rctx.num_writers = dev->num_writers + dev->reserved_device;
875             rctx.low_use_drive = dev;
876             Dmsg2(110, "set low use drive=%s num_writers=%d\n", dev->print_name(),
877                rctx.num_writers);
878          } else {
879             Dmsg1(110, "not low use num_writers=%d\n", dev->num_writers+ 
880                dev->reserved_device);
881          }
882          Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
883          Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"), 
884             jcr->JobId, dev->print_name());
885          queue_reserve_message(jcr);
886          return 0;
887       }
888
889       /* Check for prefer mounted volumes */
890       if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
891          Mmsg(jcr->errmsg, _("3606 JobId=%u wants mounted, but drive %s has no Volume.\n"), 
892             jcr->JobId, dev->print_name());
893          queue_reserve_message(jcr);
894          Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
895          return 0;                 /* No volume mounted */
896       }
897
898       /* Check for exact Volume name match */
899       if (rctx.exact_match && rctx.have_volume &&
900           strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
901          Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"), 
902             jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName, 
903             dev->print_name());
904          queue_reserve_message(jcr);
905          Dmsg2(110, "failed: Not exact match have=%s want=%s\n",
906                dev->VolHdr.VolumeName, rctx.VolumeName);
907          return 0;
908       }
909    }
910
911    /* Check for unused autochanger drive */
912    if (rctx.autochanger_only && dev->num_writers == 0 &&
913        dev->VolHdr.VolumeName[0] == 0) {
914       /* Device is available but not yet reserved, reserve it for us */
915       Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
916          dev->print_name(), jcr->JobId);
917       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
918       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
919       return 1;                       /* reserve drive */
920    }
921
922    /*
923     * Handle the case that there are no writers
924     */
925    if (dev->num_writers == 0) {
926       /* Now check if there are any reservations on the drive */
927       if (dev->reserved_device) {           
928          /* Now check if we want the same Pool and pool type */
929          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
930              strcmp(dev->pool_type, dcr->pool_type) == 0) {
931             /* OK, compatible device */
932             Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
933                dev->print_name(), jcr->JobId);
934             return 1;
935          } else {
936             /* Drive Pool not suitable for us */
937             Mmsg(jcr->errmsg, _("3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"), 
938                   jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
939             queue_reserve_message(jcr);
940             Dmsg2(110, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
941                dev->pool_name, dcr->pool_name);
942             return 0;                 /* wait */
943          }
944       } else if (dev->can_append()) {
945          /* Device in append mode, check if changing pool */
946          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
947              strcmp(dev->pool_type, dcr->pool_type) == 0) {
948             Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
949                dev->print_name(), jcr->JobId);
950             /* OK, compatible device */
951             return 1;
952          } else {
953             /* Changing pool, unload old tape if any in drive */
954             Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
955             unload_autochanger(dcr, 0);
956          }
957       }
958       /* Device is available but not yet reserved, reserve it for us */
959       Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
960          jcr->JobId);
961       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
962       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
963       return 1;                       /* reserve drive */
964    }
965
966    /*
967     * Check if the device is in append mode with writers (i.e.
968     *  available if pool is the same).
969     */
970    if (dev->can_append() || dev->num_writers > 0) {
971       /* Yes, now check if we want the same Pool and pool type */
972       if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
973           strcmp(dev->pool_type, dcr->pool_type) == 0) {
974          Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
975             dev->print_name(), jcr->JobId);
976          /* OK, compatible device */
977          return 1;
978       } else {
979          /* Drive Pool not suitable for us */
980          Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"), 
981                jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
982          queue_reserve_message(jcr);
983          Dmsg2(110, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
984             dev->pool_name, dcr->pool_name);
985          return 0;                    /* wait */
986       }
987    } else {
988       Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
989       Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
990             jcr->JobId, dev->print_name());
991       queue_reserve_message(jcr);
992       Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
993       return -1;                      /* error, should not get here */
994    }
995    Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"), 
996          jcr->JobId, dev->print_name());
997    queue_reserve_message(jcr);
998    Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
999    return 0;
1000 }
1001
1002 /*
1003  * search_lock is already set on entering this routine 
1004  */
1005 static void queue_reserve_message(JCR *jcr)
1006 {
1007    int i;   
1008    alist *msgs = jcr->reserve_msgs;
1009    char *msg;
1010
1011    if (!msgs) {
1012       return;
1013    }
1014    /*
1015     * Look for duplicate message.  If found, do
1016     * not insert
1017     */
1018    for (i=msgs->size()-1; i >= 0; i--) {
1019       msg = (char *)msgs->get(i);
1020       if (!msg) {
1021          return;
1022       }
1023       /* Comparison based on 4 digit message number */
1024       if (strncmp(msg, jcr->errmsg, 4) == 0) {
1025          return;
1026       }
1027    }      
1028    /* Message unique, so insert it */
1029    jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1030 }
1031
1032 /*
1033  * Send any reservation messages queued for this jcr
1034  */
1035 void send_drive_reserve_messages(JCR *jcr, BSOCK *user)
1036 {
1037    int i;
1038    alist *msgs;
1039    char *msg;
1040
1041    lock_reservations();
1042    msgs = jcr->reserve_msgs;
1043    if (!msgs || msgs->size() == 0) {
1044       unlock_reservations();
1045       return;
1046    }
1047    for (i=msgs->size()-1; i >= 0; i--) {
1048       msg = (char *)msgs->get(i);
1049       if (msg) {
1050          bnet_fsend(user, "   %s", msg);
1051       } else {
1052          break;
1053       }
1054    }
1055    unlock_reservations();
1056 }