]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/acquire.c
Update doc, default working directory bscan
[bacula/bacula] / bacula / src / stored / acquire.c
1 /*
2  *  Routines to acquire and release a device for read/write
3  *
4  *   Kern Sibbald, August MMII
5  *                            
6  *   Version $Id$
7  */
8 /*
9    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2 of
14    the License, or (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19    General Public License for more details.
20
21    You should have received a copy of the GNU General Public
22    License along with this program; if not, write to the Free
23    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24    MA 02111-1307, USA.
25
26  */
27
28 #include "bacula.h"                   /* pull in global headers */
29 #include "stored.h"                   /* pull in Storage Deamon headers */
30
31
32 /********************************************************************* 
33  * Acquire device for reading.  We permit (for the moment)
34  *  only one reader.  We read the Volume label from the block and
35  *  leave the block pointers just after the label.
36  *
37  *  Returns: 0 if failed for any reason
38  *           1 if successful
39  */
40 int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
41 {
42    int stat = 0;
43    int tape_previously_mounted;
44    VOL_LIST *vol;
45
46    lock_device(dev);
47    block_device(dev, BST_DOING_ACQUIRE);
48    unlock_device(dev);
49
50    tape_previously_mounted = (dev->state & ST_READ) || (dev->state & ST_APPEND);
51
52    if (dev->state & ST_READ || dev->num_writers > 0) {
53       Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy. Job cancelled.\n"), dev_name(dev));
54       goto get_out;
55    }
56
57    /* Find next Volume, if any */
58    vol = jcr->VolList;
59    if (!vol) {
60       Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job cancelled.\n"));
61       goto get_out;
62    }
63    jcr->CurVolume++;
64    for (int i=1; i<jcr->CurVolume; i++) {
65       vol = vol->next;
66    }
67    pm_strcpy(&jcr->VolumeName, vol->VolumeName);
68
69    for (;;) {
70       if (job_cancelled(jcr)) {
71          Mmsg0(&dev->errmsg, _("Job cancelled.\n"));
72          goto get_out;                /* error return */
73       }
74       /*
75        * This code ensures that the device is ready for
76        * reading. If it is a file, it opens it.
77        * If it is a tape, it checks the volume name 
78        */
79       for ( ; !(dev->state & ST_OPENED); ) {
80           Dmsg1(120, "bstored: open vol=%s\n", jcr->VolumeName);
81           if (open_dev(dev, jcr->VolumeName, READ_ONLY) < 0) {
82              Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"), 
83                  dev_name(dev), jcr->VolumeName, strerror_dev(dev));
84              goto get_out;
85           }
86           Dmsg1(129, "open_dev %s OK\n", dev_name(dev));
87       }
88       dev->state &= ~ST_LABEL;           /* force reread of label */
89       Dmsg0(200, "calling read-vol-label\n");
90       switch (read_dev_volume_label(jcr, dev, block)) {
91          case VOL_OK:
92             break;                    /* got it */
93          case VOL_IO_ERROR:
94             /*
95              * Send error message generated by read_dev_volume_label()
96              *  only we really had a tape mounted. This supresses superfluous
97              *  error messages when nothing is mounted.
98              */
99             if (tape_previously_mounted) {
100                Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);                         
101             }
102             goto default_path;
103          default:
104             Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
105 default_path:
106             tape_previously_mounted = 0;
107             Dmsg0(200, "dir_get_volume_info\n");
108             if (!dir_get_volume_info(jcr, 0)) { 
109                Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
110             }
111             Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
112                jcr->VolumeName, jcr->VolCatInfo.Slot);                         
113             if (autoload_device(jcr, dev, 0, NULL)) {
114                continue;
115             }
116             /* Mount a specific volume and no other */
117             Dmsg0(200, "calling dir_ask_sysop\n");
118             if (!dir_ask_sysop_to_mount_volume(jcr, dev)) {
119                goto get_out;          /* error return */
120             }
121             continue;                 /* try reading again */
122       }
123       break;
124    }
125
126    dev->state |= ST_READ;
127    attach_jcr_to_device(dev, jcr);    /* attach jcr to device */
128    stat = 1;                          /* good return */
129    if ((dev->state & ST_TAPE) && vol->start_file > 0) {
130       Dmsg1(200, "====== Got start_file = %d\n", vol->start_file);
131       fsf_dev(dev, vol->start_file);
132    }
133
134 get_out:
135    P(dev->mutex); 
136    unblock_device(dev);
137    V(dev->mutex);
138    return stat;
139 }
140
141 /*
142  * Acquire device for writing. We permit multiple writers.
143  *  If this is the first one, we read the label.
144  *
145  *  Returns: 0 if failed for any reason
146  *           1 if successful
147  */
148 int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
149 {
150    int release = 0;
151    int do_mount = 0;
152    int stat = 0;
153
154    lock_device(dev);
155    block_device(dev, BST_DOING_ACQUIRE);
156    unlock_device(dev);
157    Dmsg1(190, "acquire_append device is %s\n", dev_is_tape(dev)?"tape":"disk");
158
159
160    if (dev->state & ST_APPEND) {
161       /* 
162        * Device already in append mode   
163        *
164        * Check if we have the right Volume mounted   
165        *   OK if current volume info OK
166        *   OK if next volume matches current volume
167        *   otherwise mount desired volume obtained from
168        *    dir_find_next_appendable_volume
169        */
170       strcpy(jcr->VolumeName, dev->VolHdr.VolName);
171       if (!dir_get_volume_info(jcr, 1) ||
172           !(dir_find_next_appendable_volume(jcr) &&
173             strcmp(dev->VolHdr.VolName, jcr->VolumeName) == 0)) { /* wrong tape mounted */
174          if (dev->num_writers != 0) {
175             Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev_name(dev));
176             goto get_out;
177          }
178          /* Wrong tape mounted, release it, then fall through to get correct one */
179          release = 1;
180          do_mount = 1;
181       }
182    } else { 
183       /* Not already in append mode, so mount the device */
184       if (dev->state & ST_READ) {
185          Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev));
186          goto get_out;
187       } 
188       ASSERT(dev->num_writers == 0);
189       do_mount = 1;
190    }
191
192    if (do_mount) {
193       if (!mount_next_write_volume(jcr, dev, block, release)) {
194          Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
195             dev_name(dev));
196          goto get_out;
197       }
198    }
199
200    dev->num_writers++;
201    if (dev->num_writers > 1) {
202       Dmsg2(100, "Hey!!!! There are %d writers on device %s\n", dev->num_writers,
203          dev_name(dev));
204    }
205    if (jcr->NumVolumes == 0) {
206       jcr->NumVolumes = 1;
207    }
208    attach_jcr_to_device(dev, jcr);    /* attach jcr to device */
209    stat = 1;                          /* good return */
210
211 get_out:
212    P(dev->mutex); 
213    unblock_device(dev);
214    V(dev->mutex);
215    return stat;
216 }
217
218 /*
219  * This job is done, so release the device. From a Unix standpoint,
220  *  the device remains open.
221  *
222  */
223 int release_device(JCR *jcr, DEVICE *dev)
224 {
225    lock_device(dev);
226    Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk");
227    if (dev->state & ST_READ) {
228       dev->state &= ~ST_READ;         /* clear read bit */
229       if (!dev_is_tape(dev) || !(dev->capabilities & CAP_ALWAYSOPEN)) {
230          if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
231             offline_dev(dev);
232          }
233          close_dev(dev);
234       }
235       /******FIXME**** send read volume usage statistics to director */
236
237    } else if (dev->num_writers > 0) {
238       dev->num_writers--;
239       if (dev->state & ST_TAPE) {
240          jcr->EndBlock = dev->EndBlock;
241          jcr->EndFile  = dev->EndFile;
242          Dmsg2(200, "Release device: EndFile=%u EndBlock=%u\n", jcr->EndFile, jcr->EndBlock);
243       } else {
244          jcr->EndBlock = (uint32_t)dev->file_addr;
245          jcr->EndFile = (uint32_t)(dev->file_addr >> 32);
246       }
247       Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
248       if (dev->num_writers == 0) {
249          Dmsg0(100, "dir_create_jobmedia_record. Release\n");
250          dir_create_jobmedia_record(jcr);
251          weof_dev(dev, 1);
252          dev->VolCatInfo.VolCatFiles++;             /* increment number of files */
253          dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs */
254          /* Note! do volume update before close, which zaps VolCatInfo */
255          Dmsg0(100, "dir_update_vol_info. Release\n");
256          dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */
257
258          if (!dev_is_tape(dev) || !(dev->capabilities & CAP_ALWAYSOPEN)) {
259             if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
260                offline_dev(dev);
261             }
262             close_dev(dev);
263          }
264       } else {
265          Dmsg0(100, "dir_create_jobmedia_record. Release\n");
266          dir_create_jobmedia_record(jcr);
267          Dmsg0(100, "dir_update_vol_info. Release\n");
268          dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs */
269          dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */
270       }
271    } else {
272       Jmsg2(jcr, M_ERROR, 0, _("BAD ERROR: release_device %s, Volume %s not in use.\n"), 
273             dev_name(dev), NPRT(jcr->VolumeName));
274    }
275    detach_jcr_from_device(dev, jcr);
276    unlock_device(dev);
277    return 1;
278 }