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