2 * Drive reservation functions for Storage Daemon
6 * Split from job.c and acquire.c June 2005
12 Copyright (C) 2000-2005 Kern Sibbald
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 ammended with additional clauses defined in the
17 file LICENSE in the main source directory.
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.
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.
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.
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];
59 /* Forward referenced functions */
60 static int can_reserve_drive(DCR *dcr);
61 static int search_res_for_device(RCTX &rctx);
62 static int reserve_device(RCTX &rctx);
63 static bool reserve_device_for_read(DCR *dcr);
64 static bool reserve_device_for_append(DCR *dcr);
65 static bool use_storage_cmd(JCR *jcr);
67 /* Requests from the Director daemon */
68 static char use_storage[] = "use storage=%127s media_type=%127s "
69 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
70 static char use_device[] = "use device=%127s\n";
72 /* Responses sent to Director daemon */
73 static char OK_device[] = "3000 OK use device device=%s\n";
74 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
75 static char BAD_use[] = "3913 Bad use command: %s\n";
78 bool use_cmd(JCR *jcr)
81 * Wait for the device, media, and pool information
83 if (!use_storage_cmd(jcr)) {
84 set_jcr_job_status(jcr, JS_ErrorTerminated);
85 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
91 static bool use_storage_cmd(JCR *jcr)
93 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
94 BSOCK *dir = jcr->dir_bsock;
107 * If there are multiple devices, the director sends us
108 * use_device for each device that it wants to use.
110 Dmsg1(100, "<dird: %s", dir->msg);
111 dirstore = New(alist(10, not_owned_by_alist));
113 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
114 media_type.c_str(), pool_name.c_str(),
115 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
119 unbash_spaces(store_name);
120 unbash_spaces(media_type);
121 unbash_spaces(pool_name);
122 unbash_spaces(pool_type);
123 store = new DIRSTORE;
124 dirstore->append(store);
125 memset(store, 0, sizeof(DIRSTORE));
126 store->device = New(alist(10));
127 bstrncpy(store->name, store_name, sizeof(store->name));
128 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
129 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
130 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
131 store->append = append;
133 /* Now get all devices */
134 while (bnet_recv(dir) >= 0) {
135 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
139 unbash_spaces(dev_name);
140 store->device->append(bstrdup(dev_name.c_str()));
142 } while (ok && bnet_recv(dir) >= 0);
145 /* This loop is debug code and can be removed */
146 /* ***FIXME**** remove after 1.38 release */
147 foreach_alist(store, dirstore) {
148 Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n",
149 store->name, store->media_type, store->pool_name,
151 foreach_alist(device_name, store->device) {
152 Dmsg1(100, " Device=%s\n", device_name);
158 * At this point, we have a list of all the Director's Storage
159 * resources indicated for this Job, which include Pool, PoolType,
160 * storage name, and Media type.
161 * Then for each of the Storage resources, we have a list of
162 * device names that were given.
164 * Wiffle through them and find one that can do the backup.
168 init_jcr_device_wait_timers(jcr);
170 int need_wait = false;
171 foreach_alist(store, dirstore) {
173 foreach_alist(device_name, store->device) {
175 rctx.device_name = device_name;
176 stat = search_res_for_device(rctx);
177 if (stat == 1) { /* found available device */
180 dcr->Stripe = Stripe;
183 } else if (stat == 0) { /* device busy */
186 rctx.errors.push(bstrdup(jcr->errmsg));
190 * If there is some device for which we can wait, then
191 * wait and try again until the wait time expires
193 if (!need_wait || !wait_for_device(jcr, first)) {
197 for (error=(char*)rctx.errors.first(); error;
198 error=(char*)rctx.errors.next()) {
203 unbash_spaces(dir->msg);
204 pm_strcpy(jcr->errmsg, dir->msg);
205 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
207 Jmsg(jcr, M_FATAL, 0, _("\n"
208 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
209 dev_name.c_str(), media_type.c_str());
210 bnet_fsend(dir, NO_device, dev_name.c_str());
211 Dmsg1(100, ">dird: %s\n", dir->msg);
214 unbash_spaces(dir->msg);
215 pm_strcpy(jcr->errmsg, dir->msg);
217 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
219 Jmsg(jcr, M_FATAL, 0, _("Could not find an available device.\n"));
220 for (error=(char*)rctx.errors.first(); error;
221 error=(char*)rctx.errors.next()) {
222 Jmsg(jcr, M_INFO, 0, "%s", error);
224 bnet_fsend(dir, BAD_use, jcr->errmsg);
225 Dmsg1(100, ">dird: %s\n", dir->msg);
230 foreach_alist(store, dirstore) {
231 delete store->device;
238 for (error=(char*)rctx.errors.first(); error;
239 error=(char*)rctx.errors.next()) {
246 * Search for a particular storage device with particular storage
247 * characteristics (MediaType).
249 static int search_res_for_device(RCTX &rctx)
251 AUTOCHANGER *changer;
252 BSOCK *dir = rctx.jcr->dir_bsock;
256 Dmsg1(100, "Search res for %s\n", rctx.device_name);
257 foreach_res(rctx.device, R_DEVICE) {
258 Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
259 /* Find resource, and make sure we were able to open it */
260 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0 &&
261 strcmp(rctx.device->media_type, rctx.store->media_type) == 0) {
262 stat = reserve_device(rctx);
266 Dmsg1(220, "Got: %s", dir->msg);
267 bash_spaces(rctx.device_name);
268 ok = bnet_fsend(dir, OK_device, rctx.device_name);
269 Dmsg1(100, ">dird: %s\n", dir->msg);
273 foreach_res(changer, R_AUTOCHANGER) {
274 Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
275 /* Find resource, and make sure we were able to open it */
276 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
277 /* Try each device in this AutoChanger */
278 foreach_alist(rctx.device, changer->device) {
279 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
280 stat = reserve_device(rctx);
281 if (stat == -1) { /* hard error */
284 if (stat == 0) { /* must wait, try next one */
288 Dmsg1(100, "Device %s opened.\n", rctx.device_name);
289 pm_strcpy(dev_name, rctx.device->hdr.name);
290 bash_spaces(dev_name);
291 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
292 Dmsg1(100, ">dird: %s\n", dir->msg);
297 return 0; /* nothing found */
301 * Try to reserve a specific device.
303 * Returns: 1 -- OK, have DCR
307 static int reserve_device(RCTX &rctx)
311 const int name_len = MAX_NAME_LENGTH;
312 if (!rctx.device->dev) {
313 rctx.device->dev = init_dev(rctx.jcr, NULL, rctx.device);
315 if (!rctx.device->dev) {
316 if (dev_cap(rctx.device->dev, CAP_AUTOCHANGER)) {
317 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
318 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
319 rctx.device->hdr.name, rctx.device_name);
321 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
322 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
327 Dmsg1(100, "Found device %s\n", rctx.device->hdr.name);
328 dcr = new_dcr(rctx.jcr, rctx.device->dev);
330 BSOCK *dir = rctx.jcr->dir_bsock;
331 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
332 Dmsg1(100, ">dird: %s\n", dir->msg);
336 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
337 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
338 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
339 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
340 if (rctx.store->append == SD_APPEND) {
341 ok = reserve_device_for_append(dcr);
342 Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
344 ok = reserve_device_for_read(dcr);
347 free_dcr(rctx.jcr->dcr);
354 * We "reserve" the drive by setting the ST_READ bit. No one else
355 * should touch the drive until that is cleared.
356 * This allows the DIR to "reserve" the device before actually
359 static bool reserve_device_for_read(DCR *dcr)
361 DEVICE *dev = dcr->dev;
367 dev->block(BST_DOING_ACQUIRE);
369 if (device_is_unmounted(dev)) {
370 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
371 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
376 if (dev->is_busy()) {
377 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
378 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
379 Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
395 * We reserve the device for appending by incrementing the
396 * reserved_device. We do virtually all the same work that
397 * is done in acquire_device_for_append(), but we do
398 * not attempt to mount the device. This routine allows
399 * the DIR to reserve multiple devices before *really*
400 * starting the job. It also permits the SD to refuse
401 * certain devices (not up, ...).
403 * Note, in reserving a device, if the device is for the
404 * same pool and the same pool type, then it is acceptable.
405 * The Media Type has already been checked. If we are
406 * the first tor reserve the device, we put the pool
407 * name and pool type in the device record.
409 static bool reserve_device_for_append(DCR *dcr)
412 DEVICE *dev = dcr->dev;
417 dev->block(BST_DOING_ACQUIRE);
419 if (dev->can_read()) {
420 Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
424 if (device_is_unmounted(dev)) {
425 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
429 Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
431 if (can_reserve_drive(dcr) != 1) {
432 Mmsg1(jcr->errmsg, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
436 dev->reserved_device++;
437 Dmsg1(200, "============= Inc reserve=%d\n", dev->reserved_device);
438 dcr->reserved_device = true;
447 * Returns: 1 if drive can be reserved
448 * 0 if we should wait
451 static int can_reserve_drive(DCR *dcr)
453 DEVICE *dev = dcr->dev;
456 * First handle the case that the drive is not yet in append mode
458 if (!dev->can_append() && dev->num_writers == 0) {
459 /* Now check if there are any reservations on the drive */
460 if (dev->reserved_device) {
461 /* Yes, now check if we want the same Pool and pool type */
462 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
463 strcmp(dev->pool_type, dcr->pool_type) == 0) {
464 /* OK, compatible device */
466 /* Drive not suitable for us */
470 /* Device is available but not yet reserved, reserve it for us */
471 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
472 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
474 return 1; /* reserve drive */
478 * Check if device in append mode with no writers (i.e. available)
480 if (dev->can_append() && dev->num_writers == 0) {
481 /* Device is available but not yet reserved, reserve it for us */
482 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
483 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
488 * Now check if the device is in append mode with writers (i.e.
489 * available if pool is the same).
491 if (dev->can_append() || dev->num_writers > 0) {
492 Dmsg0(190, "device already in append.\n");
493 /* Yes, now check if we want the same Pool and pool type */
494 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
495 strcmp(dev->pool_type, dcr->pool_type) == 0) {
496 /* OK, compatible device */
498 /* Drive not suitable for us */
499 Jmsg(jcr, M_WARNING, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
503 Pmsg0(000, "Logic error!!!! Should not get here.\n");
504 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
505 return -1; /* error, should not get here */
507 return 1; /* reserve drive */