]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/device.c
- Simplify code in askdir.c that waits for creating an appendable
[bacula/bacula] / bacula / src / stored / device.c
1 /*
2  *
3  *  Higher Level Device routines.
4  *  Knows about Bacula tape labels and such
5  *
6  *  NOTE! In general, subroutines that have the word
7  *        "device" in the name do locking.  Subroutines
8  *        that have the word "dev" in the name do not
9  *        do locking.  Thus if xxx_device() calls
10  *        yyy_dev(), all is OK, but if xxx_device()
11  *        calls yyy_device(), everything will hang.
12  *        Obviously, no zzz_dev() is allowed to call
13  *        a www_device() or everything falls apart.
14  *
15  * Concerning the routines lock_device() and block_device()
16  *  see the end of this module for details.  In general,
17  *  blocking a device leaves it in a state where all threads
18  *  other than the current thread block when they attempt to
19  *  lock the device. They remain suspended (blocked) until the device
20  *  is unblocked. So, a device is blocked during an operation
21  *  that takes a long time (initialization, mounting a new
22  *  volume, ...) locking a device is done for an operation
23  *  that takes a short time such as writing data to the
24  *  device.
25  *
26  *
27  *   Kern Sibbald, MM, MMI
28  *
29  *   Version $Id$
30  */
31 /*
32    Copyright (C) 2000-2005 Kern Sibbald
33
34    This program is free software; you can redistribute it and/or
35    modify it under the terms of the GNU General Public License
36    version 2 as amended with additional clauses defined in the
37    file LICENSE in the main source directory.
38
39    This program is distributed in the hope that it will be useful,
40    but WITHOUT ANY WARRANTY; without even the implied warranty of
41    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
42    the file LICENSE for additional details.
43
44  */
45
46 #include "bacula.h"                   /* pull in global headers */
47 #include "stored.h"                   /* pull in Storage Deamon headers */
48
49 /* Forward referenced functions */
50
51 extern char my_name[];
52 extern int debug_level;
53
54 /*
55  * This is the dreaded moment. We either have an end of
56  * medium condition or worse, and error condition.
57  * Attempt to "recover" by obtaining a new Volume.
58  *
59  * Here are a few things to know:
60  *  dcr->VolCatInfo contains the info on the "current" tape for this job.
61  *  dev->VolCatInfo contains the info on the tape in the drive.
62  *    The tape in the drive could have changed several times since
63  *    the last time the job used it (jcr->VolCatInfo).
64  *  dcr->VolumeName is the name of the current/desired tape in the drive.
65  *
66  * We enter with device locked, and
67  *     exit with device locked.
68  *
69  * Note, we are called only from one place in block.c
70  *
71  *  Returns: true  on success
72  *           false on failure
73  */
74 bool fixup_device_block_write_error(DCR *dcr)
75 {
76    char PrevVolName[MAX_NAME_LENGTH];
77    DEV_BLOCK *label_blk;
78    DEV_BLOCK *block = dcr->block;
79    char b1[30], b2[30];
80    time_t wait_time;
81    char dt[MAX_TIME_LENGTH];
82    JCR *jcr = dcr->jcr;
83    DEVICE *dev = dcr->dev;
84
85    wait_time = time(NULL);
86
87    Dmsg0(100, "Enter fixup_device_block_write_error\n");
88
89    block_device(dev, BST_DOING_ACQUIRE);
90    /* Unlock, but leave BLOCKED */
91    unlock_device(dev);
92
93    bstrncpy(PrevVolName, dev->VolCatInfo.VolCatName, sizeof(PrevVolName));
94    bstrncpy(dev->VolHdr.PrevVolumeName, PrevVolName, sizeof(dev->VolHdr.PrevVolumeName));
95
96    label_blk = new_block(dev);
97    dcr->block = label_blk;
98
99    /* Inform User about end of medium */
100    Jmsg(jcr, M_INFO, 0, _("End of medium on Volume \"%s\" Bytes=%s Blocks=%s at %s.\n"),
101         PrevVolName, edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
102         edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
103         bstrftime(dt, sizeof(dt), time(NULL)));
104
105    if (!mount_next_write_volume(dcr, 1)) {
106       free_block(label_blk);
107       dcr->block = block;
108       P(dev->mutex);
109       unblock_device(dev);
110       return false;                /* device locked */
111    }
112    P(dev->mutex);                  /* lock again */
113
114    Jmsg(jcr, M_INFO, 0, _("New volume \"%s\" mounted on device %s at %s.\n"),
115       dcr->VolumeName, dev->print_name(), bstrftime(dt, sizeof(dt), time(NULL)));
116
117    /*
118     * If this is a new tape, the label_blk will contain the
119     *  label, so write it now. If this is a previously
120     *  used tape, mount_next_write_volume() will return an
121     *  empty label_blk, and nothing will be written.
122     */
123    Dmsg0(190, "write label block to dev\n");
124    if (!write_block_to_dev(dcr)) {
125       berrno be;
126       Pmsg1(0, _("write_block_to_device Volume label failed. ERR=%s"),
127         be.strerror(dev->dev_errno));
128       free_block(label_blk);
129       dcr->block = block;
130       unblock_device(dev);
131       return false;                /* device locked */
132    }
133    free_block(label_blk);
134    dcr->block = block;
135
136    /*
137     * Walk through all attached jcrs indicating the volume has changed
138     */
139    Dmsg1(100, "Walk attached dcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
140    DCR *mdcr;
141    foreach_dlist(mdcr, dev->attached_dcrs) {
142       JCR *mjcr = mdcr->jcr;
143       if (mjcr->JobId == 0) {
144          continue;                 /* ignore console */
145       }
146       mdcr->NewVol = true;
147       if (jcr != mjcr) {
148          bstrncpy(mdcr->VolumeName, dcr->VolumeName, sizeof(mdcr->VolumeName));
149       }
150    }
151
152    /* Clear NewVol now because dir_get_volume_info() already done */
153    jcr->dcr->NewVol = false;
154    set_new_volume_parameters(dcr);
155
156    jcr->run_time += time(NULL) - wait_time; /* correct run time for mount wait */
157
158    /* Write overflow block to device */
159    Dmsg0(190, "Write overflow block to dev\n");
160    if (!write_block_to_dev(dcr)) {
161       berrno be;
162       Pmsg1(0, _("write_block_to_device overflow block failed. ERR=%s"),
163         be.strerror(dev->dev_errno));
164       unblock_device(dev);
165       return false;                /* device locked */
166    }
167
168    unblock_device(dev);
169    return true;                             /* device locked */
170 }
171
172 /*
173  * We have a new Volume mounted, so reset the Volume parameters
174  *  concerning this job.  The global changes were made earlier
175  *  in the dev structure.
176  */
177 void set_new_volume_parameters(DCR *dcr)
178 {
179    JCR *jcr = dcr->jcr;
180    DEVICE *dev = dcr->dev;
181    if (dcr->NewVol && !dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
182       Jmsg1(jcr, M_ERROR, 0, "%s", jcr->errmsg);
183    }
184    /* Set new start/end positions */
185    if (dev->is_tape()) {
186       dcr->StartBlock = dev->block_num;
187       dcr->StartFile = dev->file;
188    } else {
189       dcr->StartBlock = (uint32_t)dev->file_addr;
190       dcr->StartFile  = (uint32_t)(dev->file_addr >> 32);
191    }
192    /* Reset indicies */
193    dcr->VolFirstIndex = 0;
194    dcr->VolLastIndex = 0;
195    jcr->NumVolumes++;
196    dcr->NewVol = false;
197    dcr->WroteVol = false;
198 }
199
200 /*
201  * We are now in a new Volume file, so reset the Volume parameters
202  *  concerning this job.  The global changes were made earlier
203  *  in the dev structure.
204  */
205 void set_new_file_parameters(DCR *dcr)
206 {
207    DEVICE *dev = dcr->dev;
208
209    /* Set new start/end positions */
210    if (dev->is_tape()) {
211       dcr->StartBlock = dev->block_num;
212       dcr->StartFile = dev->file;
213    } else {
214       dcr->StartBlock = (uint32_t)dev->file_addr;
215       dcr->StartFile  = (uint32_t)(dev->file_addr >> 32);
216    }
217    /* Reset indicies */
218    dcr->VolFirstIndex = 0;
219    dcr->VolLastIndex = 0;
220    dcr->NewFile = false;
221    dcr->WroteVol = false;
222 }
223
224
225
226 /*
227  *   First Open of the device. Expect dev to already be initialized.
228  *
229  *   This routine is used only when the Storage daemon starts
230  *   and always_open is set, and in the stand-alone utility
231  *   routines such as bextract.
232  *
233  *   Note, opening of a normal file is deferred to later so
234  *    that we can get the filename; the device_name for
235  *    a file is the directory only.
236  *
237  *   Returns: false on failure
238  *            true  on success
239  */
240 bool first_open_device(DCR *dcr)
241 {
242    DEVICE *dev = dcr->dev;
243    bool ok = true;
244
245    Dmsg0(120, "start open_output_device()\n");
246    if (!dev) {
247       return false;
248    }
249
250    lock_device(dev);
251
252    /* Defer opening files */
253    if (!dev->is_tape()) {
254       Dmsg0(129, "Device is file, deferring open.\n");
255       goto bail_out;
256    }
257
258     int mode;
259     if (dev_cap(dev, CAP_STREAM)) {
260        mode = OPEN_WRITE_ONLY;
261     } else {
262        mode = OPEN_READ_ONLY;
263     }
264    Dmsg0(129, "Opening device.\n");
265    if (dev->open(dcr, mode) < 0) {
266       Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
267       ok = false;
268       goto bail_out;
269    }
270    Dmsg1(129, "open dev %s OK\n", dev->print_name());
271
272 bail_out:
273    unlock_device(dev);
274    return ok;
275 }
276
277 /*
278  * Make sure device is open, if not do so
279  */
280 bool open_device(DCR *dcr)
281 {
282    DEVICE *dev = dcr->dev;
283    /* Open device */
284    int mode;
285    if (dev_cap(dev, CAP_STREAM)) {
286       mode = OPEN_WRITE_ONLY;
287    } else {
288       mode = OPEN_READ_WRITE;
289    }
290    if (dev->open(dcr, mode) < 0) {
291       /* If polling, ignore the error */
292       /* If DVD, also ignore the error, very often you cannot open the device
293        * (when there is no DVD, or when the one inserted is a wrong one) */
294       if ((!dev->poll) && (!dev->is_dvd())) {
295          Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"),
296             dev->print_name(), strerror_dev(dev));
297          Pmsg2(000, _("Unable to open archive %s: ERR=%s\n"), 
298             dev->print_name(), strerror_dev(dev));
299       }
300       return false;
301    }
302    return true;
303 }
304
305 /*
306  * Release any Volume attached to this device 
307  *  then close the device.
308  */
309 void close_device(DEVICE *dev)
310 {
311    free_volume(dev);
312    dev->close();
313 }
314
315 /*
316  */
317 void force_close_device(DEVICE *dev)
318 {
319    if (!dev || dev->fd < 0) {
320       return;
321    }
322    Dmsg1(29, "Force close_dev %s\n", dev->print_name());
323    free_volume(dev);
324    dev->close();
325 }
326
327
328 void dev_lock(DEVICE *dev)
329 {
330    int errstat;
331    if ((errstat=rwl_writelock(&dev->lock))) {
332       Emsg1(M_ABORT, 0, _("Device write lock failure. ERR=%s\n"), strerror(errstat));
333    }
334 }
335
336 void dev_unlock(DEVICE *dev)
337 {
338    int errstat;
339    if ((errstat=rwl_writeunlock(&dev->lock))) {
340       Emsg1(M_ABORT, 0, _("Device write unlock failure. ERR=%s\n"), strerror(errstat));
341    }
342 }
343
344 /*
345  * When dev_blocked is set, all threads EXCEPT thread with id no_wait_id
346  * must wait. The no_wait_id thread is out obtaining a new volume
347  * and preparing the label.
348  */
349 void _lock_device(const char *file, int line, DEVICE *dev)
350 {
351    int stat;
352    Dmsg3(500, "lock %d from %s:%d\n", dev->dev_blocked, file, line);
353    P(dev->mutex);
354    if (dev->dev_blocked && !pthread_equal(dev->no_wait_id, pthread_self())) {
355       dev->num_waiting++;             /* indicate that I am waiting */
356       while (dev->dev_blocked) {
357          if ((stat = pthread_cond_wait(&dev->wait, &dev->mutex)) != 0) {
358             V(dev->mutex);
359             Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
360                strerror(stat));
361          }
362       }
363       dev->num_waiting--;             /* no longer waiting */
364    }
365 }
366
367 /*
368  * Check if the device is blocked or not
369  */
370 bool is_device_unmounted(DEVICE *dev)
371 {
372    bool stat;
373    int blocked = dev->dev_blocked;
374    stat = (blocked == BST_UNMOUNTED) ||
375           (blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
376    return stat;
377 }
378
379 void _unlock_device(const char *file, int line, DEVICE *dev)
380 {
381    Dmsg2(500, "unlock from %s:%d\n", file, line);
382    V(dev->mutex);
383 }
384
385 /*
386  * Block all other threads from using the device
387  *  Device must already be locked.  After this call,
388  *  the device is blocked to any thread calling lock_device(),
389  *  but the device is not locked (i.e. no P on device).  Also,
390  *  the current thread can do slip through the lock_device()
391  *  calls without blocking.
392  */
393 void _block_device(const char *file, int line, DEVICE *dev, int state)
394 {
395    Dmsg3(500, "block set %d from %s:%d\n", state, file, line);
396    ASSERT(dev->get_blocked() == BST_NOT_BLOCKED);
397    dev->set_blocked(state);           /* make other threads wait */
398    dev->no_wait_id = pthread_self();  /* allow us to continue */
399 }
400
401
402
403 /*
404  * Unblock the device, and wake up anyone who went to sleep.
405  */
406 void _unblock_device(const char *file, int line, DEVICE *dev)
407 {
408    Dmsg3(500, "unblock %s from %s:%d\n", dev->print_blocked(), file, line);
409    ASSERT(dev->dev_blocked);
410    dev->set_blocked(BST_NOT_BLOCKED);
411    dev->no_wait_id = 0;
412    if (dev->num_waiting > 0) {
413       pthread_cond_broadcast(&dev->wait); /* wake them up */
414    }
415 }
416
417 /*
418  * Enter with device locked and blocked
419  * Exit with device unlocked and blocked by us.
420  */
421 void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state)
422 {
423
424    Dmsg3(400, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
425       file, line);
426    hold->dev_blocked = dev->get_blocked();
427    hold->dev_prev_blocked = dev->dev_prev_blocked;
428    hold->no_wait_id = dev->no_wait_id;
429    dev->set_blocked(state);
430    Dmsg1(400, "steal lock. new=%s\n", dev->print_blocked());
431    dev->no_wait_id = pthread_self();
432    V(dev->mutex);
433 }
434
435 /*
436  * Enter with device blocked by us but not locked
437  * Exit with device locked, and blocked by previous owner
438  */
439 void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold)
440 {
441    Dmsg3(400, "return lock. old=%s from %s:%d\n",
442       dev->print_blocked(), file, line);
443    P(dev->mutex);
444    dev->dev_blocked = hold->dev_blocked;
445    dev->dev_prev_blocked = hold->dev_prev_blocked;
446    dev->no_wait_id = hold->no_wait_id;
447    Dmsg1(400, "return lock. new=%s\n", dev->print_blocked());
448    if (dev->num_waiting > 0) {
449       pthread_cond_broadcast(&dev->wait); /* wake them up */
450    }
451 }