]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/reserve.c
kes Change error message 'illegal' to 'invalid' -- bug #707
[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_volume %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(void sendit(const char *msg, int len, void *sarg), void *arg)
258 {
259    VOLRES *vol;
260    char *msg;
261    int len;
262
263    msg = (char *)get_pool_memory(PM_MESSAGE);
264
265    P(vol_list_lock);
266    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
267       if (vol->dev) {
268          len = Mmsg(msg, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
269          sendit(msg, len, arg);
270       } else {
271          len = Mmsg(msg, "%s\n", vol->vol_name);
272          sendit(msg, len, arg);
273       }
274    }
275    V(vol_list_lock);
276
277    free_pool_memory(msg);
278 }
279       
280 /* Create the Volume list */
281 void create_volume_list()
282 {
283    VOLRES *dummy = NULL;
284    if (vol_list == NULL) {
285       vol_list = New(dlist(dummy, &dummy->link));
286    }
287 }
288
289 /* Release all Volumes from the list */
290 void free_volume_list()
291 {
292    VOLRES *vol;
293    if (!vol_list) {
294       return;
295    }
296    P(vol_list_lock);
297    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
298       Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
299          vol->dcr, vol->dev);
300    }
301    delete vol_list;
302    vol_list = NULL;
303    V(vol_list_lock);
304 }
305
306 bool is_volume_in_use(DCR *dcr)
307 {
308    VOLRES *vol = find_volume(dcr->VolumeName);
309    if (!vol) {
310       Dmsg1(100, "Vol=%s not in use.\n", dcr->VolumeName);
311       return false;                   /* vol not in list */
312    }
313    if (!vol->dev) {                   /* vol not attached to device */
314       Dmsg1(100, "Vol=%s has no dev.\n", dcr->VolumeName);
315       return false;
316    }
317    if (dcr->dev == vol->dev) {        /* same device OK */
318       Dmsg1(100, "Vol=%s on same dev.\n", dcr->VolumeName);
319       return false;
320    }
321    if (!vol->dev->is_busy()) {
322       Dmsg2(100, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
323       return false;
324    }
325    Dmsg2(100, "Vol=%s used by %s.\n", dcr->VolumeName, vol->dev->print_name());
326    return true;
327 }
328
329
330 /*
331  * We get the following type of information:
332  *
333  * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
334  *  use device=zzz
335  *  use device=aaa
336  *  use device=bbb
337  * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
338  *  use device=bbb
339  *
340  */
341 static bool use_storage_cmd(JCR *jcr)
342 {
343    POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
344    BSOCK *dir = jcr->dir_bsock;
345    int append;
346    bool ok;       
347    int Copy, Stripe;
348    DIRSTORE *store;
349    RCTX rctx;
350    char *msg;
351    alist *msgs;
352    alist *dirstore;
353
354    memset(&rctx, 0, sizeof(RCTX));
355    rctx.jcr = jcr;
356    /*
357     * If there are multiple devices, the director sends us
358     *   use_device for each device that it wants to use.
359     */
360    dirstore = New(alist(10, not_owned_by_alist));
361 // Dmsg2(000, "dirstore=%p JobId=%u\n", dirstore, jcr->JobId);
362    msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));  
363    do {
364       Dmsg1(100, "<dird: %s", dir->msg);
365       ok = sscanf(dir->msg, use_storage, store_name.c_str(), 
366                   media_type.c_str(), pool_name.c_str(), 
367                   pool_type.c_str(), &append, &Copy, &Stripe) == 7;
368       if (!ok) {
369          break;
370       }
371       if (append) {
372          jcr->write_store = dirstore;
373       } else {
374          jcr->read_store = dirstore;
375       }
376       rctx.append = append;
377       unbash_spaces(store_name);
378       unbash_spaces(media_type);
379       unbash_spaces(pool_name);
380       unbash_spaces(pool_type);
381       store = new DIRSTORE;
382       dirstore->append(store);
383       memset(store, 0, sizeof(DIRSTORE));
384       store->device = New(alist(10));
385       bstrncpy(store->name, store_name, sizeof(store->name));
386       bstrncpy(store->media_type, media_type, sizeof(store->media_type));
387       bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
388       bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
389       store->append = append;
390
391       /* Now get all devices */
392       while (bnet_recv(dir) >= 0) {
393          Dmsg1(100, "<dird device: %s", dir->msg);
394          ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
395          if (!ok) {
396             break;
397          }
398          unbash_spaces(dev_name);
399          store->device->append(bstrdup(dev_name.c_str()));
400       }
401    }  while (ok && bnet_recv(dir) >= 0);
402
403 #ifdef DEVELOPER
404    /* This loop is debug code and can be removed */
405    /* ***FIXME**** remove after 1.38 release */
406    char *device_name;
407    foreach_alist(store, dirstore) {
408       Dmsg5(110, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n", 
409          store->name, store->media_type, store->pool_name, 
410          store->pool_type, store->append);
411       foreach_alist(device_name, store->device) {
412          Dmsg1(110, "   Device=%s\n", device_name);
413       }
414    }
415 #endif
416
417    init_jcr_device_wait_timers(jcr);
418    /*                    
419     * At this point, we have a list of all the Director's Storage
420     *  resources indicated for this Job, which include Pool, PoolType,
421     *  storage name, and Media type.     
422     * Then for each of the Storage resources, we have a list of
423     *  device names that were given.
424     *
425     * Wiffle through them and find one that can do the backup.
426     */
427    if (ok) {
428       bool first = true;           /* print wait message once */
429       bool fail = false;
430       rctx.notify_dir = true;
431       lock_reservations();
432       for ( ; !fail && !job_canceled(jcr); ) {
433          while ((msg = (char *)msgs->pop())) {
434             free(msg);
435          }
436          rctx.suitable_device = false;
437          rctx.have_volume = false;
438          rctx.any_drive = false;
439          if (!jcr->PreferMountedVols) {
440             /* Look for unused drives in autochangers */
441             rctx.num_writers = 20000000;   /* start with impossible number */
442             rctx.low_use_drive = NULL;
443             rctx.PreferMountedVols = false;                
444             rctx.exact_match = false;
445             rctx.autochanger_only = true;
446             Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
447                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
448                rctx.autochanger_only, rctx.any_drive);
449             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
450                break;
451             }
452             /* Look through all drives possibly for low_use drive */
453             if (rctx.low_use_drive) {
454                rctx.try_low_use_drive = true;
455                if ((ok = find_suitable_device_for_job(jcr, rctx))) {
456                   break;
457                }
458                rctx.try_low_use_drive = false;
459             }
460             rctx.autochanger_only = false;
461             Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
462                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
463                rctx.autochanger_only, rctx.any_drive);
464             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
465                break;
466             }
467          }
468          /* Look for an exact match all drives */
469          rctx.PreferMountedVols = true;
470          rctx.exact_match = true;
471          rctx.autochanger_only = false;
472          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
473             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
474             rctx.autochanger_only, rctx.any_drive);
475          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
476             break;
477          }
478          /* Look for any mounted drive */
479          rctx.exact_match = false;
480          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
481             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
482             rctx.autochanger_only, rctx.any_drive);
483          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
484             break;
485          }
486          /* Try any drive */
487          rctx.any_drive = true;
488          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
489             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
490             rctx.autochanger_only, rctx.any_drive);
491          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
492             break;
493          }
494          /* Keep reservations locked *except* during wait_for_device() */
495          unlock_reservations();
496          if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
497             Dmsg0(100, "Fail. !suitable_device || !wait_for_device\n");
498             fail = true;
499          }   
500          lock_reservations();
501          first = false;
502          bnet_sig(dir, BNET_HEARTBEAT);  /* Inform Dir that we are alive */
503       }
504       unlock_reservations();
505       if (!ok) {
506          /*
507           * If we get here, there are no suitable devices available, which
508           *  means nothing configured.  If a device is suitable but busy
509           *  with another Volume, we will not come here.
510           */
511          unbash_spaces(dir->msg);
512          pm_strcpy(jcr->errmsg, dir->msg);
513          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
514          Jmsg(jcr, M_FATAL, 0, _("\n"
515             "     Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
516               dev_name.c_str(), media_type.c_str());
517          bnet_fsend(dir, NO_device, dev_name.c_str());
518
519          Dmsg1(100, ">dird: %s", dir->msg);
520       }
521    } else {
522       unbash_spaces(dir->msg);
523       pm_strcpy(jcr->errmsg, dir->msg);
524       Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
525       bnet_fsend(dir, BAD_use, jcr->errmsg);
526       Dmsg1(100, ">dird: %s", dir->msg);
527    }
528
529    release_msgs(jcr);
530    return ok;
531 }
532
533 void release_msgs(JCR *jcr)
534 {
535    alist *msgs = jcr->reserve_msgs;
536    char *msg;
537
538    if (!msgs) {
539       return;
540    }
541    lock_reservations();
542    while ((msg = (char *)msgs->pop())) {
543       free(msg);
544    }
545    delete msgs;
546    jcr->reserve_msgs = NULL;
547    unlock_reservations();
548 }
549
550 /*
551  * Search for a device suitable for this job.
552  */
553 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
554 {
555    bool ok;
556    DIRSTORE *store;
557    char *device_name;
558    alist *dirstore;
559
560    if (rctx.append) {
561       dirstore = jcr->write_store;
562    } else {
563       dirstore = jcr->read_store;
564    }
565    /* 
566     * For each storage device that the user specified, we
567     *  search and see if there is a resource for that device.
568     */
569    Dmsg4(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
570       rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
571       rctx.autochanger_only);
572    ok = false;
573    foreach_alist(store, dirstore) {
574       rctx.store = store;
575       foreach_alist(device_name, store->device) {
576          int stat;
577          rctx.device_name = device_name;
578          stat = search_res_for_device(rctx); 
579          if (stat == 1) {             /* found available device */
580             Dmsg1(100, "Suitable device found=%s\n", device_name);
581             ok = true;
582             break;
583          } else if (stat == 0) {      /* device busy */
584             Dmsg1(110, "Suitable device found=%s, not used: busy\n", device_name);
585          } else {
586             /* otherwise error */
587             Dmsg0(110, "No suitable device found.\n");
588          }
589       }
590       if (ok) {
591          break;
592       }
593    }
594
595    return ok;
596 }
597
598 /*
599  * Search for a particular storage device with particular storage
600  *  characteristics (MediaType).
601  */
602 int search_res_for_device(RCTX &rctx) 
603 {
604    AUTOCHANGER *changer;
605    BSOCK *dir = rctx.jcr->dir_bsock;
606    bool ok;
607    int stat;
608
609    Dmsg1(110, "Search res for %s\n", rctx.device_name);
610    /* Look through Autochangers first */
611    foreach_res(changer, R_AUTOCHANGER) {
612       Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
613       /* Find resource, and make sure we were able to open it */
614       if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
615          /* Try each device in this AutoChanger */
616          foreach_alist(rctx.device, changer->device) {
617             Dmsg1(110, "Try changer device %s\n", rctx.device->hdr.name);
618             stat = reserve_device(rctx);
619             if (stat != 1) {             /* try another device */
620                continue;
621             }
622             POOL_MEM dev_name;
623             if (rctx.store->append == SD_APPEND) {
624                Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
625                   rctx.jcr->dcr->dev->reserved_device);
626             } else {
627                Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
628                   rctx.jcr->read_dcr->dev->reserved_device);
629             }
630             if (rctx.notify_dir) {
631                pm_strcpy(dev_name, rctx.device->hdr.name);
632                bash_spaces(dev_name);
633                ok = bnet_fsend(dir, OK_device, dev_name.c_str());  /* Return real device name */
634                Dmsg1(100, ">dird changer: %s", dir->msg);
635             } else {
636                ok = true;
637             }
638             return ok ? 1 : -1;
639          }
640       }
641    }
642
643    /* Now if requested look through regular devices */
644    if (!rctx.autochanger_only) {
645       foreach_res(rctx.device, R_DEVICE) {
646          Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
647          /* Find resource, and make sure we were able to open it */
648          if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
649             stat = reserve_device(rctx);
650             if (stat != 1) {
651                return stat;
652             }
653             if (rctx.notify_dir) {
654                bash_spaces(rctx.device_name);
655                ok = bnet_fsend(dir, OK_device, rctx.device_name);
656                Dmsg1(100, ">dird dev: %s", dir->msg);
657             } else {
658                ok = true;
659             }
660             return ok ? 1 : -1;
661          }
662       }
663    }
664    return -1;                    /* nothing found */
665 }
666
667 /*
668  *  Try to reserve a specific device.
669  *
670  *  Returns: 1 -- OK, have DCR
671  *           0 -- must wait
672  *          -1 -- fatal error
673  */
674 static int reserve_device(RCTX &rctx)
675 {
676    bool ok;
677    DCR *dcr;
678    const int name_len = MAX_NAME_LENGTH;
679
680    /* Make sure MediaType is OK */
681    Dmsg2(110, "MediaType device=%s request=%s\n",
682          rctx.device->media_type, rctx.store->media_type);
683    if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
684       return -1;
685    }
686
687    /* Make sure device exists -- i.e. we can stat() it */
688    if (!rctx.device->dev) {
689       rctx.device->dev = init_dev(rctx.jcr, rctx.device);
690    }
691    if (!rctx.device->dev) {
692       if (rctx.device->changer_res) {
693         Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
694            "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
695              rctx.device->hdr.name, rctx.device_name);
696       } else {
697          Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
698             "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
699               rctx.device_name);
700       }
701       return -1;  /* no use waiting */
702    }  
703
704    rctx.suitable_device = true;
705    Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
706          rctx.jcr->JobId);
707    dcr = new_dcr(rctx.jcr, rctx.device->dev);
708    if (!dcr) {
709       BSOCK *dir = rctx.jcr->dir_bsock;
710       bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
711       Dmsg1(100, ">dird: %s", dir->msg);
712       return -1;
713    }
714    bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
715    bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
716    bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
717    bstrncpy(dcr->dev_name, rctx.device_name, name_len);
718    if (rctx.store->append == SD_APPEND) {
719       if (rctx.exact_match && !rctx.have_volume) {
720          dcr->any_volume = true;
721          if (dir_find_next_appendable_volume(dcr)) {
722             bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
723             Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
724             rctx.have_volume = true;
725          } else {
726             Dmsg0(100, "No next volume found\n");
727             rctx.VolumeName[0] = 0;
728         }
729       }
730       ok = reserve_device_for_append(dcr, rctx);
731       if (ok) {
732          rctx.jcr->dcr = dcr;
733          Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
734                dcr->dev->reserved_device,
735                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
736       }
737    } else {
738       ok = reserve_device_for_read(dcr);
739       if (ok) {
740          rctx.jcr->read_dcr = dcr;
741          Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
742                dcr->dev->reserved_device,
743                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
744       }
745    }
746    if (!ok) {
747       free_dcr(dcr);
748       Dmsg0(110, "Not OK.\n");
749       return 0;
750    }
751    return 1;
752 }
753
754 /*
755  * We "reserve" the drive by setting the ST_READ bit. No one else
756  *  should touch the drive until that is cleared.
757  *  This allows the DIR to "reserve" the device before actually
758  *  starting the job. 
759  */
760 static bool reserve_device_for_read(DCR *dcr)
761 {
762    DEVICE *dev = dcr->dev;
763    JCR *jcr = dcr->jcr;
764    bool ok = false;
765
766    ASSERT(dcr);
767
768    /* Get locks in correct order */
769    unlock_reservations();
770    P(dev->mutex);
771    lock_reservations();
772
773    if (is_device_unmounted(dev)) {             
774       Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
775       Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
776            jcr->JobId, dev->print_name());
777       queue_reserve_message(jcr);
778       goto bail_out;
779    }
780
781    if (dev->is_busy()) {
782       Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
783          dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
784       Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
785             jcr->JobId, dev->print_name());
786       queue_reserve_message(jcr);
787       goto bail_out;
788    }
789
790    dev->clear_append();
791    dev->set_read();
792    ok = true;
793    dev->reserved_device++;
794    Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
795       dev->print_name(), dev);
796    dcr->reserved_device = true;
797
798 bail_out:
799    V(dev->mutex);
800    return ok;
801 }
802
803
804 /*
805  * We reserve the device for appending by incrementing the 
806  *  reserved_device. We do virtually all the same work that
807  *  is done in acquire_device_for_append(), but we do
808  *  not attempt to mount the device. This routine allows
809  *  the DIR to reserve multiple devices before *really* 
810  *  starting the job. It also permits the SD to refuse 
811  *  certain devices (not up, ...).
812  *
813  * Note, in reserving a device, if the device is for the
814  *  same pool and the same pool type, then it is acceptable.
815  *  The Media Type has already been checked. If we are
816  *  the first tor reserve the device, we put the pool
817  *  name and pool type in the device record.
818  */
819 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
820 {
821    JCR *jcr = dcr->jcr;
822    DEVICE *dev = dcr->dev;
823    bool ok = false;
824
825    ASSERT(dcr);
826
827    /* Get locks in correct order */
828    unlock_reservations();
829    P(dev->mutex);
830    lock_reservations();
831
832    /* If device is being read, we cannot write it */
833    if (dev->can_read()) {
834       Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"), 
835          jcr->JobId, dev->print_name());
836       Dmsg1(110, "%s", jcr->errmsg);
837       queue_reserve_message(jcr);
838       goto bail_out;
839    }
840
841    /* If device is unmounted, we are out of luck */
842    if (is_device_unmounted(dev)) {
843       Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"), 
844          jcr->JobId, dev->print_name());
845       Dmsg1(110, "%s", jcr->errmsg);
846       queue_reserve_message(jcr);
847       goto bail_out;
848    }
849
850    Dmsg1(110, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
851
852    /* Now do detailed tests ... */
853    if (can_reserve_drive(dcr, rctx) != 1) {
854       Dmsg0(110, "can_reserve_drive!=1\n");
855       goto bail_out;
856    }
857
858    dev->reserved_device++;
859    Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
860       dev->print_name(), dev);
861    dcr->reserved_device = true;
862    ok = true;
863
864 bail_out:
865    V(dev->mutex);
866    return ok;
867 }
868
869 /*
870  * Returns: 1 if drive can be reserved
871  *          0 if we should wait
872  *         -1 on error or impossibility
873  */
874 static int can_reserve_drive(DCR *dcr, RCTX &rctx) 
875 {
876    DEVICE *dev = dcr->dev;
877    JCR *jcr = dcr->jcr;
878
879    Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
880          rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
881          rctx.autochanger_only, rctx.any_drive);
882
883    /* setting any_drive overrides PreferMountedVols flag */
884    if (!rctx.any_drive) {
885       /*
886        * When PreferMountedVols is set, we keep track of the 
887        *  drive in use that has the least number of writers, then if
888        *  no unmounted drive is found, we try that drive. This   
889        *  helps spread the load to the least used drives.  
890        */
891       if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
892          Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
893             dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
894          return 1;
895       }
896       /* If he wants a free drive, but this one is busy, no go */
897       if (!rctx.PreferMountedVols && dev->is_busy()) {
898          /* Save least used drive */
899          if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
900             rctx.num_writers = dev->num_writers + dev->reserved_device;
901             rctx.low_use_drive = dev;
902             Dmsg2(110, "set low use drive=%s num_writers=%d\n", dev->print_name(),
903                rctx.num_writers);
904          } else {
905             Dmsg1(110, "not low use num_writers=%d\n", dev->num_writers+ 
906                dev->reserved_device);
907          }
908          Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
909          Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"), 
910             jcr->JobId, dev->print_name());
911          queue_reserve_message(jcr);
912          return 0;
913       }
914
915       /* Check for prefer mounted volumes */
916       if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
917          Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"), 
918             jcr->JobId, dev->print_name());
919          queue_reserve_message(jcr);
920          Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
921          return 0;                 /* No volume mounted */
922       }
923
924       /* Check for exact Volume name match */
925       if (rctx.exact_match && rctx.have_volume &&
926           strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
927          Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"), 
928             jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName, 
929             dev->print_name());
930          queue_reserve_message(jcr);
931          Dmsg2(110, "failed: Not exact match have=%s want=%s\n",
932                dev->VolHdr.VolumeName, rctx.VolumeName);
933          return 0;
934       }
935    }
936
937    /* Check for unused autochanger drive */
938    if (rctx.autochanger_only && dev->num_writers == 0 &&
939        dev->VolHdr.VolumeName[0] == 0) {
940       /* Device is available but not yet reserved, reserve it for us */
941       Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
942          dev->print_name(), jcr->JobId);
943       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
944       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
945       return 1;                       /* reserve drive */
946    }
947
948    /*
949     * Handle the case that there are no writers
950     */
951    if (dev->num_writers == 0) {
952       /* Now check if there are any reservations on the drive */
953       if (dev->reserved_device) {           
954          /* Now check if we want the same Pool and pool type */
955          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
956              strcmp(dev->pool_type, dcr->pool_type) == 0) {
957             /* OK, compatible device */
958             Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
959                dev->print_name(), jcr->JobId);
960             return 1;
961          } else {
962             /* Drive Pool not suitable for us */
963             Mmsg(jcr->errmsg, _("3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"), 
964                   jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
965             queue_reserve_message(jcr);
966             Dmsg2(110, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
967                dev->pool_name, dcr->pool_name);
968             return 0;                 /* wait */
969          }
970       } else if (dev->can_append()) {
971          /* Device in append mode, check if changing pool */
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             /* Changing pool, unload old tape if any in drive */
980             Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
981             unload_autochanger(dcr, 0);
982          }
983       }
984       /* Device is available but not yet reserved, reserve it for us */
985       Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
986          jcr->JobId);
987       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
988       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
989       return 1;                       /* reserve drive */
990    }
991
992    /*
993     * Check if the device is in append mode with writers (i.e.
994     *  available if pool is the same).
995     */
996    if (dev->can_append() || dev->num_writers > 0) {
997       /* Yes, now check if we want the same Pool and pool type */
998       if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
999           strcmp(dev->pool_type, dcr->pool_type) == 0) {
1000          Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
1001             dev->print_name(), jcr->JobId);
1002          /* OK, compatible device */
1003          return 1;
1004       } else {
1005          /* Drive Pool not suitable for us */
1006          Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"), 
1007                jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
1008          queue_reserve_message(jcr);
1009          Dmsg2(110, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
1010             dev->pool_name, dcr->pool_name);
1011          return 0;                    /* wait */
1012       }
1013    } else {
1014       Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
1015       Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1016             jcr->JobId, dev->print_name());
1017       queue_reserve_message(jcr);
1018       Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1019       return -1;                      /* error, should not get here */
1020    }
1021    Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"), 
1022          jcr->JobId, dev->print_name());
1023    queue_reserve_message(jcr);
1024    Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1025    return 0;
1026 }
1027
1028 /*
1029  * search_lock is already set on entering this routine 
1030  */
1031 static void queue_reserve_message(JCR *jcr)
1032 {
1033    int i;   
1034    alist *msgs = jcr->reserve_msgs;
1035    char *msg;
1036
1037    if (!msgs) {
1038       return;
1039    }
1040    /*
1041     * Look for duplicate message.  If found, do
1042     * not insert
1043     */
1044    for (i=msgs->size()-1; i >= 0; i--) {
1045       msg = (char *)msgs->get(i);
1046       if (!msg) {
1047          return;
1048       }
1049       /* Comparison based on 4 digit message number */
1050       if (strncmp(msg, jcr->errmsg, 4) == 0) {
1051          return;
1052       }
1053    }      
1054    /* Message unique, so insert it */
1055    jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1056 }
1057
1058 /*
1059  * Send any reservation messages queued for this jcr
1060  */
1061 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1062 {
1063    int i;
1064    alist *msgs;
1065    char *msg;
1066
1067    lock_reservations();
1068    msgs = jcr->reserve_msgs;
1069    if (!msgs || msgs->size() == 0) {
1070       unlock_reservations();
1071       return;
1072    }
1073    for (i=msgs->size()-1; i >= 0; i--) {
1074       msg = (char *)msgs->get(i);
1075       if (msg) {
1076          sendit("   ", 3, arg);
1077          sendit(msg, strlen(msg), arg);
1078       } else {
1079          break;
1080       }
1081    }
1082    unlock_reservations();
1083 }