]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/acquire.c
8ec4bb3766c0add199a05f97e991ec5bc6b0b209
[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;
43
44    lock_device(dev);
45    if (dev->state & ST_READ || dev->num_writers > 0) {
46       Jmsg(jcr, M_FATAL, 0, _("Device %s is busy.\n"), dev_name(dev));
47       unlock_device(dev);
48       return 0;
49    }
50    dev->state &= ~ST_LABEL;           /* force reread of label */
51    block_device(dev, BST_DOING_ACQUIRE);
52    unlock_device(dev);
53    stat = ready_dev_for_read(jcr, dev, block);  
54    P(dev->mutex); 
55    unblock_device(dev);
56    V(dev->mutex);
57    return stat;
58 }
59
60 /*
61  * Acquire device for writing. We permit multiple writers.
62  *  If this is the first one, we read the label.
63  *
64  *  Returns: 0 if failed for any reason
65  *           1 if successful
66  */
67 int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
68 {
69    int release = 0;
70    int do_mount = 0;
71
72    lock_device(dev);
73    Dmsg1(190, "acquire_append device is %s\n", dev_is_tape(dev)?"tape":"disk");
74
75
76    if (dev->state & ST_APPEND) {
77       /* 
78        * Device already in append mode   
79        *
80        * Check if we have the right Volume mounted   
81        *  OK if AnonVols and volume info OK
82        *  OK if next volume matches current volume
83        *  otherwise mount desired volume obtained from
84        *    dir_find_next_appendable_volume
85        */
86       strcpy(jcr->VolumeName, dev->VolHdr.VolName);
87       if (((dev->capabilities & CAP_ANONVOLS) &&
88             !dir_get_volume_info(jcr)) ||
89           (!dir_find_next_appendable_volume(jcr) || 
90             strcmp(dev->VolHdr.VolName, jcr->VolumeName) != 0)) { /* wrong tape mounted */
91          if (dev->num_writers != 0) {
92             Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing with another Volume.\n"), dev_name(dev));
93             unlock_device(dev);
94             return 0;
95          }
96          /* Wrong tape mounted, release it, then fall through to get correct one */
97          release = 1;
98          do_mount = 1;
99       }
100    } else { 
101       /* Not already in append mode, so mount the device */
102       if (dev->state & ST_READ) {
103          Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev));
104          unlock_device(dev);
105          return 0;
106       } 
107       ASSERT(dev->num_writers == 0);
108       do_mount = 1;
109    }
110
111    if (do_mount) {
112       block_device(dev, BST_DOING_ACQUIRE);
113       unlock_device(dev);
114       if (!mount_next_write_volume(jcr, dev, block, release)) {
115          Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
116             dev_name(dev));
117          P(dev->mutex);
118          unblock_device(dev);
119          unlock_device(dev);
120          return 0;
121       }
122       P(dev->mutex);
123       unblock_device(dev);
124    }
125
126    dev->num_writers++;
127    if (dev->num_writers > 1) {
128       Dmsg2(0, "Hey!!!! There are %d writers on device %s\n", dev->num_writers,
129          dev_name(dev));
130    }
131    if (jcr->NumVolumes == 0) {
132       jcr->NumVolumes = 1;
133    }
134    attach_jcr_to_device(dev, jcr);    /* attach jcr to device */
135    unlock_device(dev);
136    return 1;                          /* got it */
137 }
138
139 /*
140  * This job is done, so release the device. From a Unix standpoint,
141  *  the device remains open.
142  *
143  */
144 int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
145 {
146    P(dev->mutex);
147    Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk");
148    if (dev->state & ST_READ) {
149       dev->state &= ~ST_READ;         /* clear read bit */
150       if (!dev_is_tape(dev) || !(dev->capabilities & CAP_ALWAYSOPEN)) {
151          if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
152             offline_dev(dev);
153          }
154          close_dev(dev);
155       }
156       /******FIXME**** send read volume usage statistics to director */
157
158    } else if (dev->num_writers > 0) {
159       dev->num_writers--;
160       Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
161       if (dev->num_writers == 0) {
162          weof_dev(dev, 1);
163          Dmsg0(100, "dir_create_jobmedia_record. Release\n");
164          dir_create_jobmedia_record(jcr);
165          dev->VolCatInfo.VolCatFiles++;             /* increment number of files */
166          /* Note! do volume update before close, which zaps VolCatInfo */
167          Dmsg0(100, "dir_update_vol_info. Release\n");
168          dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */
169
170          if (!dev_is_tape(dev) || !(dev->capabilities & CAP_ALWAYSOPEN)) {
171             if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
172                offline_dev(dev);
173             }
174             close_dev(dev);
175          }
176       } else {
177          Dmsg0(100, "dir_create_jobmedia_record. Release\n");
178          dir_create_jobmedia_record(jcr);
179          Dmsg0(100, "dir_update_vol_info. Release\n");
180          dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */
181       }
182    } else {
183       Jmsg1(jcr, M_ERROR, 0, _("BAD ERROR: release_device %s not in use.\n"), dev_name(dev));
184    }
185    detach_jcr_from_device(dev, jcr);
186    V(dev->mutex);
187    return 1;
188 }
189
190
191
192 /*
193  * This routine ensures that the device is ready for
194  * reading. If it is a file, it opens it.
195  * If it is a tape, it checks the volume name 
196  *
197  *  Returns 0 on failure
198  *  Returns 1 on success
199  */
200 int ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
201 {
202    if (!(dev->state & ST_OPENED)) {
203        Dmsg1(120, "bstored: open vol=%s\n", jcr->VolumeName);
204        if (open_dev(dev, jcr->VolumeName, READ_ONLY) < 0) {
205           Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"), 
206               dev_name(dev), jcr->VolumeName, strerror_dev(dev));
207           return 0;
208        }
209        Dmsg1(129, "open_dev %s OK\n", dev_name(dev));
210    }
211
212    for (;;) {
213       if (job_cancelled(jcr)) {
214          Mmsg0(&dev->errmsg, _("Job cancelled.\n"));
215          return 0;
216       }
217       if (!rewind_dev(dev)) {
218          Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device %s. ERR=%s\n"), 
219                dev_name(dev), strerror_dev(dev));
220       }
221       switch (read_dev_volume_label(jcr, dev, block)) {
222          case VOL_OK:
223             break;                    /* got it */
224          default:
225             /* Send error message generated by read_dev_volume_label() */
226             Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);                         
227             if (!rewind_dev(dev)) {
228                Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device %s. ERR=%s\n"), 
229                      dev_name(dev), strerror_dev(dev));
230             }
231             /* Mount a specific volume and no other */
232             if (!dir_ask_sysop_to_mount_volume(jcr, dev)) {
233                return 0;              /* error return */
234             }
235             continue;                 /* try reading again */
236       }
237       break;
238    }
239
240    dev->state |= ST_READ;
241    return 1; 
242 }