2 * Routines to acquire and release a device for read/write
4 * Kern Sibbald, August MMII
9 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
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.
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.
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,
28 #include "bacula.h" /* pull in global headers */
29 #include "stored.h" /* pull in Storage Deamon headers */
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.
37 * Returns: 0 if failed for any reason
40 int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
44 new_lock_device_state(dev, BST_DOING_ACQUIRE);
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);
52 dev->state &= ~ST_LABEL; /* force reread of label */
53 block_device(dev, BST_DOING_ACQUIRE);
55 stat = ready_dev_for_read(jcr, dev, block);
61 new_unlock_device(dev);
66 * Acquire device for writing. We permit multiple writers.
67 * If this is the first one, we read the label.
69 * Returns: 0 if failed for any reason
72 int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
77 new_lock_device_state(dev, BST_DOING_ACQUIRE);
79 Dmsg1(190, "acquire_append device is %s\n", dev_is_tape(dev)?"tape":"disk");
82 if (dev->state & ST_APPEND) {
84 * Device already in append mode
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
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));
100 new_unlock_device(dev);
103 /* Wrong tape mounted, release it, then fall through to get correct one */
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));
112 new_unlock_device(dev);
115 ASSERT(dev->num_writers == 0);
120 block_device(dev, BST_DOING_ACQUIRE);
122 if (!mount_next_write_volume(jcr, dev, block, release)) {
123 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
130 new_unlock_device(dev);
140 if (dev->num_writers > 1) {
141 Dmsg2(0, "Hey!!!! There are %d writers on device %s\n", dev->num_writers,
144 if (jcr->NumVolumes == 0) {
147 attach_jcr_to_device(dev, jcr); /* attach jcr to device */
149 new_unlock_device(dev);
150 return 1; /* got it */
154 * This job is done, so release the device. From a Unix standpoint,
155 * the device remains open.
158 int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
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) {
173 /******FIXME**** send read volume usage statistics to director */
175 } else if (dev->num_writers > 0) {
177 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
178 if (dev->num_writers == 0) {
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 */
187 if (!dev_is_tape(dev) || !(dev->capabilities & CAP_ALWAYSOPEN)) {
188 if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
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 */
200 Jmsg1(jcr, M_ERROR, 0, _("BAD ERROR: release_device %s not in use.\n"), dev_name(dev));
202 detach_jcr_from_device(dev, jcr);
206 new_unlock_device(dev);
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
217 * Returns 0 on failure
218 * Returns 1 on success
220 int ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
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));
229 Dmsg1(129, "open_dev %s OK\n", dev_name(dev));
233 if (job_cancelled(jcr)) {
234 Mmsg0(&dev->errmsg, _("Job cancelled.\n"));
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));
241 switch (read_dev_volume_label(jcr, dev, block)) {
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));
251 /* Mount a specific volume and no other */
252 if (!dir_ask_sysop_to_mount_volume(jcr, dev)) {
253 return 0; /* error return */
255 continue; /* try reading again */
260 dev->state |= ST_READ;