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