]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/device.c
Update the Microsoft Visual Studio build to match the MinGW32 build.
[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-2006 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 /*
52  * This is the dreaded moment. We either have an end of
53  * medium condition or worse, and error condition.
54  * Attempt to "recover" by obtaining a new Volume.
55  *
56  * Here are a few things to know:
57  *  dcr->VolCatInfo contains the info on the "current" tape for this job.
58  *  dev->VolCatInfo contains the info on the tape in the drive.
59  *    The tape in the drive could have changed several times since
60  *    the last time the job used it (jcr->VolCatInfo).
61  *  dcr->VolumeName is the name of the current/desired tape in the drive.
62  *
63  * We enter with device locked, and
64  *     exit with device locked.
65  *
66  * Note, we are called only from one place in block.c
67  *
68  *  Returns: true  on success
69  *           false on failure
70  */
71 bool fixup_device_block_write_error(DCR *dcr)
72 {
73    char PrevVolName[MAX_NAME_LENGTH];
74    DEV_BLOCK *label_blk;
75    DEV_BLOCK *block = dcr->block;
76    char b1[30], b2[30];
77    time_t wait_time;
78    char dt[MAX_TIME_LENGTH];
79    JCR *jcr = dcr->jcr;
80    DEVICE *dev = dcr->dev;
81
82    wait_time = time(NULL);
83
84    Dmsg0(100, "Enter fixup_device_block_write_error\n");
85
86    block_device(dev, BST_DOING_ACQUIRE);
87    /* Unlock, but leave BLOCKED */
88    unlock_device(dev);
89
90    bstrncpy(PrevVolName, dev->VolCatInfo.VolCatName, sizeof(PrevVolName));
91    bstrncpy(dev->VolHdr.PrevVolumeName, PrevVolName, sizeof(dev->VolHdr.PrevVolumeName));
92
93    label_blk = new_block(dev);
94    dcr->block = label_blk;
95
96    /* Inform User about end of medium */
97    Jmsg(jcr, M_INFO, 0, _("End of medium on Volume \"%s\" Bytes=%s Blocks=%s at %s.\n"),
98         PrevVolName, edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
99         edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
100         bstrftime(dt, sizeof(dt), time(NULL)));
101
102    if (!mount_next_write_volume(dcr, 1)) {
103       free_block(label_blk);
104       dcr->block = block;
105       P(dev->mutex);
106       unblock_device(dev);
107       return false;                /* device locked */
108    }
109    P(dev->mutex);                  /* lock again */
110
111    Jmsg(jcr, M_INFO, 0, _("New volume \"%s\" mounted on device %s at %s.\n"),
112       dcr->VolumeName, dev->print_name(), bstrftime(dt, sizeof(dt), time(NULL)));
113
114    /*
115     * If this is a new tape, the label_blk will contain the
116     *  label, so write it now. If this is a previously
117     *  used tape, mount_next_write_volume() will return an
118     *  empty label_blk, and nothing will be written.
119     */
120    Dmsg0(190, "write label block to dev\n");
121    if (!write_block_to_dev(dcr)) {
122       berrno be;
123       Pmsg1(0, _("write_block_to_device Volume label failed. ERR=%s"),
124         be.strerror(dev->dev_errno));
125       free_block(label_blk);
126       dcr->block = block;
127       unblock_device(dev);
128       return false;                /* device locked */
129    }
130    free_block(label_blk);
131    dcr->block = block;
132
133    /*
134     * Walk through all attached jcrs indicating the volume has changed
135     */
136    Dmsg1(100, "Walk attached dcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
137    DCR *mdcr;
138    foreach_dlist(mdcr, dev->attached_dcrs) {
139       JCR *mjcr = mdcr->jcr;
140       if (mjcr->JobId == 0) {
141          continue;                 /* ignore console */
142       }
143       mdcr->NewVol = true;
144       if (jcr != mjcr) {
145          bstrncpy(mdcr->VolumeName, dcr->VolumeName, sizeof(mdcr->VolumeName));
146       }
147    }
148
149    /* Clear NewVol now because dir_get_volume_info() already done */
150    jcr->dcr->NewVol = false;
151    set_new_volume_parameters(dcr);
152
153    jcr->run_time += time(NULL) - wait_time; /* correct run time for mount wait */
154
155    /* Write overflow block to device */
156    Dmsg0(190, "Write overflow block to dev\n");
157    if (!write_block_to_dev(dcr)) {
158       berrno be;
159       Pmsg1(0, _("write_block_to_device overflow block failed. ERR=%s"),
160         be.strerror(dev->dev_errno));
161       unblock_device(dev);
162       return false;                /* device locked */
163    }
164
165    unblock_device(dev);
166    return true;                             /* device locked */
167 }
168
169 /*
170  * We have a new Volume mounted, so reset the Volume parameters
171  *  concerning this job.  The global changes were made earlier
172  *  in the dev structure.
173  */
174 void set_new_volume_parameters(DCR *dcr)
175 {
176    JCR *jcr = dcr->jcr;
177    DEVICE *dev = dcr->dev;
178    if (dcr->NewVol && !dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
179       Jmsg1(jcr, M_ERROR, 0, "%s", jcr->errmsg);
180    }
181    /* Set new start/end positions */
182    if (dev->is_tape()) {
183       dcr->StartBlock = dev->block_num;
184       dcr->StartFile = dev->file;
185    } else {
186       dcr->StartBlock = (uint32_t)dev->file_addr;
187       dcr->StartFile  = (uint32_t)(dev->file_addr >> 32);
188    }
189    /* Reset indicies */
190    dcr->VolFirstIndex = 0;
191    dcr->VolLastIndex = 0;
192    jcr->NumVolumes++;
193    dcr->NewVol = false;
194    dcr->WroteVol = false;
195 }
196
197 /*
198  * We are now in a new Volume file, so reset the Volume parameters
199  *  concerning this job.  The global changes were made earlier
200  *  in the dev structure.
201  */
202 void set_new_file_parameters(DCR *dcr)
203 {
204    DEVICE *dev = dcr->dev;
205
206    /* Set new start/end positions */
207    if (dev->is_tape()) {
208       dcr->StartBlock = dev->block_num;
209       dcr->StartFile = dev->file;
210    } else {
211       dcr->StartBlock = (uint32_t)dev->file_addr;
212       dcr->StartFile  = (uint32_t)(dev->file_addr >> 32);
213    }
214    /* Reset indicies */
215    dcr->VolFirstIndex = 0;
216    dcr->VolLastIndex = 0;
217    dcr->NewFile = false;
218    dcr->WroteVol = false;
219 }
220
221
222
223 /*
224  *   First Open of the device. Expect dev to already be initialized.
225  *
226  *   This routine is used only when the Storage daemon starts
227  *   and always_open is set, and in the stand-alone utility
228  *   routines such as bextract.
229  *
230  *   Note, opening of a normal file is deferred to later so
231  *    that we can get the filename; the device_name for
232  *    a file is the directory only.
233  *
234  *   Returns: false on failure
235  *            true  on success
236  */
237 bool first_open_device(DCR *dcr)
238 {
239    DEVICE *dev = dcr->dev;
240    bool ok = true;
241
242    Dmsg0(120, "start open_output_device()\n");
243    if (!dev) {
244       return false;
245    }
246
247    lock_device(dev);
248
249    /* Defer opening files */
250    if (!dev->is_tape()) {
251       Dmsg0(129, "Device is file, deferring open.\n");
252       goto bail_out;
253    }
254
255     int mode;
256     if (dev_cap(dev, CAP_STREAM)) {
257        mode = OPEN_WRITE_ONLY;
258     } else {
259        mode = OPEN_READ_ONLY;
260     }
261    Dmsg0(129, "Opening device.\n");
262    if (dev->open(dcr, mode) < 0) {
263       Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
264       ok = false;
265       goto bail_out;
266    }
267    Dmsg1(129, "open dev %s OK\n", dev->print_name());
268
269 bail_out:
270    unlock_device(dev);
271    return ok;
272 }
273
274 /*
275  * Make sure device is open, if not do so
276  */
277 bool open_device(DCR *dcr)
278 {
279    DEVICE *dev = dcr->dev;
280    /* Open device */
281    int mode;
282    if (dev_cap(dev, CAP_STREAM)) {
283       mode = OPEN_WRITE_ONLY;
284    } else {
285       mode = OPEN_READ_WRITE;
286    }
287    if (dev->open(dcr, mode) < 0) {
288       /* If polling, ignore the error */
289       /* If DVD, also ignore the error, very often you cannot open the device
290        * (when there is no DVD, or when the one inserted is a wrong one) */
291       if (!dev->poll && !dev->is_dvd() && !dev->is_removable()) {
292          Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"),
293             dev->print_name(), dev->bstrerror());
294          Pmsg2(000, _("Unable to open archive %s: ERR=%s\n"), 
295             dev->print_name(), dev->bstrerror());
296       }
297       return false;
298    }
299    return true;
300 }
301
302
303
304 void dev_lock(DEVICE *dev)
305 {
306    int errstat;
307    if ((errstat=rwl_writelock(&dev->lock))) {
308       Emsg1(M_ABORT, 0, _("Device write lock failure. ERR=%s\n"), strerror(errstat));
309    }
310 }
311
312 void dev_unlock(DEVICE *dev)
313 {
314    int errstat;
315    if ((errstat=rwl_writeunlock(&dev->lock))) {
316       Emsg1(M_ABORT, 0, _("Device write unlock failure. ERR=%s\n"), strerror(errstat));
317    }
318 }
319
320 /*
321  * When dev_blocked is set, all threads EXCEPT thread with id no_wait_id
322  * must wait. The no_wait_id thread is out obtaining a new volume
323  * and preparing the label.
324  */
325 void _lock_device(const char *file, int line, DEVICE *dev)
326 {
327    int stat;
328    Dmsg3(500, "lock %d from %s:%d\n", dev->dev_blocked, file, line);
329    P(dev->mutex);
330    if (dev->dev_blocked && !pthread_equal(dev->no_wait_id, pthread_self())) {
331       dev->num_waiting++;             /* indicate that I am waiting */
332       while (dev->dev_blocked) {
333          if ((stat = pthread_cond_wait(&dev->wait, &dev->mutex)) != 0) {
334             V(dev->mutex);
335             Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"),
336                strerror(stat));
337          }
338       }
339       dev->num_waiting--;             /* no longer waiting */
340    }
341 }
342
343 /*
344  * Check if the device is blocked or not
345  */
346 bool is_device_unmounted(DEVICE *dev)
347 {
348    bool stat;
349    int blocked = dev->dev_blocked;
350    stat = (blocked == BST_UNMOUNTED) ||
351           (blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP);
352    return stat;
353 }
354
355 void _unlock_device(const char *file, int line, DEVICE *dev)
356 {
357    Dmsg2(500, "unlock from %s:%d\n", file, line);
358    V(dev->mutex);
359 }
360
361 /*
362  * Block all other threads from using the device
363  *  Device must already be locked.  After this call,
364  *  the device is blocked to any thread calling lock_device(),
365  *  but the device is not locked (i.e. no P on device).  Also,
366  *  the current thread can do slip through the lock_device()
367  *  calls without blocking.
368  */
369 void _block_device(const char *file, int line, DEVICE *dev, int state)
370 {
371    Dmsg3(500, "block set %d from %s:%d\n", state, file, line);
372    ASSERT(dev->get_blocked() == BST_NOT_BLOCKED);
373    dev->set_blocked(state);           /* make other threads wait */
374    dev->no_wait_id = pthread_self();  /* allow us to continue */
375 }
376
377
378
379 /*
380  * Unblock the device, and wake up anyone who went to sleep.
381  */
382 void _unblock_device(const char *file, int line, DEVICE *dev)
383 {
384    Dmsg3(500, "unblock %s from %s:%d\n", dev->print_blocked(), file, line);
385    ASSERT(dev->dev_blocked);
386    dev->set_blocked(BST_NOT_BLOCKED);
387    dev->no_wait_id = 0;
388    if (dev->num_waiting > 0) {
389       pthread_cond_broadcast(&dev->wait); /* wake them up */
390    }
391 }
392
393 /*
394  * Enter with device locked and blocked
395  * Exit with device unlocked and blocked by us.
396  */
397 void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state)
398 {
399
400    Dmsg3(400, "steal lock. old=%s from %s:%d\n", dev->print_blocked(),
401       file, line);
402    hold->dev_blocked = dev->get_blocked();
403    hold->dev_prev_blocked = dev->dev_prev_blocked;
404    hold->no_wait_id = dev->no_wait_id;
405    dev->set_blocked(state);
406    Dmsg1(400, "steal lock. new=%s\n", dev->print_blocked());
407    dev->no_wait_id = pthread_self();
408    V(dev->mutex);
409 }
410
411 /*
412  * Enter with device blocked by us but not locked
413  * Exit with device locked, and blocked by previous owner
414  */
415 void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold)
416 {
417    Dmsg3(400, "return lock. old=%s from %s:%d\n",
418       dev->print_blocked(), file, line);
419    P(dev->mutex);
420    dev->dev_blocked = hold->dev_blocked;
421    dev->dev_prev_blocked = hold->dev_prev_blocked;
422    dev->no_wait_id = hold->no_wait_id;
423    Dmsg1(400, "return lock. new=%s\n", dev->print_blocked());
424    if (dev->num_waiting > 0) {
425       pthread_cond_broadcast(&dev->wait); /* wake them up */
426    }
427 }